Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(453)

Unified Diff: src/messages.js

Issue 1137683003: Only record one in n line endings to save space. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix false detection of exotic newlines Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/macros.py ('k') | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/messages.js
diff --git a/src/messages.js b/src/messages.js
index 8d79dac43225931eb1800bde5f2b54feead2f92b..3ff69fb61d2377db7760f2ff5076dd2740badaad 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -40,6 +40,7 @@ var InternalArray = utils.InternalArray;
var ObjectDefineProperty = utils.ObjectDefineProperty;
var ArrayJoin;
+var MathFloor;
var ObjectToString;
var StringCharAt;
var StringIndexOf;
@@ -47,6 +48,7 @@ var StringSubstring;
utils.Import(function(from) {
ArrayJoin = from.ArrayJoin;
+ MathFloor = from.MathFloor;
ObjectToString = from.ObjectToString;
StringCharAt = from.StringCharAt;
StringIndexOf = from.StringIndexOf;
@@ -203,41 +205,94 @@ function GetSourceLine(message) {
return location.sourceText();
}
+
+function Newlines(source, from, to, reduction) {
+ var newLines = new InternalArray();
+ if (!IS_STRING(source)) return newLines;
+
+ var length = source.length;
+ for (; from < to && from < length && newLines.length < reduction - 1
+ ; ++from) {
+ var c = %_StringCharCodeAt(source, from);
+ if (c == ASCII_CR) {
+ if (from < length - 1) {
+ var c2 = %_StringCharCodeAt(source, from + 1);
+ if (c2 == ASCII_NL) {
+ from++; // CR-LF counts as one newline.
+ }
+ }
+ newLines.push(from);
+ } else if (c == ASCII_NL) {
+ newLines.push(from);
+ }
+ }
+ // End-of-file virtual end-of-line.
+ if (to >= length) {
+ var last = length != 0 ? %_StringCharCodeAt(source, length - 1) : 0;
+ if (last != ASCII_NL && last != ASCII_CR) newLines.push(source.length - 1);
+ }
+ return newLines;
+}
+
+
+function ScriptLineEnd(line) {
+ if (line < 0) return -1;
+ var source = this.source;
+ if (!IS_STRING(source)) return -1;
+ var line_ends = this.line_ends;
+ var reduction = line_ends[REDUCTION_INDEX];
+ var index = MathFloor(line / reduction) + FIRST_LINE_END_INDEX;
+ if (index >= line_ends.length) return -1;
+ var position = line_ends[index];
+ if (line % reduction == 0) return position;
+ var lines = Newlines(source, position + 1, source.length, reduction);
+ return lines[line % reduction - 1];
+}
+
+
/**
* Find a line number given a specific source position.
* @param {number} position The source position.
- * @return {number} 0 if input too small, -1 if input too large,
- else the line number.
+ * @return {number} -1 if position too large, else the 0-based line number.
*/
function ScriptLineFromPosition(position) {
- var lower = 0;
- var upper = this.lineCount() - 1;
+ var source = this.source;
+ if (!IS_STRING(source)) return -1;
+
var line_ends = this.line_ends;
+ var lower = FIRST_LINE_END_INDEX;
+ var upper = line_ends.length - 1;
- // We'll never find invalid positions so bail right away.
- if (position > line_ends[upper]) {
- return -1;
- }
+ var reduction = line_ends[REDUCTION_INDEX];
+ // This '>' would normally be a '>=', but due to {}-less 'with' statements in
+ // top-level code we sometimes encounter code positions that are one character
+ // after the end of the source. See comment in Rewriter::Rewrite.
+ if (position > source.length) return -1;
- // This means we don't have to safe-guard indexing line_ends[i - 1].
- if (position <= line_ends[0]) {
- return 0;
- }
+ var index = 0;
// Binary search to find line # from position range.
- while (upper >= 1) {
- var i = (lower + upper) >> 1;
-
- if (position > line_ends[i]) {
- lower = i + 1;
- } else if (position <= line_ends[i - 1]) {
- upper = i - 1;
- } else {
- return i;
+ if (position > line_ends[upper]) {
+ index = upper;
+ } else {
+ // Invariant: position > line_ends[lower]
+ // Invariant: position <= line_ends[upper]
+ while (lower + 1 < upper) {
+ // Since they differ by at least 2, i must be different from both
+ // upper or lower.
+ var i = (lower + upper) >> 1;
+ if (position > line_ends[i]) {
+ lower = i;
+ } else {
+ upper = i;
+ }
}
+ index = lower;
}
- return -1;
+ var line = (index - FIRST_LINE_END_INDEX) * reduction;
+ return line +
+ Newlines(source, line_ends[index] + 1, position, reduction).length;
}
/**
@@ -250,14 +305,19 @@ function ScriptLineFromPosition(position) {
*/
function ScriptLocationFromPosition(position,
include_resource_offset) {
+ // Get zero-based line number.
var line = this.lineFromPosition(position);
if (line == -1) return null;
// Determine start, end and column.
- var line_ends = this.line_ends;
- var start = line == 0 ? 0 : line_ends[line - 1] + 1;
- var end = line_ends[line];
- if (end > 0 && %_CallFunction(this.source, end - 1, StringCharAt) == '\r') {
+ var start = this.lineEnd(line) + 1;
+ // End will be used for substr, so make it non-inclusive.
+ var end = this.lineEnd(line + 1) + 1;
+ if (end > this.source.length) end = this.source.length;
+ // But trim the newline if there is one (there might not be at EOF).
+ while (end > start) {
+ var trim_char = %_CallFunction(this.source, end - 1, StringCharAt);
+ if (trim_char != '\n' && trim_char != '\r') break;
end--;
}
var column = position - start;
@@ -317,7 +377,7 @@ function ScriptLocationFromLine(opt_line, opt_column, opt_offset_position) {
}
return this.locationFromPosition(
- this.line_ends[offset_line + line - 1] + 1 + column); // line > 0 here.
+ this.lineEnd(offset_line + line) + 1 + column); // line > 0 here.
}
}
@@ -351,15 +411,14 @@ function ScriptSourceSlice(opt_from_line, opt_to_line) {
return null;
}
- var line_ends = this.line_ends;
- var from_position = from_line == 0 ? 0 : line_ends[from_line - 1] + 1;
- var to_position = to_line == 0 ? 0 : line_ends[to_line - 1] + 1;
+ var from_position = this.lineEnd(from_line) + 1;
+ var to_position = this.lineEnd(to_line) + 1;
// Return a source slice with line numbers re-adjusted to the resource.
return new SourceSlice(this,
from_line + this.line_offset,
to_line + this.line_offset,
- from_position, to_position);
+ from_position, to_position);
}
@@ -377,9 +436,8 @@ function ScriptSourceLine(opt_line) {
}
// Return the source line.
- var line_ends = this.line_ends;
- var start = line == 0 ? 0 : line_ends[line - 1] + 1;
- var end = line_ends[line];
+ var start = this.lineEnd(line) + 1;
+ var end = this.lineEnd(line + 1);
return %_CallFunction(this.source, start, end, StringSubstring);
}
@@ -391,7 +449,7 @@ function ScriptSourceLine(opt_line) {
*/
function ScriptLineCount() {
// Return number of source lines.
- return this.line_ends.length;
+ return this.line_ends[NUMBER_OF_LINES_INDEX];
}
@@ -426,7 +484,8 @@ utils.SetUpLockedPrototype(Script, [
"sourceSlice", ScriptSourceSlice,
"sourceLine", ScriptSourceLine,
"lineCount", ScriptLineCount,
- "nameOrSourceURL", ScriptNameOrSourceURL
+ "nameOrSourceURL", ScriptNameOrSourceURL,
+ "lineEnd", ScriptLineEnd
]
);
« no previous file with comments | « src/macros.py ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698