Commit 1a9dc2d0 authored by kasperl@chromium.org's avatar kasperl@chromium.org

Move InitLineEnds and GetLineNumber to handles.cc to avoid

issues with a raw this pointer and GC.

Fix issue with FlattenString where we may keep a StringShape
alive across a GC.
Review URL: http://codereview.chromium.org/43020

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1481 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 3f3ed140
......@@ -275,9 +275,10 @@ const AccessorDescriptor Accessors::ScriptType = {
Object* Accessors::ScriptGetLineEnds(Object* object, void*) {
Object* script = JSValue::cast(object)->value();
Script::cast(script)->InitLineEnds();
return Script::cast(script)->line_ends();
HandleScope scope;
Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
InitScriptLineEnds(script);
return script->line_ends();
}
......
......@@ -317,7 +317,7 @@ bool Compiler::CompileLazy(Handle<SharedFunctionInfo> shared,
// the line number is not for free.
if (Logger::is_enabled() || OProfileAgent::is_enabled()) {
if (script->name()->IsString()) {
int line_num = script->GetLineNumber(start_position);
int line_num = GetScriptLineNumber(script, start_position);
if (line_num > 0) {
line_num += script->line_offset()->value() + 1;
}
......
......@@ -186,9 +186,7 @@ void TransformToFastProperties(Handle<JSObject> object,
void FlattenString(Handle<String> string) {
StringShape shape(*string);
if (string->IsFlat(shape)) return;
CALL_HEAP_FUNCTION_VOID(string->TryFlatten(shape));
CALL_HEAP_FUNCTION_VOID(string->TryFlattenIfNotFlat(StringShape(*string)));
ASSERT(string->IsFlat(StringShape(*string)));
}
......@@ -343,6 +341,78 @@ Handle<JSValue> GetScriptWrapper(Handle<Script> script) {
}
// Init line_ends array with code positions of line ends inside script
// source.
void InitScriptLineEnds(Handle<Script> script) {
if (!script->line_ends()->IsUndefined()) return;
if (!script->source()->IsString()) {
ASSERT(script->source()->IsUndefined());
script->set_line_ends(*(Factory::NewJSArray(0)));
ASSERT(script->line_ends()->IsJSArray());
return;
}
Handle<String> src(String::cast(script->source()));
const int src_len = src->length();
Handle<String> new_line = Factory::NewStringFromAscii(CStrVector("\n"));
// Pass 1: Identify line count.
int line_count = 0;
int position = 0;
while (position != -1 && position < src_len) {
position = Runtime::StringMatch(src, new_line, position);
if (position != -1) {
position++;
}
// Even if the last line misses a line end, it is counted.
line_count++;
}
// 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 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(position != -1 ? position++ : src_len));
}
ASSERT(array_index == line_count);
Handle<JSArray> object = Factory::NewJSArrayWithElements(array);
script->set_line_ends(*object);
ASSERT(script->line_ends()->IsJSArray());
}
// Convert code position into line number.
int GetScriptLineNumber(Handle<Script> script, int code_pos) {
InitScriptLineEnds(script);
AssertNoAllocation no_allocation;
JSArray* line_ends_array = JSArray::cast(script->line_ends());
const int line_ends_len = (Smi::cast(line_ends_array->length()))->value();
int line = -1;
if (line_ends_len > 0 &&
code_pos <= (Smi::cast(line_ends_array->GetElement(0)))->value()) {
line = 0;
} else {
for (int i = 1; i < line_ends_len; ++i) {
if ((Smi::cast(line_ends_array->GetElement(i - 1)))->value() < code_pos &&
code_pos <= (Smi::cast(line_ends_array->GetElement(i)))->value()) {
line = i;
break;
}
}
}
return line != -1 ? line + script->line_offset()->value() : line;
}
// Compute the property keys from the interceptor.
v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver,
Handle<JSObject> object) {
......
......@@ -225,6 +225,10 @@ Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray>,
// if none exists.
Handle<JSValue> GetScriptWrapper(Handle<Script> script);
// Script line number computations.
void InitScriptLineEnds(Handle<Script> script);
int GetScriptLineNumber(Handle<Script> script, int code_position);
// Computes the enumerable keys from interceptors. Used for debug mirrors and
// by GetKeysInFixedArrayFor below.
v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver,
......
......@@ -6959,76 +6959,6 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
}
// Init line_ends array with code positions of line ends inside script source
void Script::InitLineEnds() {
if (!line_ends()->IsUndefined()) return;
if (!source()->IsString()) {
ASSERT(source()->IsUndefined());
set_line_ends(*(Factory::NewJSArray(0)));
ASSERT(line_ends()->IsJSArray());
return;
}
Handle<String> src(String::cast(source()));
const int src_len = src->length();
Handle<String> new_line = Factory::NewStringFromAscii(CStrVector("\n"));
// Pass 1: Identify line count
int line_count = 0;
int position = 0;
while (position != -1 && position < src_len) {
position = Runtime::StringMatch(src, new_line, position);
if (position != -1) {
position++;
}
// Even if the last line misses a line end, it is counted
line_count++;
}
// 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 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(position != -1 ? position++ : src_len));
}
ASSERT(array_index == line_count);
Handle<JSArray> object = Factory::NewJSArrayWithElements(array);
set_line_ends(*object);
ASSERT(line_ends()->IsJSArray());
}
// Convert code position into line number
int Script::GetLineNumber(int code_pos) {
InitLineEnds();
JSArray* line_ends_array = JSArray::cast(line_ends());
const int line_ends_len = (Smi::cast(line_ends_array->length()))->value();
int line = -1;
if (line_ends_len > 0 &&
code_pos <= (Smi::cast(line_ends_array->GetElement(0)))->value()) {
line = 0;
} else {
for (int i = 1; i < line_ends_len; ++i) {
if ((Smi::cast(line_ends_array->GetElement(i - 1)))->value() < code_pos &&
code_pos <= (Smi::cast(line_ends_array->GetElement(i)))->value()) {
line = i;
break;
}
}
}
return line != -1 ? line + line_offset()->value() : line;
}
// Check if there is a break point at this code position.
bool DebugInfo::HasBreakPoint(int code_position) {
// Get the break point info object for this code position.
......
......@@ -2576,9 +2576,6 @@ class Script: public Struct {
void ScriptVerify();
#endif
void InitLineEnds();
int GetLineNumber(int code_position);
static const int kSourceOffset = HeapObject::kHeaderSize;
static const int kNameOffset = kSourceOffset + kPointerSize;
static const int kLineOffsetOffset = kNameOffset + kPointerSize;
......
......@@ -312,7 +312,7 @@ TEST(Regression236) {
Handle<Script> script = Factory::NewScript(Factory::empty_string());
script->set_source(Heap::undefined_value());
CHECK_EQ(-1, script->GetLineNumber(0));
CHECK_EQ(-1, script->GetLineNumber(100));
CHECK_EQ(-1, script->GetLineNumber(-1));
CHECK_EQ(-1, GetScriptLineNumber(script, 0));
CHECK_EQ(-1, GetScriptLineNumber(script, 100));
CHECK_EQ(-1, GetScriptLineNumber(script, -1));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment