Commit b4c1aefb authored by jgruber's avatar jgruber Committed by Commit bot

Refactor data structures for simple stack traces

Simple stack traces are captured through Isolate::CaptureSimpleStackTrace.
Captured frames are stored in a FixedArray, which in turn is stored as a
property (using a private symbol) on the error object itself. Actual formatting
of the textual stack trace is done lazily when the user reads the stack
property of the error object.

This would involve many conversions back and forth between index-encoded raw
data (receiver, function, offset and code), JS CallSite objects, and C++
CallSite objects.

This commit refactors the C++ CallSite class into a Struct class called
StackTraceFrame, which is the new single point of truth frame information.
Isolate::CaptureSimpleStackTrace stores an array of StackTraceFrames, and JS
CallSite objects (now created only when the user specifies custom stack trace
formatting through Error.prepareStackTrace) internally only store a reference
to a StackTraceFrame.

BUG=

Review-Url: https://codereview.chromium.org/2230953002
Cr-Commit-Position: refs/heads/master@{#38645}
parent 0686c414
...@@ -7623,8 +7623,8 @@ class Internals { ...@@ -7623,8 +7623,8 @@ class Internals {
static const int kNodeIsPartiallyDependentShift = 4; static const int kNodeIsPartiallyDependentShift = 4;
static const int kNodeIsActiveShift = 4; static const int kNodeIsActiveShift = 4;
static const int kJSObjectType = 0xb7; static const int kJSObjectType = 0xb8;
static const int kJSApiObjectType = 0xb6; static const int kJSApiObjectType = 0xb7;
static const int kFirstNonstringType = 0x80; static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x83; static const int kOddballType = 0x83;
static const int kForeignType = 0x87; static const int kForeignType = 0x87;
......
...@@ -11,15 +11,22 @@ ...@@ -11,15 +11,22 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
#define CHECK_CALLSITE(recv, method) \ #define CHECK_CALLSITE(recv, method) \
CHECK_RECEIVER(JSObject, recv, method); \ CHECK_RECEIVER(JSObject, recv, method); \
if (!JSReceiver::HasOwnProperty( \ Handle<StackTraceFrame> frame; \
recv, isolate->factory()->call_site_position_symbol()) \ { \
.FromMaybe(false)) { \ Handle<Object> frame_obj; \
THROW_NEW_ERROR_RETURN_FAILURE( \ ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \
isolate, \ isolate, frame_obj, \
NewTypeError(MessageTemplate::kCallSiteMethod, \ JSObject::GetProperty(recv, \
isolate->factory()->NewStringFromAsciiChecked(method))); \ isolate->factory()->call_site_frame_symbol())); \
if (!frame_obj->IsStackTraceFrame()) { \
THROW_NEW_ERROR_RETURN_FAILURE( \
isolate, NewTypeError(MessageTemplate::kCallSiteMethod, \
isolate->factory()->NewStringFromAsciiChecked( \
method))); \
} \
frame = Handle<StackTraceFrame>::cast(frame_obj); \
} }
namespace { namespace {
...@@ -34,167 +41,107 @@ Object* PositiveNumberOrNull(int value, Isolate* isolate) { ...@@ -34,167 +41,107 @@ Object* PositiveNumberOrNull(int value, Isolate* isolate) {
BUILTIN(CallSitePrototypeGetColumnNumber) { BUILTIN(CallSitePrototypeGetColumnNumber) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getColumnNumber"); CHECK_CALLSITE(recv, "getColumnNumber");
return PositiveNumberOrNull(frame->GetColumnNumber(), isolate);
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
return PositiveNumberOrNull(call_site.GetColumnNumber(), isolate);
} }
BUILTIN(CallSitePrototypeGetEvalOrigin) { BUILTIN(CallSitePrototypeGetEvalOrigin) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getEvalOrigin"); CHECK_CALLSITE(recv, "getEvalOrigin");
return *frame->GetEvalOrigin();
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
return *call_site.GetEvalOrigin();
} }
BUILTIN(CallSitePrototypeGetFileName) { BUILTIN(CallSitePrototypeGetFileName) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getFileName"); CHECK_CALLSITE(recv, "getFileName");
return *frame->GetFileName();
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
return *call_site.GetFileName();
}
namespace {
bool CallSiteIsStrict(Isolate* isolate, Handle<JSObject> receiver) {
Handle<Object> strict;
Handle<Symbol> symbol = isolate->factory()->call_site_strict_symbol();
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, strict,
JSObject::GetProperty(receiver, symbol));
return strict->BooleanValue();
} }
} // namespace
BUILTIN(CallSitePrototypeGetFunction) { BUILTIN(CallSitePrototypeGetFunction) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getFunction"); CHECK_CALLSITE(recv, "getFunction");
if (CallSiteIsStrict(isolate, recv)) if (frame->IsStrict() || frame->IsWasmFrame()) {
return *isolate->factory()->undefined_value(); return *isolate->factory()->undefined_value();
}
Handle<Symbol> symbol = isolate->factory()->call_site_function_symbol(); return frame->function();
RETURN_RESULT_OR_FAILURE(isolate, JSObject::GetProperty(recv, symbol));
} }
BUILTIN(CallSitePrototypeGetFunctionName) { BUILTIN(CallSitePrototypeGetFunctionName) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getFunctionName"); CHECK_CALLSITE(recv, "getFunctionName");
return *frame->GetFunctionName();
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
return *call_site.GetFunctionName();
} }
BUILTIN(CallSitePrototypeGetLineNumber) { BUILTIN(CallSitePrototypeGetLineNumber) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getLineNumber"); CHECK_CALLSITE(recv, "getLineNumber");
return PositiveNumberOrNull(frame->GetLineNumber(), isolate);
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
int line_number = call_site.IsWasm() ? call_site.wasm_func_index()
: call_site.GetLineNumber();
return PositiveNumberOrNull(line_number, isolate);
} }
BUILTIN(CallSitePrototypeGetMethodName) { BUILTIN(CallSitePrototypeGetMethodName) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getMethodName"); CHECK_CALLSITE(recv, "getMethodName");
return *frame->GetMethodName();
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
return *call_site.GetMethodName();
} }
BUILTIN(CallSitePrototypeGetPosition) { BUILTIN(CallSitePrototypeGetPosition) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getPosition"); CHECK_CALLSITE(recv, "getPosition");
return Smi::FromInt(frame->GetPosition());
Handle<Symbol> symbol = isolate->factory()->call_site_position_symbol();
RETURN_RESULT_OR_FAILURE(isolate, JSObject::GetProperty(recv, symbol));
} }
BUILTIN(CallSitePrototypeGetScriptNameOrSourceURL) { BUILTIN(CallSitePrototypeGetScriptNameOrSourceURL) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getScriptNameOrSourceUrl"); CHECK_CALLSITE(recv, "getScriptNameOrSourceUrl");
return *frame->GetScriptNameOrSourceUrl();
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
return *call_site.GetScriptNameOrSourceUrl();
} }
BUILTIN(CallSitePrototypeGetThis) { BUILTIN(CallSitePrototypeGetThis) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getThis"); CHECK_CALLSITE(recv, "getThis");
if (CallSiteIsStrict(isolate, recv)) if (frame->IsStrict() || frame->ForceConstructor() || frame->IsWasmFrame()) {
return *isolate->factory()->undefined_value();
Handle<Object> receiver;
Handle<Symbol> symbol = isolate->factory()->call_site_receiver_symbol();
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
JSObject::GetProperty(recv, symbol));
if (*receiver == isolate->heap()->call_site_constructor_symbol())
return *isolate->factory()->undefined_value(); return *isolate->factory()->undefined_value();
}
return *receiver; return frame->receiver();
} }
BUILTIN(CallSitePrototypeGetTypeName) { BUILTIN(CallSitePrototypeGetTypeName) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "getTypeName"); CHECK_CALLSITE(recv, "getTypeName");
return *frame->GetTypeName();
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
return *call_site.GetTypeName();
} }
BUILTIN(CallSitePrototypeIsConstructor) { BUILTIN(CallSitePrototypeIsConstructor) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "isConstructor"); CHECK_CALLSITE(recv, "isConstructor");
return isolate->heap()->ToBoolean(frame->IsConstructor());
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
return isolate->heap()->ToBoolean(call_site.IsConstructor());
} }
BUILTIN(CallSitePrototypeIsEval) { BUILTIN(CallSitePrototypeIsEval) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "isEval"); CHECK_CALLSITE(recv, "isEval");
return isolate->heap()->ToBoolean(frame->IsEval());
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
return isolate->heap()->ToBoolean(call_site.IsEval());
} }
BUILTIN(CallSitePrototypeIsNative) { BUILTIN(CallSitePrototypeIsNative) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "isNative"); CHECK_CALLSITE(recv, "isNative");
return isolate->heap()->ToBoolean(frame->IsNative());
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
return isolate->heap()->ToBoolean(call_site.IsNative());
} }
BUILTIN(CallSitePrototypeIsToplevel) { BUILTIN(CallSitePrototypeIsToplevel) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "isToplevel"); CHECK_CALLSITE(recv, "isToplevel");
return isolate->heap()->ToBoolean(frame->IsToplevel());
CallSite call_site(isolate, recv);
CHECK(call_site.IsJavaScript() || call_site.IsWasm());
return isolate->heap()->ToBoolean(call_site.IsToplevel());
} }
BUILTIN(CallSitePrototypeToString) { BUILTIN(CallSitePrototypeToString) {
HandleScope scope(isolate); HandleScope scope(isolate);
CHECK_CALLSITE(recv, "toString"); CHECK_CALLSITE(recv, "toString");
RETURN_RESULT_OR_FAILURE(isolate, CallSiteUtils::ToString(isolate, recv)); return *frame->ToString();
} }
#undef CHECK_CALLSITE #undef CHECK_CALLSITE
......
...@@ -434,31 +434,6 @@ void StackGuard::InitThread(const ExecutionAccess& lock) { ...@@ -434,31 +434,6 @@ void StackGuard::InitThread(const ExecutionAccess& lock) {
// --- C a l l s t o n a t i v e s --- // --- C a l l s t o n a t i v e s ---
Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
Handle<JSFunction> fun,
Handle<Object> pos,
Handle<Object> is_global) {
Isolate* isolate = fun->GetIsolate();
Handle<Object> strict_mode = isolate->factory()->ToBoolean(false);
MaybeHandle<Object> maybe_callsite =
CallSiteUtils::Construct(isolate, recv, fun, pos, strict_mode);
if (maybe_callsite.is_null()) {
isolate->clear_pending_exception();
return isolate->factory()->empty_string();
}
MaybeHandle<String> maybe_to_string =
CallSiteUtils::ToString(isolate, maybe_callsite.ToHandleChecked());
if (maybe_to_string.is_null()) {
isolate->clear_pending_exception();
return isolate->factory()->empty_string();
}
return maybe_to_string.ToHandleChecked();
}
void StackGuard::HandleGCInterrupt() { void StackGuard::HandleGCInterrupt() {
if (CheckAndClearInterrupt(GC_REQUEST)) { if (CheckAndClearInterrupt(GC_REQUEST)) {
isolate_->heap()->HandleGCRequest(); isolate_->heap()->HandleGCRequest();
......
...@@ -48,11 +48,6 @@ class Execution final : public AllStatic { ...@@ -48,11 +48,6 @@ class Execution final : public AllStatic {
Handle<Object> receiver, int argc, Handle<Object> receiver, int argc,
Handle<Object> argv[], Handle<Object> argv[],
MaybeHandle<Object>* exception_out = NULL); MaybeHandle<Object>* exception_out = NULL);
static Handle<String> GetStackTraceLine(Handle<Object> recv,
Handle<JSFunction> fun,
Handle<Object> pos,
Handle<Object> is_global);
}; };
......
...@@ -917,6 +917,13 @@ Handle<Script> Factory::NewScript(Handle<String> source) { ...@@ -917,6 +917,13 @@ Handle<Script> Factory::NewScript(Handle<String> source) {
return script; return script;
} }
Handle<StackTraceFrame> Factory::NewStackTraceFrame() {
Handle<StackTraceFrame> frame =
Handle<StackTraceFrame>::cast(NewStruct(STACK_TRACE_FRAME_TYPE));
frame->set_flags(0);
frame->set_offset(0);
return frame;
}
Handle<Foreign> Factory::NewForeign(Address addr, PretenureFlag pretenure) { Handle<Foreign> Factory::NewForeign(Address addr, PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(isolate(), CALL_HEAP_FUNCTION(isolate(),
......
...@@ -292,6 +292,8 @@ class Factory final { ...@@ -292,6 +292,8 @@ class Factory final {
Handle<Script> NewScript(Handle<String> source); Handle<Script> NewScript(Handle<String> source);
Handle<StackTraceFrame> NewStackTraceFrame();
// Foreign objects are pretenured when allocated by the bootstrapper. // Foreign objects are pretenured when allocated by the bootstrapper.
Handle<Foreign> NewForeign(Address addr, Handle<Foreign> NewForeign(Address addr,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
......
...@@ -161,13 +161,7 @@ ...@@ -161,13 +161,7 @@
V(array_iteration_kind_symbol) \ V(array_iteration_kind_symbol) \
V(array_iterator_next_symbol) \ V(array_iterator_next_symbol) \
V(array_iterator_object_symbol) \ V(array_iterator_object_symbol) \
V(call_site_constructor_symbol) \ V(call_site_frame_symbol) \
V(call_site_function_symbol) \
V(call_site_position_symbol) \
V(call_site_receiver_symbol) \
V(call_site_strict_symbol) \
V(call_site_wasm_obj_symbol) \
V(call_site_wasm_func_index_symbol) \
V(class_end_position_symbol) \ V(class_end_position_symbol) \
V(class_start_position_symbol) \ V(class_start_position_symbol) \
V(detailed_stack_trace_symbol) \ V(detailed_stack_trace_symbol) \
......
This diff is collapsed.
This diff is collapsed.
...@@ -42,40 +42,6 @@ class MessageLocation { ...@@ -42,40 +42,6 @@ class MessageLocation {
Handle<JSFunction> function_; Handle<JSFunction> function_;
}; };
class CallSite {
public:
CallSite(Isolate* isolate, Handle<JSObject> call_site_obj);
Handle<Object> GetFileName();
Handle<Object> GetFunctionName();
Handle<Object> GetScriptNameOrSourceUrl();
Handle<Object> GetMethodName();
Handle<Object> GetTypeName();
Handle<Object> GetEvalOrigin();
// Return 1-based line number, including line offset.
int GetLineNumber();
// Return 1-based column number, including column offset if first line.
int GetColumnNumber();
bool IsNative();
bool IsToplevel();
bool IsEval();
bool IsConstructor();
bool IsJavaScript() { return !fun_.is_null(); }
bool IsWasm() { return !wasm_obj_.is_null(); }
int wasm_func_index() const { return wasm_func_index_; }
private:
Isolate* isolate_;
Handle<Object> receiver_;
Handle<JSFunction> fun_;
int32_t pos_ = -1;
Handle<JSObject> wasm_obj_;
uint32_t wasm_func_index_ = static_cast<uint32_t>(-1);
};
// Determines how stack trace collection skips frames. // Determines how stack trace collection skips frames.
enum FrameSkipMode { enum FrameSkipMode {
// Unconditionally skips the first frame. Used e.g. when the Error constructor // Unconditionally skips the first frame. Used e.g. when the Error constructor
...@@ -107,16 +73,6 @@ class ErrorUtils : public AllStatic { ...@@ -107,16 +73,6 @@ class ErrorUtils : public AllStatic {
Handle<Object> stack_trace); Handle<Object> stack_trace);
}; };
class CallSiteUtils : public AllStatic {
public:
static MaybeHandle<Object> Construct(Isolate* isolate,
Handle<Object> receiver,
Handle<Object> fun, Handle<Object> pos,
Handle<Object> strict_mode);
static MaybeHandle<String> ToString(Isolate* isolate, Handle<Object> recv);
};
#define MESSAGE_TEMPLATES(T) \ #define MESSAGE_TEMPLATES(T) \
/* Error */ \ /* Error */ \
T(None, "") \ T(None, "") \
......
...@@ -1016,6 +1016,10 @@ void Script::ScriptVerify() { ...@@ -1016,6 +1016,10 @@ void Script::ScriptVerify() {
VerifyPointer(line_ends()); VerifyPointer(line_ends());
} }
void StackTraceFrame::StackTraceFrameVerify() {
CHECK(IsStackTraceFrame());
VerifyPointer(abstract_code());
}
void NormalizedMapCache::NormalizedMapCacheVerify() { void NormalizedMapCache::NormalizedMapCacheVerify() {
FixedArray::cast(this)->FixedArrayVerify(); FixedArray::cast(this)->FixedArrayVerify();
......
...@@ -5809,6 +5809,29 @@ void Script::set_origin_options(ScriptOriginOptions origin_options) { ...@@ -5809,6 +5809,29 @@ void Script::set_origin_options(ScriptOriginOptions origin_options) {
(origin_options.Flags() << kOriginOptionsShift)); (origin_options.Flags() << kOriginOptionsShift));
} }
SMI_ACCESSORS(StackTraceFrame, flags, kFlagsOffset)
ACCESSORS(StackTraceFrame, abstract_code, AbstractCode, kAbstractCodeOffset)
SMI_ACCESSORS(StackTraceFrame, offset, kOffsetOffset)
ACCESSORS_CHECKED(StackTraceFrame, receiver, Object, kReceiverOffset,
!IsWasmFrame())
ACCESSORS_CHECKED(StackTraceFrame, function, JSFunction, kFunctionOffset,
!IsWasmFrame())
ACCESSORS_CHECKED(StackTraceFrame, wasm_object, Object, kWasmObjectOffset,
IsWasmFrame())
SMI_ACCESSORS_CHECKED(StackTraceFrame, wasm_function_index,
kWasmFunctionIndexOffset, IsWasmFrame())
bool StackTraceFrame::IsWasmFrame() const {
return ((flags() & kIsWasmFrame) != 0);
}
bool StackTraceFrame::IsJavaScriptFrame() const { return !IsWasmFrame(); }
bool StackTraceFrame::IsStrict() const { return ((flags() & kIsStrict) != 0); }
bool StackTraceFrame::ForceConstructor() const {
return ((flags() & kForceConstructor) != 0);
}
ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex) ACCESSORS(DebugInfo, shared, SharedFunctionInfo, kSharedFunctionInfoIndex)
ACCESSORS(DebugInfo, debug_bytecode_array, Object, kDebugBytecodeArrayIndex) ACCESSORS(DebugInfo, debug_bytecode_array, Object, kDebugBytecodeArrayIndex)
......
...@@ -1274,6 +1274,21 @@ void Script::ScriptPrint(std::ostream& os) { // NOLINT ...@@ -1274,6 +1274,21 @@ void Script::ScriptPrint(std::ostream& os) { // NOLINT
os << "\n"; os << "\n";
} }
void StackTraceFrame::StackTraceFramePrint(std::ostream& os) { // NOLINT
HeapObject::PrintHeader(os, "StackTraceFrame");
os << "\n - flags: " << flags();
os << "\n - abstract_code: " << Brief(abstract_code());
os << "\n - offset: " << offset();
if (IsWasmFrame()) {
os << "\n - wasm_object: " << Brief(wasm_object());
os << "\n - wasm_function_index data: " << wasm_function_index();
} else {
DCHECK(IsJavaScriptFrame());
os << "\n - receiver: " << Brief(receiver());
os << "\n - function: " << Brief(function());
}
os << "\n";
}
void DebugInfo::DebugInfoPrint(std::ostream& os) { // NOLINT void DebugInfo::DebugInfoPrint(std::ostream& os) { // NOLINT
HeapObject::PrintHeader(os, "DebugInfo"); HeapObject::PrintHeader(os, "DebugInfo");
......
This diff is collapsed.
...@@ -388,6 +388,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; ...@@ -388,6 +388,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(ALLOCATION_MEMENTO_TYPE) \ V(ALLOCATION_MEMENTO_TYPE) \
V(ALLOCATION_SITE_TYPE) \ V(ALLOCATION_SITE_TYPE) \
V(SCRIPT_TYPE) \ V(SCRIPT_TYPE) \
V(STACK_TRACE_FRAME_TYPE) \
V(TYPE_FEEDBACK_INFO_TYPE) \ V(TYPE_FEEDBACK_INFO_TYPE) \
V(ALIASED_ARGUMENTS_ENTRY_TYPE) \ V(ALIASED_ARGUMENTS_ENTRY_TYPE) \
V(BOX_TYPE) \ V(BOX_TYPE) \
...@@ -503,6 +504,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1; ...@@ -503,6 +504,7 @@ const int kStubMinorKeyBits = kSmiValueSize - kStubMajorKeyBits - 1;
V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \ V(FUNCTION_TEMPLATE_INFO, FunctionTemplateInfo, function_template_info) \
V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \ V(OBJECT_TEMPLATE_INFO, ObjectTemplateInfo, object_template_info) \
V(SCRIPT, Script, script) \ V(SCRIPT, Script, script) \
V(STACK_TRACE_FRAME, StackTraceFrame, stack_trace_frame) \
V(ALLOCATION_SITE, AllocationSite, allocation_site) \ V(ALLOCATION_SITE, AllocationSite, allocation_site) \
V(ALLOCATION_MEMENTO, AllocationMemento, allocation_memento) \ V(ALLOCATION_MEMENTO, AllocationMemento, allocation_memento) \
V(TYPE_FEEDBACK_INFO, TypeFeedbackInfo, type_feedback_info) \ V(TYPE_FEEDBACK_INFO, TypeFeedbackInfo, type_feedback_info) \
...@@ -674,6 +676,7 @@ enum InstanceType { ...@@ -674,6 +676,7 @@ enum InstanceType {
ALLOCATION_SITE_TYPE, ALLOCATION_SITE_TYPE,
ALLOCATION_MEMENTO_TYPE, ALLOCATION_MEMENTO_TYPE,
SCRIPT_TYPE, SCRIPT_TYPE,
STACK_TRACE_FRAME_TYPE,
TYPE_FEEDBACK_INFO_TYPE, TYPE_FEEDBACK_INFO_TYPE,
ALIASED_ARGUMENTS_ENTRY_TYPE, ALIASED_ARGUMENTS_ENTRY_TYPE,
BOX_TYPE, BOX_TYPE,
...@@ -6491,7 +6494,6 @@ class Box : public Struct { ...@@ -6491,7 +6494,6 @@ class Box : public Struct {
DISALLOW_IMPLICIT_CONSTRUCTORS(Box); DISALLOW_IMPLICIT_CONSTRUCTORS(Box);
}; };
// Container for metadata stored on each prototype map. // Container for metadata stored on each prototype map.
class PrototypeInfo : public Struct { class PrototypeInfo : public Struct {
public: public:
...@@ -6776,6 +6778,88 @@ class Script: public Struct { ...@@ -6776,6 +6778,88 @@ class Script: public Struct {
DISALLOW_IMPLICIT_CONSTRUCTORS(Script); DISALLOW_IMPLICIT_CONSTRUCTORS(Script);
}; };
class StackTraceFrame : public Struct {
public:
// --- Fields for JS and Wasm frames. ---
static const int kIsWasmFrame = 1 << 0;
static const int kForceConstructor = 1 << 1;
static const int kIsStrict = 1 << 2;
// [flags]
DECL_INT_ACCESSORS(flags)
// [abstract_code]
DECL_ACCESSORS(abstract_code, AbstractCode)
// [offset]
DECL_INT_ACCESSORS(offset)
// --- Fields for JS frames. ---
// [receiver]
DECL_ACCESSORS(receiver, Object)
// [function]
DECL_ACCESSORS(function, JSFunction)
// --- Fields for Wasm frames. ---
// [wasm_object]
DECL_ACCESSORS(wasm_object, Object)
// [wasm_function_index]
DECL_INT_ACCESSORS(wasm_function_index)
inline bool IsWasmFrame() const;
inline bool IsJavaScriptFrame() const;
inline bool IsStrict() const;
inline bool ForceConstructor() const;
Handle<Object> GetFileName();
Handle<Object> GetFunctionName();
Handle<Object> GetScriptNameOrSourceUrl();
Handle<Object> GetMethodName();
Handle<Object> GetTypeName();
Handle<Object> GetEvalOrigin();
int GetPosition();
// Return 1-based line number, including line offset.
int GetLineNumber();
// Return 1-based column number, including column offset if first line.
int GetColumnNumber();
bool IsNative();
bool IsToplevel();
bool IsEval();
bool IsConstructor();
Handle<String> ToString();
DECLARE_CAST(StackTraceFrame)
// Dispatched behavior.
DECLARE_PRINTER(StackTraceFrame)
DECLARE_VERIFIER(StackTraceFrame)
// Fields for all frame types.
static const int kFlagsOffset = HeapObject::kHeaderSize;
static const int kAbstractCodeOffset = kFlagsOffset + kPointerSize;
static const int kOffsetOffset = kAbstractCodeOffset + kPointerSize;
// Fields for JS frames.
static const int kReceiverOffset = kOffsetOffset + kPointerSize;
static const int kFunctionOffset = kReceiverOffset + kPointerSize;
// Fields for Wasm frames.
static const int kWasmObjectOffset = kOffsetOffset + kPointerSize;
static const int kWasmFunctionIndexOffset = kWasmObjectOffset + kPointerSize;
static const int kSize = kFunctionOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(StackTraceFrame);
};
// List of builtin functions we want to identify to improve code // List of builtin functions we want to identify to improve code
// generation. // generation.
......
...@@ -115,22 +115,27 @@ RUNTIME_FUNCTION(Runtime_ThrowWasmError) { ...@@ -115,22 +115,27 @@ RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
// TODO(wasm): This implementation is temporary, see bug #5007: // TODO(wasm): This implementation is temporary, see bug #5007:
// https://bugs.chromium.org/p/v8/issues/detail?id=5007 // https://bugs.chromium.org/p/v8/issues/detail?id=5007
Handle<JSObject> error = Handle<JSObject>::cast(error_obj); Handle<JSObject> error = Handle<JSObject>::cast(error_obj);
// Patch the stack trace (array of <receiver, function, code, position>).
Handle<Object> stack_trace_obj = JSReceiver::GetDataProperty( Handle<Object> stack_trace_obj = JSReceiver::GetDataProperty(
error, isolate->factory()->stack_trace_symbol()); error, isolate->factory()->stack_trace_symbol());
// Patch the stack trace (array of <receiver, function, code, position>).
if (stack_trace_obj->IsJSArray()) { if (stack_trace_obj->IsJSArray()) {
Handle<FixedArray> stack_elements( Handle<FixedArray> stack_elements(
FixedArray::cast(JSArray::cast(*stack_trace_obj)->elements())); FixedArray::cast(JSArray::cast(*stack_trace_obj)->elements()));
DCHECK_EQ(1, stack_elements->length() % 4); Handle<StackTraceFrame> frame =
DCHECK(Code::cast(stack_elements->get(3))->kind() == Code::WASM_FUNCTION); handle(StackTraceFrame::cast(stack_elements->get(0)));
DCHECK(stack_elements->get(4)->IsSmi() &&
Smi::cast(stack_elements->get(4))->value() >= 0); DCHECK(frame->IsWasmFrame());
stack_elements->set(4, Smi::FromInt(-1 - byte_offset)); DCHECK(frame->offset() >= 0);
frame->set_offset(-1 - byte_offset);
} }
Handle<Object> detailed_stack_trace_obj = JSReceiver::GetDataProperty(
error, isolate->factory()->detailed_stack_trace_symbol());
// Patch the detailed stack trace (array of JSObjects with various // Patch the detailed stack trace (array of JSObjects with various
// properties). // properties).
Handle<Object> detailed_stack_trace_obj = JSReceiver::GetDataProperty(
error, isolate->factory()->detailed_stack_trace_symbol());
if (detailed_stack_trace_obj->IsJSArray()) { if (detailed_stack_trace_obj->IsJSArray()) {
Handle<FixedArray> stack_elements( Handle<FixedArray> stack_elements(
FixedArray::cast(JSArray::cast(*detailed_stack_trace_obj)->elements())); FixedArray::cast(JSArray::cast(*detailed_stack_trace_obj)->elements()));
......
...@@ -248,6 +248,7 @@ Type::bitset BitsetType::Lub(i::Map* map) { ...@@ -248,6 +248,7 @@ Type::bitset BitsetType::Lub(i::Map* map) {
case TRANSITION_ARRAY_TYPE: case TRANSITION_ARRAY_TYPE:
case FOREIGN_TYPE: case FOREIGN_TYPE:
case SCRIPT_TYPE: case SCRIPT_TYPE:
case STACK_TRACE_FRAME_TYPE:
case CODE_TYPE: case CODE_TYPE:
case PROPERTY_CELL_TYPE: case PROPERTY_CELL_TYPE:
return kOtherInternal & kTaggedPointer; return kOtherInternal & kTaggedPointer;
......
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