Commit 06af80d4 authored by ulan@chromium.org's avatar ulan@chromium.org

Introduce Runtime_GetAllScopesDetails to get all scopes at once for a frame.

This will reduce heavy ScopeIterator instantiations.
Once incorporated into chromium, will give 30% speed boost.

BUG=chromium:340285
LOG=Y
R=ulan@chromium.org, Yang, rossberg, ulan

Review URL: https://codereview.chromium.org/181063008

Patch from Andrey Adaykin <aandrey@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19717 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f19e15c3
......@@ -1687,6 +1687,18 @@ FrameMirror.prototype.scope = function(index) {
};
FrameMirror.prototype.allScopes = function() {
var scopeDetails = %GetAllScopesDetails(this.break_id_,
this.details_.frameId(),
this.details_.inlinedFrameIndex());
var result = [];
for (var i = 0; i < scopeDetails.length; ++i) {
result.push(new ScopeMirror(this, UNDEFINED, i, scopeDetails[i]));
}
return result;
};
FrameMirror.prototype.stepInPositions = function() {
var script = this.func().script();
var funcOffset = this.func().sourcePosition_();
......@@ -1878,17 +1890,18 @@ FrameMirror.prototype.toText = function(opt_locals) {
var kScopeDetailsTypeIndex = 0;
var kScopeDetailsObjectIndex = 1;
function ScopeDetails(frame, fun, index) {
function ScopeDetails(frame, fun, index, opt_details) {
if (frame) {
this.break_id_ = frame.break_id_;
this.details_ = %GetScopeDetails(frame.break_id_,
this.details_ = opt_details ||
%GetScopeDetails(frame.break_id_,
frame.details_.frameId(),
frame.details_.inlinedFrameIndex(),
index);
this.frame_id_ = frame.details_.frameId();
this.inlined_frame_id_ = frame.details_.inlinedFrameIndex();
} else {
this.details_ = %GetFunctionScopeDetails(fun.value(), index);
this.details_ = opt_details || %GetFunctionScopeDetails(fun.value(), index);
this.fun_value_ = fun.value();
this.break_id_ = undefined;
}
......@@ -1934,10 +1947,11 @@ ScopeDetails.prototype.setVariableValueImpl = function(name, new_value) {
* @param {FrameMirror} frame The frame this scope is a part of
* @param {FunctionMirror} function The function this scope is a part of
* @param {number} index The scope index in the frame
* @param {Array=} opt_details Raw scope details data
* @constructor
* @extends Mirror
*/
function ScopeMirror(frame, function, index) {
function ScopeMirror(frame, function, index, opt_details) {
%_CallFunction(this, SCOPE_TYPE, Mirror);
if (frame) {
this.frame_index_ = frame.index_;
......@@ -1945,7 +1959,7 @@ function ScopeMirror(frame, function, index) {
this.frame_index_ = undefined;
}
this.scope_index_ = index;
this.details_ = new ScopeDetails(frame, function, index);
this.details_ = new ScopeDetails(frame, function, index, opt_details);
}
inherits(ScopeMirror, Mirror);
......
......@@ -12177,7 +12177,7 @@ static const int kScopeDetailsObjectIndex = 1;
static const int kScopeDetailsSize = 2;
static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
static Handle<JSObject> MaterializeScopeDetails(Isolate* isolate,
ScopeIterator* it) {
// Calculate the size of the result.
int details_size = kScopeDetailsSize;
......@@ -12186,10 +12186,10 @@ static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
// Fill in scope details.
details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
Handle<JSObject> scope_object = it->ScopeObject();
RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
RETURN_IF_EMPTY_HANDLE_VALUE(isolate, scope_object, Handle<JSObject>());
details->set(kScopeDetailsObjectIndex, *scope_object);
return *isolate->factory()->NewJSArrayWithElements(details);
return isolate->factory()->NewJSArrayWithElements(details);
}
......@@ -12230,7 +12230,51 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
if (it.Done()) {
return isolate->heap()->undefined_value();
}
return MaterializeScopeDetails(isolate, &it);
Handle<JSObject> details = MaterializeScopeDetails(isolate, &it);
RETURN_IF_EMPTY_HANDLE(isolate, details);
return *details;
}
// Return an array of scope details
// args[0]: number: break id
// args[1]: number: frame index
// args[2]: number: inlined frame index
//
// The array returned contains arrays with the following information:
// 0: Scope type
// 1: Scope object
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAllScopesDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
// Check arguments.
Object* check;
{ MaybeObject* maybe_check = Runtime_CheckExecutionState(
RUNTIME_ARGUMENTS(isolate, args));
if (!maybe_check->ToObject(&check)) return maybe_check;
}
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
// Get the frame where the debugging is performed.
StackFrame::Id id = UnwrapFrameId(wrapped_id);
JavaScriptFrameIterator frame_it(isolate, id);
JavaScriptFrame* frame = frame_it.frame();
List<Handle<JSObject> > result(4);
ScopeIterator it(isolate, frame, inlined_jsframe_index);
for (; !it.Done(); it.Next()) {
Handle<JSObject> details = MaterializeScopeDetails(isolate, &it);
RETURN_IF_EMPTY_HANDLE(isolate, details);
result.Add(details);
}
Handle<FixedArray> array = isolate->factory()->NewFixedArray(result.length());
for (int i = 0; i < result.length(); ++i) {
array->set(i, *result[i]);
}
return *isolate->factory()->NewJSArrayWithElements(array);
}
......@@ -12269,7 +12313,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
return isolate->heap()->undefined_value();
}
return MaterializeScopeDetails(isolate, &it);
Handle<JSObject> details = MaterializeScopeDetails(isolate, &it);
RETURN_IF_EMPTY_HANDLE(isolate, details);
return *details;
}
......
......@@ -492,6 +492,7 @@ namespace internal {
F(GetScopeCount, 2, 1) \
F(GetStepInPositions, 2, 1) \
F(GetScopeDetails, 4, 1) \
F(GetAllScopesDetails, 3, 1) \
F(GetFunctionScopeCount, 1, 1) \
F(GetFunctionScopeDetails, 2, 1) \
F(SetScopeVariableValue, 6, 1) \
......
......@@ -76,13 +76,24 @@ function EndTest() {
}
// Check that two scope are the same.
function CheckScopeMirrors(scope1, scope2) {
assertEquals(scope1.scopeType(), scope2.scopeType());
assertEquals(scope1.frameIndex(), scope2.frameIndex());
assertEquals(scope1.scopeIndex(), scope2.scopeIndex());
}
// Check that the scope chain contains the expected types of scopes.
function CheckScopeChain(scopes, exec_state) {
var all_scopes = exec_state.frame().allScopes();
assertEquals(scopes.length, exec_state.frame().scopeCount());
assertEquals(scopes.length, all_scopes.length, "FrameMirror.allScopes length");
for (var i = 0; i < scopes.length; i++) {
var scope = exec_state.frame().scope(i);
assertTrue(scope.isScope());
assertEquals(scopes[i], scope.scopeType());
CheckScopeMirrors(all_scopes[i], scope);
// Check the global object when hitting the global scope.
if (scopes[i] == debug.ScopeType.Global) {
......
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