Index: src/isolate.cc |
diff --git a/src/isolate.cc b/src/isolate.cc |
index 624f2a8d93be453c855f272ef982d08cb69d7cf8..3a9b93a42d0645fd7edb6f582708fd8b8f2ad658 100644 |
--- a/src/isolate.cc |
+++ b/src/isolate.cc |
@@ -315,21 +315,7 @@ void Isolate::PushStackTraceAndDie(unsigned int magic, void* ptr1, void* ptr2, |
base::OS::Abort(); |
} |
-static Handle<FixedArray> MaybeGrow(Isolate* isolate, |
- Handle<FixedArray> elements, |
- int cur_position, int new_size) { |
- if (new_size > elements->length()) { |
- int new_capacity = JSObject::NewElementsCapacity(elements->length()); |
- Handle<FixedArray> new_elements = |
- isolate->factory()->NewFixedArrayWithHoles(new_capacity); |
- for (int i = 0; i < cur_position; i++) { |
- new_elements->set(i, elements->get(i)); |
- } |
- elements = new_elements; |
- } |
- DCHECK(new_size <= elements->length()); |
- return elements; |
-} |
+namespace { |
class StackTraceHelper { |
public: |
@@ -435,8 +421,6 @@ class StackTraceHelper { |
bool encountered_strict_function_; |
}; |
-namespace { |
- |
// TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the |
// receiver in RegExp constructor frames. |
Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) { |
@@ -444,35 +428,36 @@ Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) { |
? Handle<Object>::cast(isolate->factory()->undefined_value()) |
: in; |
} |
+ |
+bool GetStackTraceLimit(Isolate* isolate, int* result) { |
+ Handle<JSObject> error = isolate->error_function(); |
+ |
+ Handle<String> key = isolate->factory()->stackTraceLimit_string(); |
+ Handle<Object> stack_trace_limit = JSReceiver::GetDataProperty(error, key); |
+ if (!stack_trace_limit->IsNumber()) return false; |
+ |
+ // Ensure that limit is not negative. |
+ *result = Max(FastD2IChecked(stack_trace_limit->Number()), 0); |
+ return true; |
} |
+} // namespace |
+ |
Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object, |
FrameSkipMode mode, |
Handle<Object> caller) { |
DisallowJavascriptExecution no_js(this); |
- // Get stack trace limit. |
- Handle<JSObject> error = error_function(); |
- Handle<String> stackTraceLimit = |
- factory()->InternalizeUtf8String("stackTraceLimit"); |
- DCHECK(!stackTraceLimit.is_null()); |
- Handle<Object> stack_trace_limit = |
- JSReceiver::GetDataProperty(error, stackTraceLimit); |
- if (!stack_trace_limit->IsNumber()) return factory()->undefined_value(); |
- int limit = FastD2IChecked(stack_trace_limit->Number()); |
- limit = Max(limit, 0); // Ensure that limit is not negative. |
- |
- int initial_size = Min(limit, 10); |
- Handle<FixedArray> elements = |
- factory()->NewFixedArrayWithHoles(initial_size * 4 + 1); |
+ int limit; |
+ if (!GetStackTraceLimit(this, &limit)) return factory()->undefined_value(); |
+ |
+ const int initial_size = Min(limit, 10); |
+ Handle<FrameArray> elements = factory()->NewFrameArray(initial_size); |
StackTraceHelper helper(this, mode, caller); |
- // First element is reserved to store the number of sloppy frames. |
- int cursor = 1; |
- int frames_seen = 0; |
- for (StackFrameIterator iter(this); !iter.done() && frames_seen < limit; |
- iter.Advance()) { |
+ for (StackFrameIterator iter(this); |
+ !iter.done() && elements->FrameCount() < limit; iter.Advance()) { |
StackFrame* frame = iter.frame(); |
switch (frame->type()) { |
@@ -502,14 +487,11 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object, |
recv = handle(heap()->call_site_constructor_symbol(), this); |
} |
} |
- Handle<Smi> offset(Smi::FromInt(frames[i].code_offset()), this); |
- |
- elements = MaybeGrow(this, elements, cursor, cursor + 4); |
- elements->set(cursor++, *TheHoleToUndefined(this, recv)); |
- elements->set(cursor++, *fun); |
- elements->set(cursor++, *abstract_code); |
- elements->set(cursor++, *offset); |
- frames_seen++; |
+ const int offset = frames[i].code_offset(); |
+ |
+ elements = FrameArray::AppendJSFrame(elements, |
+ TheHoleToUndefined(this, recv), |
+ fun, abstract_code, offset); |
} |
} break; |
@@ -534,39 +516,39 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object, |
recv = handle(exit_frame->receiver(), this); |
} |
- elements = MaybeGrow(this, elements, cursor, cursor + 4); |
- elements->set(cursor++, *recv); |
- elements->set(cursor++, *fun); |
- elements->set(cursor++, *code); |
- elements->set(cursor++, Smi::FromInt(offset)); |
- frames_seen++; |
+ elements = FrameArray::AppendJSFrame( |
+ elements, recv, fun, Handle<AbstractCode>::cast(code), offset); |
} break; |
case StackFrame::WASM: { |
WasmFrame* wasm_frame = WasmFrame::cast(frame); |
+ Handle<Object> wasm_object = handle(wasm_frame->wasm_obj(), this); |
+ const int wasm_function_index = wasm_frame->function_index(); |
Code* code = wasm_frame->unchecked_code(); |
Handle<AbstractCode> abstract_code = |
Handle<AbstractCode>(AbstractCode::cast(code), this); |
- int offset = |
+ const int offset = |
static_cast<int>(wasm_frame->pc() - code->instruction_start()); |
- elements = MaybeGrow(this, elements, cursor, cursor + 4); |
- elements->set(cursor++, wasm_frame->wasm_obj()); |
- elements->set(cursor++, Smi::FromInt(wasm_frame->function_index())); |
- elements->set(cursor++, *abstract_code); |
- elements->set(cursor++, Smi::FromInt(offset)); |
- frames_seen++; |
+ |
+ // TODO(wasm): The wasm object returned by the WasmFrame should always |
+ // be a wasm object. |
+ DCHECK(wasm::IsWasmObject(*wasm_object) || |
+ wasm_object->IsUndefined(this)); |
+ |
+ elements = FrameArray::AppendWasmFrame( |
+ elements, wasm_object, wasm_function_index, abstract_code, offset); |
} break; |
default: |
break; |
} |
} |
- elements->set(0, Smi::FromInt(helper.sloppy_frames())); |
- elements->Shrink(cursor); |
- Handle<JSArray> result = factory()->NewJSArrayWithElements(elements); |
- result->set_length(Smi::FromInt(cursor)); |
+ |
+ elements->SetSloppyFrameCount(helper.sloppy_frames()); |
+ elements->ShrinkToFit(); |
+ |
// TODO(yangguo): Queue this structured stack trace for preprocessing on GC. |
- return result; |
+ return factory()->NewJSArrayWithElements(elements); |
} |
MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace( |
@@ -773,19 +755,6 @@ class CaptureStackTraceHelper { |
Handle<String> constructor_key_; |
}; |
- |
-int PositionFromStackTrace(Handle<FixedArray> elements, int index) { |
- DisallowHeapAllocation no_gc; |
- Object* maybe_code = elements->get(index + 2); |
- if (maybe_code->IsSmi()) { |
- return Smi::cast(maybe_code)->value(); |
- } else { |
- AbstractCode* abstract_code = AbstractCode::cast(maybe_code); |
- int code_offset = Smi::cast(elements->get(index + 3))->value(); |
- return abstract_code->SourcePosition(code_offset); |
- } |
-} |
- |
Handle<JSArray> Isolate::CaptureCurrentStackTrace( |
int frame_limit, StackTrace::StackTraceOptions options) { |
DisallowJavascriptExecution no_js(this); |
@@ -1531,22 +1500,25 @@ bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target, |
if (!property->IsJSArray()) return false; |
Handle<JSArray> simple_stack_trace = Handle<JSArray>::cast(property); |
- Handle<FixedArray> elements(FixedArray::cast(simple_stack_trace->elements())); |
- int elements_limit = Smi::cast(simple_stack_trace->length())->value(); |
+ Handle<FrameArray> elements(FrameArray::cast(simple_stack_trace->elements())); |
- for (int i = 1; i < elements_limit; i += 4) { |
- Handle<Object> fun_obj = handle(elements->get(i + 1), this); |
- if (fun_obj->IsSmi()) { |
+ const int frame_count = elements->FrameCount(); |
+ for (int i = 0; i < frame_count; i++) { |
+ if (elements->IsWasmFrame(i)) { |
// TODO(clemensh): handle wasm frames |
return false; |
} |
- Handle<JSFunction> fun = Handle<JSFunction>::cast(fun_obj); |
+ |
+ Handle<JSFunction> fun = handle(elements->Function(i), this); |
if (!fun->shared()->IsSubjectToDebugging()) continue; |
Object* script = fun->shared()->script(); |
if (script->IsScript() && |
!(Script::cast(script)->source()->IsUndefined(this))) { |
- int pos = PositionFromStackTrace(elements, i); |
+ AbstractCode* abstract_code = elements->Code(i); |
+ const int code_offset = elements->Offset(i)->value(); |
+ const int pos = abstract_code->SourcePosition(code_offset); |
+ |
Handle<Script> casted_script(Script::cast(script)); |
*target = MessageLocation(casted_script, pos, pos + 1); |
return true; |