Skip to content

Commit

Permalink
[inspector] store stack frame in struct instead of JSObject
Browse files Browse the repository at this point in the history
JSObject is slow: creating strings for keys and storing values by these keys after takes significant amount of time.
With this CL console methods (most of them collect top stack frame to calculate source location) are ~33% faster.
V8Debugger::captureStackTrace is ~50% faster.

BUG=v8:6189
R=yangguo@chromium.org
TBR=bmeurer@chromium.org

Review-Url: https://codereview.chromium.org/2789073002
Cr-Commit-Position: refs/heads/master@{#44344}
  • Loading branch information
alexkozy authored and Commit bot committed Apr 3, 2017
1 parent 32d4d8e commit dc662e5
Show file tree
Hide file tree
Showing 14 changed files with 164 additions and 186 deletions.
4 changes: 2 additions & 2 deletions include/v8.h
Expand Up @@ -8646,8 +8646,8 @@ class Internals {
static const int kNodeIsIndependentShift = 3;
static const int kNodeIsActiveShift = 4;

static const int kJSApiObjectType = 0xba;
static const int kJSObjectType = 0xbb;
static const int kJSApiObjectType = 0xbb;
static const int kJSObjectType = 0xbc;
static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x82;
static const int kForeignType = 0x86;
Expand Down
74 changes: 28 additions & 46 deletions src/api.cc
Expand Up @@ -2846,8 +2846,8 @@ Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
auto self = Utils::OpenHandle(this);
auto obj = i::JSReceiver::GetElement(isolate, self, index).ToHandleChecked();
auto jsobj = i::Handle<i::JSObject>::cast(obj);
return scope.Escape(Utils::StackFrameToLocal(jsobj));
auto info = i::Handle<i::StackFrameInfo>::cast(obj);
return scope.Escape(Utils::StackFrameToLocal(info));
}


Expand Down Expand Up @@ -2875,77 +2875,59 @@ Local<StackTrace> StackTrace::CurrentStackTrace(

// --- S t a c k F r a m e ---

static int getIntProperty(const StackFrame* f, const char* propertyName,
int defaultValue) {
i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(f);
i::Handle<i::Object> obj =
i::JSReceiver::GetProperty(isolate, self, propertyName).ToHandleChecked();
return obj->IsSmi() ? i::Smi::cast(*obj)->value() : defaultValue;
}


int StackFrame::GetLineNumber() const {
return getIntProperty(this, "lineNumber", Message::kNoLineNumberInfo);
int v = Utils::OpenHandle(this)->line_number();
return v ? v : Message::kNoLineNumberInfo;
}


int StackFrame::GetColumn() const {
return getIntProperty(this, "column", Message::kNoColumnInfo);
int v = Utils::OpenHandle(this)->column_number();
return v ? v : Message::kNoLineNumberInfo;
}


int StackFrame::GetScriptId() const {
return getIntProperty(this, "scriptId", Message::kNoScriptIdInfo);
int v = Utils::OpenHandle(this)->script_id();
return v ? v : Message::kNoScriptIdInfo;
}


static Local<String> getStringProperty(const StackFrame* f,
const char* propertyName) {
i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
Local<String> StackFrame::GetScriptName() const {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSObject> self = Utils::OpenHandle(f);
i::Handle<i::Object> obj =
i::JSReceiver::GetProperty(isolate, self, propertyName).ToHandleChecked();
i::Handle<i::StackFrameInfo> self = Utils::OpenHandle(this);
i::Handle<i::Object> obj(self->script_name(), isolate);
return obj->IsString()
? scope.Escape(Local<String>::Cast(Utils::ToLocal(obj)))
: Local<String>();
}


Local<String> StackFrame::GetScriptName() const {
return getStringProperty(this, "scriptName");
}


Local<String> StackFrame::GetScriptNameOrSourceURL() const {
return getStringProperty(this, "scriptNameOrSourceURL");
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::StackFrameInfo> self = Utils::OpenHandle(this);
i::Handle<i::Object> obj(self->script_name_or_source_url(), isolate);
return obj->IsString()
? scope.Escape(Local<String>::Cast(Utils::ToLocal(obj)))
: Local<String>();
}


Local<String> StackFrame::GetFunctionName() const {
return getStringProperty(this, "functionName");
}


static bool getBoolProperty(const StackFrame* f, const char* propertyName) {
i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(f);
i::Handle<i::Object> obj =
i::JSReceiver::GetProperty(isolate, self, propertyName).ToHandleChecked();
return obj->IsTrue(isolate);
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::StackFrameInfo> self = Utils::OpenHandle(this);
i::Handle<i::Object> obj(self->function_name(), isolate);
return obj->IsString()
? scope.Escape(Local<String>::Cast(Utils::ToLocal(obj)))
: Local<String>();
}

bool StackFrame::IsEval() const { return getBoolProperty(this, "isEval"); }

bool StackFrame::IsEval() const { return Utils::OpenHandle(this)->is_eval(); }

bool StackFrame::IsConstructor() const {
return getBoolProperty(this, "isConstructor");
return Utils::OpenHandle(this)->is_constructor();
}


Expand Down
6 changes: 3 additions & 3 deletions src/api.h
Expand Up @@ -106,7 +106,7 @@ class RegisteredExtension {
V(Context, Context) \
V(External, Object) \
V(StackTrace, JSArray) \
V(StackFrame, JSObject) \
V(StackFrame, StackFrameInfo) \
V(Proxy, JSProxy) \
V(NativeWeakMap, JSWeakMap) \
V(debug::GeneratorObject, JSGeneratorObject) \
Expand Down Expand Up @@ -188,7 +188,7 @@ class Utils {
static inline Local<StackTrace> StackTraceToLocal(
v8::internal::Handle<v8::internal::JSArray> obj);
static inline Local<StackFrame> StackFrameToLocal(
v8::internal::Handle<v8::internal::JSObject> obj);
v8::internal::Handle<v8::internal::StackFrameInfo> obj);
static inline Local<Number> NumberToLocal(
v8::internal::Handle<v8::internal::Object> obj);
static inline Local<Integer> IntegerToLocal(
Expand Down Expand Up @@ -318,7 +318,7 @@ MAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature)
MAKE_TO_LOCAL(MessageToLocal, Object, Message)
MAKE_TO_LOCAL(PromiseToLocal, JSObject, Promise)
MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace)
MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame)
MAKE_TO_LOCAL(StackFrameToLocal, StackFrameInfo, StackFrame)
MAKE_TO_LOCAL(NumberToLocal, Object, Number)
MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
Expand Down
1 change: 1 addition & 0 deletions src/ast/ast-types.cc
Expand Up @@ -312,6 +312,7 @@ AstType::bitset AstBitsetType::Lub(i::Map* map) {
case ALIASED_ARGUMENTS_ENTRY_TYPE:
case DEBUG_INFO_TYPE:
case BREAK_POINT_INFO_TYPE:
case STACK_FRAME_INFO_TYPE:
case CELL_TYPE:
case WEAK_CELL_TYPE:
case PROTOTYPE_INFO_TYPE:
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.cc
Expand Up @@ -320,6 +320,7 @@ Type::bitset BitsetType::Lub(i::Map* map) {
case PROMISE_REACTION_JOB_INFO_TYPE:
case DEBUG_INFO_TYPE:
case BREAK_POINT_INFO_TYPE:
case STACK_FRAME_INFO_TYPE:
case CELL_TYPE:
case WEAK_CELL_TYPE:
case PROTOTYPE_INFO_TYPE:
Expand Down
1 change: 1 addition & 0 deletions src/deoptimizer.cc
Expand Up @@ -4203,6 +4203,7 @@ Handle<Object> TranslatedState::MaterializeCapturedObjectAt(
case PROMISE_REACTION_JOB_INFO_TYPE:
case DEBUG_INFO_TYPE:
case BREAK_POINT_INFO_TYPE:
case STACK_FRAME_INFO_TYPE:
case CELL_TYPE:
case WEAK_CELL_TYPE:
case PROTOTYPE_INFO_TYPE:
Expand Down
13 changes: 13 additions & 0 deletions src/factory.cc
Expand Up @@ -2592,6 +2592,19 @@ Handle<BreakPointInfo> Factory::NewBreakPointInfo(int source_position) {
return new_break_point_info;
}

Handle<StackFrameInfo> Factory::NewStackFrameInfo() {
Handle<StackFrameInfo> stack_frame_info =
Handle<StackFrameInfo>::cast(NewStruct(STACK_FRAME_INFO_TYPE));
stack_frame_info->set_line_number(0);
stack_frame_info->set_column_number(0);
stack_frame_info->set_script_id(0);
stack_frame_info->set_script_name(Smi::kZero);
stack_frame_info->set_script_name_or_source_url(Smi::kZero);
stack_frame_info->set_function_name(Smi::kZero);
stack_frame_info->set_flag(0);
return stack_frame_info;
}

Handle<JSObject> Factory::NewArgumentsObject(Handle<JSFunction> callee,
int length) {
bool strict_mode_callee = is_strict(callee->shared()->language_mode()) ||
Expand Down
1 change: 1 addition & 0 deletions src/factory.h
Expand Up @@ -321,6 +321,7 @@ class V8_EXPORT_PRIVATE Factory final {
Handle<Script> NewScript(Handle<String> source);

Handle<BreakPointInfo> NewBreakPointInfo(int source_position);
Handle<StackFrameInfo> NewStackFrameInfo();

// Foreign objects are pretenured when allocated by the bootstrapper.
Handle<Foreign> NewForeign(Address addr,
Expand Down

0 comments on commit dc662e5

Please sign in to comment.