Bug 1083913: Make TokenStream::linebase an offset, not a pointer into nothingness. r=shu

This commit is contained in:
Jim Blandy 2014-11-12 14:51:40 -08:00
parent 29234315de
commit 8e95cb1c57
2 changed files with 32 additions and 38 deletions

View File

@ -283,7 +283,6 @@ TokenStream::SourceCoords::lineNumAndColumnIndex(uint32_t offset, uint32_t *line
#pragma warning(disable:4351)
#endif
// Initialize members that aren't initialized in |init|.
TokenStream::TokenStream(ExclusiveContext *cx, const ReadOnlyCompileOptions &options,
const char16_t *base, size_t length, StrictModeGetter *smg)
: srcCoords(cx, options.lineno),
@ -293,8 +292,8 @@ TokenStream::TokenStream(ExclusiveContext *cx, const ReadOnlyCompileOptions &opt
lookahead(),
lineno(options.lineno),
flags(),
linebase(base - options.column),
prevLinebase(nullptr),
linebase(0),
prevLinebase(size_t(-1)),
userbuf(cx, base, length, options.column),
filename(options.filename()),
displayURL_(nullptr),
@ -304,11 +303,6 @@ TokenStream::TokenStream(ExclusiveContext *cx, const ReadOnlyCompileOptions &opt
mutedErrors(options.mutedErrors()),
strictModeGetter(smg)
{
// Column numbers are computed as offsets from the current line's base, so the
// initial line's base must be included in the buffer. linebase and userbuf
// were adjusted above, and if we are starting tokenization part way through
// this line then adjust the next character.
// Nb: the following tables could be static, but initializing them here is
// much easier. Don't worry, the time to initialize them for each
// TokenStream is trivial. See bug 639420.
@ -364,9 +358,9 @@ MOZ_ALWAYS_INLINE void
TokenStream::updateLineInfoForEOL()
{
prevLinebase = linebase;
linebase = userbuf.addressOfNextRawChar();
linebase = userbuf.offset();
lineno++;
srcCoords.add(lineno, userbuf.offset());
srcCoords.add(lineno, linebase);
}
MOZ_ALWAYS_INLINE void
@ -451,9 +445,9 @@ TokenStream::ungetChar(int32_t c)
if (!userbuf.atStart())
userbuf.matchRawCharBackwards('\r');
MOZ_ASSERT(prevLinebase); // we should never get more than one EOL char
MOZ_ASSERT(prevLinebase != size_t(-1)); // we should never get more than one EOL char
linebase = prevLinebase;
prevLinebase = nullptr;
prevLinebase = size_t(-1);
lineno--;
} else {
MOZ_ASSERT(userbuf.peekRawChar() == c);
@ -494,10 +488,10 @@ TokenStream::peekChars(int n, char16_t *cp)
return i == n;
}
const char16_t *
TokenStream::TokenBuf::findEOLMax(const char16_t *p, size_t max)
size_t
TokenStream::TokenBuf::findEOLMax(size_t start, size_t max)
{
MOZ_ASSERT(base_ <= p && p <= limit_);
const char16_t *p = rawCharPtrAt(start);
size_t n = 0;
while (true) {
@ -505,11 +499,11 @@ TokenStream::TokenBuf::findEOLMax(const char16_t *p, size_t max)
break;
if (n >= max)
break;
n++;
if (TokenBuf::isRawEOLChar(*p++))
break;
n++;
}
return p;
return start + n;
}
void
@ -675,8 +669,6 @@ TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigne
// means that any error involving a multi-line token (e.g. an unterminated
// multi-line string literal) won't have a context printed.
if (offset != NoOffset && err.report.lineno == lineno && !callerFilename) {
const char16_t *tokenStart = userbuf.rawCharPtrAt(offset);
// We show only a portion (a "window") of the line around the erroneous
// token -- the first char in the token, plus |windowRadius| chars
// before it and |windowRadius - 1| chars after it. This is because
@ -684,20 +676,22 @@ TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigne
// helpful, and (b) can waste a lot of memory. See bug 634444.
static const size_t windowRadius = 60;
// Truncate at the front if necessary.
const char16_t *windowBase = (linebase + windowRadius < tokenStart)
? tokenStart - windowRadius
: linebase;
uint32_t windowOffset = tokenStart - windowBase;
// The window must start within the current line, no earlier than
// windowRadius characters before offset.
size_t windowStart = (offset - linebase > windowRadius) ?
offset - windowRadius :
linebase;
// Find EOL, or truncate at the back if necessary.
const char16_t *windowLimit = userbuf.findEOLMax(tokenStart, windowRadius);
size_t windowLength = windowLimit - windowBase;
// The window must end within the current line, no later than
// windowRadius after offset.
size_t windowEnd = userbuf.findEOLMax(offset, windowRadius);
size_t windowLength = windowEnd - windowStart;
MOZ_ASSERT(windowLength <= windowRadius * 2);
// Create the windowed strings.
StringBuffer windowBuf(cx);
if (!windowBuf.append(windowBase, windowLength) || !windowBuf.append((char16_t)0))
if (!windowBuf.append(userbuf.rawCharPtrAt(windowStart), windowLength) ||
!windowBuf.append((char16_t)0))
return false;
// Unicode and char versions of the window into the offending source
@ -711,8 +705,8 @@ TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigne
if (!err.report.linebuf)
return false;
err.report.tokenptr = err.report.linebuf + windowOffset;
err.report.uctokenptr = err.report.uclinebuf + windowOffset;
err.report.tokenptr = err.report.linebuf + (offset - windowStart);
err.report.uctokenptr = err.report.uclinebuf + (offset - windowStart);
}
if (cx->isJSContext())

View File

@ -266,7 +266,7 @@ class MOZ_STACK_CLASS TokenStream
const CharBuffer &getTokenbuf() const { return tokenbuf; }
const char *getFilename() const { return filename; }
unsigned getLineno() const { return lineno; }
unsigned getColumn() const { return userbuf.addressOfNextRawChar() - linebase - 1; }
unsigned getColumn() const { return userbuf.offset() - linebase - 1; }
bool getMutedErrors() const { return mutedErrors; }
JSVersion versionNumber() const { return VersionNumber(options().version); }
JSVersion versionWithFlags() const { return options().version; }
@ -517,8 +517,8 @@ class MOZ_STACK_CLASS TokenStream
const char16_t *buf;
Flags flags;
unsigned lineno;
const char16_t *linebase;
const char16_t *prevLinebase;
size_t linebase;
size_t prevLinebase;
Token currentToken;
unsigned lookahead;
Token lookaheadTokens[maxLookahead];
@ -743,9 +743,9 @@ class MOZ_STACK_CLASS TokenStream
return c == '\n' || c == '\r' || c == LINE_SEPARATOR || c == PARA_SEPARATOR;
}
// Finds the next EOL, but stops once 'max' characters have been scanned
// (*including* the starting char16_t).
const char16_t *findEOLMax(const char16_t *p, size_t max);
// Returns the offset of the next EOL, but stops once 'max' characters
// have been scanned (*including* the char at startOffset).
size_t findEOLMax(size_t startOffset, size_t max);
private:
const char16_t *base_; // base of buffer
@ -810,8 +810,8 @@ class MOZ_STACK_CLASS TokenStream
unsigned lookahead; // count of lookahead tokens
unsigned lineno; // current line number
Flags flags; // flags -- see above
const char16_t *linebase; // start of current line; points into userbuf
const char16_t *prevLinebase; // start of previous line; nullptr if on the first line
size_t linebase; // start of current line
size_t prevLinebase; // start of previous line; size_t(-1) if on the first line
TokenBuf userbuf; // user input buffer
const char *filename; // input filename or null
mozilla::UniquePtr<char16_t[], JS::FreePolicy> displayURL_; // the user's requested source URL or null