Reviewers: pfeldman, ulan, yangguo,
Description:
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
R=yangguo, ulan, pfeldman
Please review this at https://codereview.chromium.org/203463011/
SVN Base: git://github.com/v8/v8.git@master
Affected files (+54, -17 lines):
M src/mirror-debugger.js
M src/runtime.cc
M test/mjsunit/debug-scopes.js
Index: src/mirror-debugger.js
diff --git a/src/mirror-debugger.js b/src/mirror-debugger.js
index
f288123bcafad8ea3ea01b9f626ebe8a7c612d32..05458601f8ddea9789644d6e092e256b8e364dcb
100644
--- a/src/mirror-debugger.js
+++ b/src/mirror-debugger.js
@@ -1692,10 +1692,11 @@ FrameMirror.prototype.scope = function(index) {
};
-FrameMirror.prototype.allScopes = function() {
+FrameMirror.prototype.allScopes = function(opt_fast) {
var scopeDetails = %GetAllScopesDetails(this.break_id_,
this.details_.frameId(),
-
this.details_.inlinedFrameIndex());
+
this.details_.inlinedFrameIndex(),
+ opt_fast);
var result = [];
for (var i = 0; i < scopeDetails.length; ++i) {
result.push(new ScopeMirror(this, UNDEFINED, i, scopeDetails[i]));
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index
4bca2c70c77f35cd8b0cdc0711d4a4af08c2faf2..99d1019ccf6ceeb2ac4b909ba26ed06837edf14f
100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -11733,7 +11733,8 @@ class ScopeIterator {
ScopeIterator(Isolate* isolate,
JavaScriptFrame* frame,
- int inlined_jsframe_index)
+ int inlined_jsframe_index,
+ bool fast = false)
: isolate_(isolate),
frame_(frame),
inlined_jsframe_index_(inlined_jsframe_index),
@@ -11757,19 +11758,33 @@ class ScopeIterator {
// Return if ensuring debug info failed.
return;
}
- 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
+ // 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.
+ bool upto_local_scope = fast;
+
+ if (!upto_local_scope) {
+ 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);
+
+ // 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.
+ upto_local_scope = break_location_iterator.IsExit();
+ }
+
+ if (upto_local_scope) {
if (scope_info->HasContext()) {
context_ = Handle<Context>(context_->declaration_context(),
isolate_);
} else {
@@ -12245,13 +12260,14 @@ RUNTIME_FUNCTION(MaybeObject*,
Runtime_GetScopeDetails) {
// args[0]: number: break id
// args[1]: number: frame index
// args[2]: number: inlined frame index
+// args[3]: boolean: fast bit
//
// 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;
@@ -12262,13 +12278,19 @@ RUNTIME_FUNCTION(MaybeObject*,
Runtime_GetAllScopesDetails) {
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
+ bool fast = false;
+ if (args.length() == 4) {
+ CONVERT_BOOLEAN_ARG_CHECKED(fast_flag, 3);
+ fast = fast_flag;
+ }
+
// 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);
+ ScopeIterator it(isolate, frame, inlined_jsframe_index, fast);
for (; !it.Done(); it.Next()) {
Handle<JSObject> details = MaterializeScopeDetails(isolate, &it);
RETURN_IF_EMPTY_HANDLE(isolate, details);
Index: test/mjsunit/debug-scopes.js
diff --git a/test/mjsunit/debug-scopes.js b/test/mjsunit/debug-scopes.js
index
57adf236ffbafb3adaf463cfafd5ae7a167aa121..f5b5ec913ed6634dacface1cc90d176646d92513
100644
--- a/test/mjsunit/debug-scopes.js
+++ b/test/mjsunit/debug-scopes.js
@@ -71,16 +71,29 @@ function BeginTest(name) {
// 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 @@ function CheckScopeChain(scopes, exec_state) {
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 @@ function CheckScopeChain(scopes, exec_state) {
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
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/d/optout.