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

Unified Diff: src/isolate.cc

Issue 2230953002: Use a custom Struct for stack trace storage (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Tweaks Created 4 years, 4 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/isolate.h ('k') | src/messages.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/isolate.cc
diff --git a/src/isolate.cc b/src/isolate.cc
index a434db3abe04ea3a263723d0398e1a76ba3def44..b41dd37909a6512eb23c4d0a8280f2a75abd7615 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -356,21 +356,16 @@ class StackTraceHelper {
break;
}
encountered_strict_function_ = false;
- sloppy_frames_ = 0;
}
// The stack trace API should not expose receivers and function
// objects on frames deeper than the top-most one with a strict mode
- // function. The number of sloppy frames is stored as first element in
- // the result array.
- void CountSloppyFrames(JSFunction* fun) {
+ // function.
+ bool IsStrictFrame(JSFunction* fun) {
if (!encountered_strict_function_) {
- if (is_strict(fun->shared()->language_mode())) {
- encountered_strict_function_ = true;
- } else {
- sloppy_frames_++;
- }
+ encountered_strict_function_ = is_strict(fun->shared()->language_mode());
}
+ return encountered_strict_function_;
}
// Determines whether the given stack frame should be displayed in a stack
@@ -380,8 +375,6 @@ class StackTraceHelper {
IsInSameSecurityContext(fun);
}
- int sloppy_frames() const { return sloppy_frames_; }
-
private:
// This mechanism excludes a number of uninteresting frames from the stack
// trace. This can be be the first frame (which will be a builtin-exit frame
@@ -427,7 +420,6 @@ class StackTraceHelper {
const Handle<Object> caller_;
bool skip_next_frame_;
- int sloppy_frames_;
bool encountered_strict_function_;
};
@@ -440,33 +432,40 @@ 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> stackTraceLimit =
+ isolate->factory()->InternalizeUtf8String("stackTraceLimit");
+ DCHECK(!stackTraceLimit.is_null());
+
+ Handle<Object> stack_trace_limit =
+ JSReceiver::GetDataProperty(error, stackTraceLimit);
+ 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 limit;
+ if (!GetStackTraceLimit(this, &limit)) return factory()->undefined_value();
- int initial_size = Min(limit, 10);
- Handle<FixedArray> elements =
- factory()->NewFixedArrayWithHoles(initial_size * 4 + 1);
+ using ESTF = EncodedStackTraceFrame;
+ int initial_size = Min(limit, 10) * ESTF::kElementsPerFrame;
+ Handle<FixedArray> elements = factory()->NewFixedArrayWithHoles(initial_size);
+ int cursor = 0;
+ int frames_seen = 0;
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()) {
StackFrame* frame = iter.frame();
@@ -486,25 +485,31 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
// Filter out internal frames that we do not want to show.
if (!helper.IsVisibleInStackTrace(*fun)) continue;
- helper.CountSloppyFrames(*fun);
Handle<Object> recv = frames[i].receiver();
Handle<AbstractCode> abstract_code = frames[i].abstract_code();
+ const int offset = frames[i].code_offset();
+
+ bool force_constructor = false;
if (frame->type() == StackFrame::BUILTIN) {
// Help CallSite::IsConstructor correctly detect hand-written
// construct stubs.
- Code* code = Code::cast(*abstract_code);
- if (code->is_construct_stub()) {
- recv = handle(heap()->call_site_constructor_symbol(), this);
+ if (Code::cast(*abstract_code)->is_construct_stub()) {
+ force_constructor = true;
}
}
- Handle<Smi> offset(Smi::FromInt(frames[i].code_offset()), this);
- elements = MaybeGrow(this, elements, cursor, cursor + 4);
+ int flags = 0;
+ if (helper.IsStrictFrame(*fun)) flags |= StackTraceFrame::kIsStrict;
+ if (force_constructor) flags |= StackTraceFrame::kForceConstructor;
+
+ elements = MaybeGrow(this, elements, cursor,
+ cursor + ESTF::kElementsPerFrame);
elements->set(cursor++, *TheHoleToUndefined(this, recv));
elements->set(cursor++, *fun);
elements->set(cursor++, *abstract_code);
- elements->set(cursor++, *offset);
+ elements->set(cursor++, Smi::FromInt(offset));
+ elements->set(cursor++, Smi::FromInt(flags));
frames_seen++;
}
} break;
@@ -515,26 +520,24 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
// Filter out internal frames that we do not want to show.
if (!helper.IsVisibleInStackTrace(*fun)) continue;
- helper.CountSloppyFrames(*fun);
+ Handle<Object> recv = handle(exit_frame->receiver(), this);
Handle<Code> code = handle(exit_frame->LookupCode(), this);
- int offset =
+ const int offset =
static_cast<int>(exit_frame->pc() - code->instruction_start());
- // In order to help CallSite::IsConstructor detect builtin constructors,
- // we reuse the receiver field to pass along a special symbol.
- Handle<Object> recv;
- if (exit_frame->IsConstructor()) {
- recv = factory()->call_site_constructor_symbol();
- } else {
- recv = handle(exit_frame->receiver(), this);
- }
+ int flags = 0;
+ if (helper.IsStrictFrame(*fun)) flags |= StackTraceFrame::kIsStrict;
+ if (exit_frame->IsConstructor())
+ flags |= StackTraceFrame::kForceConstructor;
- elements = MaybeGrow(this, elements, cursor, cursor + 4);
+ elements =
+ MaybeGrow(this, elements, cursor, cursor + ESTF::kElementsPerFrame);
elements->set(cursor++, *recv);
elements->set(cursor++, *fun);
elements->set(cursor++, *code);
elements->set(cursor++, Smi::FromInt(offset));
+ elements->set(cursor++, Smi::FromInt(flags));
frames_seen++;
} break;
@@ -543,13 +546,21 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
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);
+
+ // TODO(wasm): The wasm object returned by the WasmFrame should always
+ // be a wasm object.
+ DCHECK(wasm::IsWasmObject(wasm_frame->wasm_obj()) ||
+ wasm_frame->wasm_obj()->IsUndefined(this));
+
+ elements =
+ MaybeGrow(this, elements, cursor, cursor + ESTF::kElementsPerFrame);
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));
+ elements->set(cursor++, Smi::FromInt(StackTraceFrame::kIsWasmFrame));
frames_seen++;
} break;
@@ -557,10 +568,12 @@ Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object,
break;
}
}
- elements->set(0, Smi::FromInt(helper.sloppy_frames()));
+
+ DCHECK_EQ(0, cursor % ESTF::kElementsPerFrame);
elements->Shrink(cursor);
Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
result->set_length(Smi::FromInt(cursor));
+
// TODO(yangguo): Queue this structured stack trace for preprocessing on GC.
return result;
}
@@ -769,19 +782,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);
@@ -1426,36 +1426,26 @@ Object* Isolate::PromoteScheduledException() {
void Isolate::PrintCurrentStackTrace(FILE* out) {
- StackTraceFrameIterator it(this);
- while (!it.done()) {
+ for (StackTraceFrameIterator it(this); !it.done(); it.Advance()) {
+ if (!it.is_javascript()) continue;
+
HandleScope scope(this);
+ JavaScriptFrame* frame = it.javascript_frame();
+
// Find code position if recorded in relocation info.
- StandardFrame* frame = it.frame();
- AbstractCode* abstract_code;
- int code_offset;
- if (frame->is_interpreted()) {
- InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame);
- abstract_code = AbstractCode::cast(iframe->GetBytecodeArray());
- code_offset = iframe->GetBytecodeOffset();
- } else {
- DCHECK(frame->is_java_script() || frame->is_wasm());
- Code* code = frame->LookupCode();
- abstract_code = AbstractCode::cast(code);
- code_offset = static_cast<int>(frame->pc() - code->instruction_start());
- }
- int pos = abstract_code->SourcePosition(code_offset);
- JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
- Handle<Object> pos_obj(Smi::FromInt(pos), this);
- // Fetch function and receiver.
- Handle<JSFunction> fun(js_frame->function(), this);
- Handle<Object> recv(js_frame->receiver(), this);
- // Advance to the next JavaScript frame and determine if the
- // current frame is the top-level frame.
- it.Advance();
- Handle<Object> is_top_level = factory()->ToBoolean(it.done());
+ AbstractCode* abstract_code = AbstractCode::cast(frame->LookupCode());
+ const int code_offset =
+ static_cast<int>(frame->pc() - abstract_code->instruction_start());
+
+ Handle<StackTraceFrame> st_frame = factory()->NewStackTraceFrame();
+
+ st_frame->set_receiver(frame->receiver());
+ st_frame->set_function(frame->function());
+ st_frame->set_abstract_code(abstract_code);
+ st_frame->set_offset(code_offset);
+
// Generate and print stack trace line.
- Handle<String> line =
- Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level);
+ Handle<String> line = st_frame->ToString();
if (line->length() > 0) {
line->PrintOn(out);
PrintF(out, "\n");
@@ -1513,6 +1503,23 @@ bool Isolate::ComputeLocationFromException(MessageLocation* target,
return true;
}
+namespace {
+
+int PositionFromStackTrace(Handle<FixedArray> elements, int index) {
+ DisallowHeapAllocation no_gc;
+ using ESTF = EncodedStackTraceFrame;
+ Object* maybe_code = elements->get(index + ESTF::kCodeOffset);
+ 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 + ESTF::kOffsetOffset))->value();
+ return abstract_code->SourcePosition(code_offset);
+ }
+}
+
+} // namespace
bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
Handle<Object> exception) {
@@ -1526,8 +1533,10 @@ bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target,
Handle<FixedArray> elements(FixedArray::cast(simple_stack_trace->elements()));
int elements_limit = Smi::cast(simple_stack_trace->length())->value();
- for (int i = 1; i < elements_limit; i += 4) {
- Handle<Object> fun_obj = handle(elements->get(i + 1), this);
+ using ESTF = EncodedStackTraceFrame;
+ for (int i = 0; i < elements_limit; i += ESTF::kElementsPerFrame) {
+ Handle<Object> fun_obj =
+ handle(elements->get(i + ESTF::kFunctionOffset), this);
if (fun_obj->IsSmi()) {
// TODO(clemensh): handle wasm frames
return false;
« no previous file with comments | « src/isolate.h ('k') | src/messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698