Revision: 20162
Author: u...@chromium.org
Date: Fri Mar 21 12:30:58 2014 UTC
Log: Add option to run ScopeIterator faster giving up nested scope
chain.
We'd like to be able to trade nested scope chain info (consisting of with,
block and catch scopes) in favor of speed in some cases.
BUG=chromium:340285
LOG=N
R=u...@chromium.org, pfeldman, ulan, yangguo
Review URL: https://codereview.chromium.org/203463011
Patch from Andrey Adaykin <aand...@chromium.org>.
http://code.google.com/p/v8/source/detail?r=20162
Modified:
/branches/bleeding_edge/src/mirror-debugger.js
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
/branches/bleeding_edge/test/mjsunit/debug-scopes.js
=======================================
--- /branches/bleeding_edge/src/mirror-debugger.js Fri Mar 14 15:10:01 2014
UTC
+++ /branches/bleeding_edge/src/mirror-debugger.js Fri Mar 21 12:30:58 2014
UTC
@@ -1692,10 +1692,11 @@
};
-FrameMirror.prototype.allScopes = function() {
+FrameMirror.prototype.allScopes = function(opt_ignore_nested_scopes) {
var scopeDetails = %GetAllScopesDetails(this.break_id_,
this.details_.frameId(),
-
this.details_.inlinedFrameIndex());
+
this.details_.inlinedFrameIndex(),
+ !!opt_ignore_nested_scopes);
var result = [];
for (var i = 0; i < scopeDetails.length; ++i) {
result.push(new ScopeMirror(this, UNDEFINED, i, scopeDetails[i]));
=======================================
--- /branches/bleeding_edge/src/runtime.cc Fri Mar 21 08:30:42 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc Fri Mar 21 12:30:58 2014 UTC
@@ -11815,7 +11815,8 @@
ScopeIterator(Isolate* isolate,
JavaScriptFrame* frame,
- int inlined_jsframe_index)
+ int inlined_jsframe_index,
+ bool ignore_nested_scopes = false)
: isolate_(isolate),
frame_(frame),
inlined_jsframe_index_(inlined_jsframe_index),
@@ -11839,19 +11840,31 @@
// Return if ensuring debug info failed.
return;
}
- Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
+
+ // Currently it takes too much time to find nested scopes due to script
+ // parsing. Sometimes we want to run the ScopeIterator as fast as
possible
+ // (for example, while collecting async call stacks on every
+ // addEventListener call), even if we drop some nested scopes.
+ // Later we may optimize getting the nested scopes (cache the result?)
+ // and include nested scopes into the "fast" iteration case as well.
+ if (!ignore_nested_scopes) {
+ Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
- // Find the break point where execution has stopped.
- BreakLocationIterator break_location_iterator(debug_info,
- ALL_BREAK_LOCATIONS);
- // pc points to the instruction after the current one, possibly a break
- // location as well. So the "- 1" to exclude it from the search.
- break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
- if (break_location_iterator.IsExit()) {
- // We are within the return sequence. At the momemt it is not
possible to
+ // Find the break point where execution has stopped.
+ BreakLocationIterator break_location_iterator(debug_info,
+ ALL_BREAK_LOCATIONS);
+ // pc points to the instruction after the current one, possibly a
break
+ // location as well. So the "- 1" to exclude it from the search.
+ break_location_iterator.FindBreakLocationFromAddress(frame->pc() -
1);
+
+ // Within the return sequence at the moment it is not possible to
// get a source position which is consistent with the current scope
chain.
// Thus all nested with, catch and block contexts are skipped and we
only
// provide the function scope.
+ ignore_nested_scopes = break_location_iterator.IsExit();
+ }
+
+ if (ignore_nested_scopes) {
if (scope_info->HasContext()) {
context_ = Handle<Context>(context_->declaration_context(),
isolate_);
} else {
@@ -11859,7 +11872,7 @@
context_ = Handle<Context>(context_->previous(), isolate_);
}
}
- if (scope_info->scope_type() != EVAL_SCOPE) {
+ if (scope_info->scope_type() == FUNCTION_SCOPE) {
nested_scope_chain_.Add(scope_info);
}
} else {
@@ -12327,13 +12340,14 @@
// args[0]: number: break id
// args[1]: number: frame index
// args[2]: number: inlined frame index
+// args[3]: boolean: ignore nested scopes
//
// 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);
+ ASSERT(args.length() == 3 || args.length() == 4);
// Check arguments.
Object* check;
@@ -12343,6 +12357,12 @@
}
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
+
+ bool ignore_nested_scopes = false;
+ if (args.length() == 4) {
+ CONVERT_BOOLEAN_ARG_CHECKED(flag, 3);
+ ignore_nested_scopes = flag;
+ }
// Get the frame where the debugging is performed.
StackFrame::Id id = UnwrapFrameId(wrapped_id);
@@ -12350,7 +12370,7 @@
JavaScriptFrame* frame = frame_it.frame();
List<Handle<JSObject> > result(4);
- ScopeIterator it(isolate, frame, inlined_jsframe_index);
+ ScopeIterator it(isolate, frame, inlined_jsframe_index,
ignore_nested_scopes);
for (; !it.Done(); it.Next()) {
Handle<JSObject> details = MaterializeScopeDetails(isolate, &it);
RETURN_IF_EMPTY_HANDLE(isolate, details);
=======================================
--- /branches/bleeding_edge/src/runtime.h Thu Mar 20 16:13:09 2014 UTC
+++ /branches/bleeding_edge/src/runtime.h Fri Mar 21 12:30:58 2014 UTC
@@ -495,7 +495,7 @@
F(GetScopeCount, 2, 1) \
F(GetStepInPositions, 2, 1) \
F(GetScopeDetails, 4, 1) \
- F(GetAllScopesDetails, 3, 1) \
+ F(GetAllScopesDetails, 4, 1) \
F(GetFunctionScopeCount, 1, 1) \
F(GetFunctionScopeDetails, 2, 1) \
F(SetScopeVariableValue, 6, 1) \
=======================================
--- /branches/bleeding_edge/test/mjsunit/debug-scopes.js Fri Mar 7
11:03:35 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/debug-scopes.js Fri Mar 21
12:30:58 2014 UTC
@@ -71,16 +71,29 @@
// Check result of a test.
function EndTest() {
assertTrue(listener_called, "listerner not called for " + test_name);
- assertNull(exception, test_name);
+ assertNull(exception, test_name + " / " + exception);
end_test_count++;
}
// Check that two scope are the same.
-function CheckScopeMirrors(scope1, scope2) {
+function assertScopeMirrorEquals(scope1, scope2) {
assertEquals(scope1.scopeType(), scope2.scopeType());
assertEquals(scope1.frameIndex(), scope2.frameIndex());
assertEquals(scope1.scopeIndex(), scope2.scopeIndex());
+ assertPropertiesEqual(scope1.scopeObject().value(),
scope2.scopeObject().value());
+}
+
+function CheckFastAllScopes(scopes, exec_state)
+{
+ var fast_all_scopes = exec_state.frame().allScopes(true);
+ var length = fast_all_scopes.length;
+ assertTrue(scopes.length >= length);
+ for (var i = 0; i < scopes.length && i < length; i++) {
+ var scope = fast_all_scopes[length - i - 1];
+ assertTrue(scope.isScope());
+ assertEquals(scopes[scopes.length - i - 1], scope.scopeType());
+ }
}
@@ -93,7 +106,7 @@
var scope = exec_state.frame().scope(i);
assertTrue(scope.isScope());
assertEquals(scopes[i], scope.scopeType());
- CheckScopeMirrors(all_scopes[i], scope);
+ assertScopeMirrorEquals(all_scopes[i], scope);
// Check the global object when hitting the global scope.
if (scopes[i] == debug.ScopeType.Global) {
@@ -102,6 +115,7 @@
assertPropertiesEqual(this, scope.scopeObject().value());
}
}
+ CheckFastAllScopes(scopes, exec_state);
// Get the debug command processor.
var dcp = exec_state.debugCommandProcessor("unspecified_running_state");
--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.