Index: src/handles.cc |
diff --git a/src/handles.cc b/src/handles.cc |
index 1364951b714ceb2c87731312f77ff1427ad98f5f..3dfb886e99085e8fdf762880e22c61f4f78b24af 100644 |
--- a/src/handles.cc |
+++ b/src/handles.cc |
@@ -37,6 +37,7 @@ |
#include "global-handles.h" |
#include "natives.h" |
#include "runtime.h" |
+#include "string-search.h" |
#include "stub-cache.h" |
namespace v8 { |
@@ -508,43 +509,50 @@ void InitScriptLineEnds(Handle<Script> script) { |
} |
-Handle<FixedArray> CalculateLineEnds(Handle<String> src, |
- bool with_imaginary_last_new_line) { |
- const int src_len = src->length(); |
- Handle<String> new_line = Factory::NewStringFromAscii(CStrVector("\n")); |
+template <typename SourceChar> |
+static void CalculateLineEnds(List<int>* line_ends, |
+ Vector<const SourceChar> src, |
+ bool with_last_line) { |
+ const int src_len = src.length(); |
+ StringSearch<char, SourceChar> search(CStrVector("\n")); |
- // Pass 1: Identify line count. |
- int line_count = 0; |
+ // Find and record line ends. |
int position = 0; |
while (position != -1 && position < src_len) { |
- position = Runtime::StringMatch(src, new_line, position); |
+ position = search.Search(src, position); |
if (position != -1) { |
+ line_ends->Add(position); |
position++; |
- } |
- if (position != -1) { |
- line_count++; |
- } else if (with_imaginary_last_new_line) { |
+ } else if (with_last_line) { |
// Even if the last line misses a line end, it is counted. |
- line_count++; |
+ line_ends->Add(src_len); |
+ return; |
} |
} |
+} |
- // Pass 2: Fill in line ends positions |
- Handle<FixedArray> array = Factory::NewFixedArray(line_count); |
- int array_index = 0; |
- position = 0; |
- while (position != -1 && position < src_len) { |
- position = Runtime::StringMatch(src, new_line, position); |
- if (position != -1) { |
- array->set(array_index++, Smi::FromInt(position++)); |
- } else if (with_imaginary_last_new_line) { |
- // If the script does not end with a line ending add the final end |
- // position as just past the last line ending. |
- array->set(array_index++, Smi::FromInt(src_len)); |
+ |
+Handle<FixedArray> CalculateLineEnds(Handle<String> src, |
+ bool with_last_line) { |
+ src = FlattenGetString(src); |
+ // Rough estimate of line count based on a roughly estimated average |
+ // length of (unpacked) code. |
+ int line_count_estimate = src->length() >> 4; |
+ List<int> line_ends(line_count_estimate); |
+ { |
+ AssertNoAllocation no_heap_allocation; // ensure vectors stay valid. |
+ // Dispatch on type of strings. |
+ if (src->IsAsciiRepresentation()) { |
+ CalculateLineEnds(&line_ends, src->ToAsciiVector(), with_last_line); |
+ } else { |
+ CalculateLineEnds(&line_ends, src->ToUC16Vector(), with_last_line); |
} |
} |
- ASSERT(array_index == line_count); |
- |
+ int line_count = line_ends.length(); |
+ Handle<FixedArray> array = Factory::NewFixedArray(line_count); |
+ for (int i = 0; i < line_count; i++) { |
+ array->set(i, Smi::FromInt(line_ends[i])); |
+ } |
return array; |
} |
@@ -556,11 +564,11 @@ int GetScriptLineNumber(Handle<Script> script, int code_pos) { |
FixedArray* line_ends_array = FixedArray::cast(script->line_ends()); |
const int line_ends_len = line_ends_array->length(); |
- if (!line_ends_len) |
- return -1; |
+ if (!line_ends_len) return -1; |
- if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) |
+ if ((Smi::cast(line_ends_array->get(0)))->value() >= code_pos) { |
return script->line_offset()->value(); |
+ } |
int left = 0; |
int right = line_ends_len; |