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

View File

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