Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: src/debug/debug-scopes.cc

Issue 1500933002: [debugger] fix debug-evaluate wrt shadowed context var. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: add TODO Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/debug/debug-scopes.h" 5 #include "src/debug/debug-scopes.h"
6 6
7 #include "src/ast/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/debug/debug.h" 8 #include "src/debug/debug.h"
9 #include "src/frames-inl.h" 9 #include "src/frames-inl.h"
10 #include "src/globals.h" 10 #include "src/globals.h"
11 #include "src/isolate-inl.h" 11 #include "src/isolate-inl.h"
12 #include "src/parsing/parser.h" 12 #include "src/parsing/parser.h"
13 13
14 namespace v8 { 14 namespace v8 {
15 namespace internal { 15 namespace internal {
16 16
17 ScopeIterator::ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector, 17 ScopeIterator::ScopeIterator(Isolate* isolate, FrameInspector* frame_inspector,
18 bool ignore_nested_scopes) 18 ScopeIterator::Option option)
19 : isolate_(isolate), 19 : isolate_(isolate),
20 frame_inspector_(frame_inspector), 20 frame_inspector_(frame_inspector),
21 nested_scope_chain_(4), 21 nested_scope_chain_(4),
22 non_locals_(nullptr),
22 seen_script_scope_(false), 23 seen_script_scope_(false),
23 failed_(false) { 24 failed_(false) {
24 if (!frame_inspector->GetContext()->IsContext() || 25 if (!frame_inspector->GetContext()->IsContext() ||
25 !frame_inspector->GetFunction()->IsJSFunction()) { 26 !frame_inspector->GetFunction()->IsJSFunction()) {
26 // Optimized frame, context or function cannot be materialized. Give up. 27 // Optimized frame, context or function cannot be materialized. Give up.
27 return; 28 return;
28 } 29 }
29 30
30 context_ = Handle<Context>(Context::cast(frame_inspector->GetContext())); 31 context_ = Handle<Context>(Context::cast(frame_inspector->GetContext()));
31 32
32 // Catch the case when the debugger stops in an internal function. 33 // Catch the case when the debugger stops in an internal function.
33 Handle<JSFunction> function = GetFunction(); 34 Handle<JSFunction> function = GetFunction();
34 Handle<SharedFunctionInfo> shared_info(function->shared()); 35 Handle<SharedFunctionInfo> shared_info(function->shared());
35 Handle<ScopeInfo> scope_info(shared_info->scope_info()); 36 Handle<ScopeInfo> scope_info(shared_info->scope_info());
36 if (shared_info->script() == isolate->heap()->undefined_value()) { 37 if (shared_info->script() == isolate->heap()->undefined_value()) {
37 while (context_->closure() == *function) { 38 while (context_->closure() == *function) {
38 context_ = Handle<Context>(context_->previous(), isolate_); 39 context_ = Handle<Context>(context_->previous(), isolate_);
39 } 40 }
40 return; 41 return;
41 } 42 }
42 43
43 // Currently it takes too much time to find nested scopes due to script 44 // Currently it takes too much time to find nested scopes due to script
44 // parsing. Sometimes we want to run the ScopeIterator as fast as possible 45 // parsing. Sometimes we want to run the ScopeIterator as fast as possible
45 // (for example, while collecting async call stacks on every 46 // (for example, while collecting async call stacks on every
46 // addEventListener call), even if we drop some nested scopes. 47 // addEventListener call), even if we drop some nested scopes.
47 // Later we may optimize getting the nested scopes (cache the result?) 48 // Later we may optimize getting the nested scopes (cache the result?)
48 // and include nested scopes into the "fast" iteration case as well. 49 // and include nested scopes into the "fast" iteration case as well.
49 50 bool ignore_nested_scopes = (option == IGNORE_NESTED_SCOPES);
51 bool collect_non_locals = (option == COLLECT_NON_LOCALS);
50 if (!ignore_nested_scopes && shared_info->HasDebugInfo()) { 52 if (!ignore_nested_scopes && shared_info->HasDebugInfo()) {
51 // The source position at return is always the end of the function, 53 // The source position at return is always the end of the function,
52 // which is not consistent with the current scope chain. Therefore all 54 // which is not consistent with the current scope chain. Therefore all
53 // nested with, catch and block contexts are skipped, and we can only 55 // nested with, catch and block contexts are skipped, and we can only
54 // inspect the function scope. 56 // inspect the function scope.
55 // This can only happen if we set a break point inside right before the 57 // This can only happen if we set a break point inside right before the
56 // return, which requires a debug info to be available. 58 // return, which requires a debug info to be available.
57 Handle<DebugInfo> debug_info(shared_info->GetDebugInfo()); 59 Handle<DebugInfo> debug_info(shared_info->GetDebugInfo());
58 60
59 // PC points to the instruction after the current one, possibly a break 61 // PC points to the instruction after the current one, possibly a break
(...skipping 11 matching lines...) Expand all
71 if (scope_info->HasContext()) { 73 if (scope_info->HasContext()) {
72 context_ = Handle<Context>(context_->declaration_context(), isolate_); 74 context_ = Handle<Context>(context_->declaration_context(), isolate_);
73 } else { 75 } else {
74 while (context_->closure() == *function) { 76 while (context_->closure() == *function) {
75 context_ = Handle<Context>(context_->previous(), isolate_); 77 context_ = Handle<Context>(context_->previous(), isolate_);
76 } 78 }
77 } 79 }
78 if (scope_info->scope_type() == FUNCTION_SCOPE) { 80 if (scope_info->scope_type() == FUNCTION_SCOPE) {
79 nested_scope_chain_.Add(scope_info); 81 nested_scope_chain_.Add(scope_info);
80 } 82 }
83 if (!collect_non_locals) return;
84 }
85
86 // Reparse the code and analyze the scopes.
87 Scope* scope = NULL;
88 // Check whether we are in global, eval or function code.
89 Zone zone;
90 if (scope_info->scope_type() != FUNCTION_SCOPE) {
91 // Global or eval code.
92 Handle<Script> script(Script::cast(shared_info->script()));
93 ParseInfo info(&zone, script);
94 if (scope_info->scope_type() == SCRIPT_SCOPE) {
95 info.set_global();
96 } else {
97 DCHECK(scope_info->scope_type() == EVAL_SCOPE);
98 info.set_eval();
99 info.set_context(Handle<Context>(function->context()));
100 }
101 if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
102 scope = info.literal()->scope();
103 }
104 if (!ignore_nested_scopes) RetrieveScopeChain(scope);
105 if (collect_non_locals) CollectNonLocals(scope);
81 } else { 106 } else {
82 // Reparse the code and analyze the scopes. 107 // Function code
83 Handle<Script> script(Script::cast(shared_info->script())); 108 ParseInfo info(&zone, function);
84 Scope* scope = NULL; 109 if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
85 110 scope = info.literal()->scope();
86 // Check whether we are in global, eval or function code.
87 Zone zone;
88 if (scope_info->scope_type() != FUNCTION_SCOPE) {
89 // Global or eval code.
90 ParseInfo info(&zone, script);
91 if (scope_info->scope_type() == SCRIPT_SCOPE) {
92 info.set_global();
93 } else {
94 DCHECK(scope_info->scope_type() == EVAL_SCOPE);
95 info.set_eval();
96 info.set_context(Handle<Context>(function->context()));
97 }
98 if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
99 scope = info.literal()->scope();
100 }
101 RetrieveScopeChain(scope, shared_info);
102 } else {
103 // Function code
104 ParseInfo info(&zone, function);
105 if (Parser::ParseStatic(&info) && Scope::Analyze(&info)) {
106 scope = info.literal()->scope();
107 }
108 RetrieveScopeChain(scope, shared_info);
109 } 111 }
112 if (!ignore_nested_scopes) RetrieveScopeChain(scope);
113 if (collect_non_locals) CollectNonLocals(scope);
110 } 114 }
111 } 115 }
112 116
113 117
114 ScopeIterator::ScopeIterator(Isolate* isolate, Handle<JSFunction> function) 118 ScopeIterator::ScopeIterator(Isolate* isolate, Handle<JSFunction> function)
115 : isolate_(isolate), 119 : isolate_(isolate),
116 frame_inspector_(NULL), 120 frame_inspector_(NULL),
117 context_(function->context()), 121 context_(function->context()),
122 non_locals_(nullptr),
118 seen_script_scope_(false), 123 seen_script_scope_(false),
119 failed_(false) { 124 failed_(false) {
120 if (!function->shared()->IsSubjectToDebugging()) context_ = Handle<Context>(); 125 if (!function->shared()->IsSubjectToDebugging()) context_ = Handle<Context>();
121 } 126 }
122 127
123 128
124 MUST_USE_RESULT MaybeHandle<JSObject> ScopeIterator::MaterializeScopeDetails() { 129 MUST_USE_RESULT MaybeHandle<JSObject> ScopeIterator::MaterializeScopeDetails() {
125 // Calculate the size of the result. 130 // Calculate the size of the result.
126 Handle<FixedArray> details = 131 Handle<FixedArray> details =
127 isolate_->factory()->NewFixedArray(kScopeDetailsSize); 132 isolate_->factory()->NewFixedArray(kScopeDetailsSize);
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 if (Type() == ScopeTypeGlobal || Type() == ScopeTypeScript || 318 if (Type() == ScopeTypeGlobal || Type() == ScopeTypeScript ||
314 nested_scope_chain_.is_empty()) { 319 nested_scope_chain_.is_empty()) {
315 return context_; 320 return context_;
316 } else if (nested_scope_chain_.last()->HasContext()) { 321 } else if (nested_scope_chain_.last()->HasContext()) {
317 return context_; 322 return context_;
318 } else { 323 } else {
319 return Handle<Context>(); 324 return Handle<Context>();
320 } 325 }
321 } 326 }
322 327
328
329 void ScopeIterator::GetNonLocals(List<Handle<String> >* list_out) {
330 Handle<String> this_string = isolate_->factory()->this_string();
331 for (HashMap::Entry* entry = non_locals_->Start(); entry != nullptr;
332 entry = non_locals_->Next(entry)) {
333 Handle<String> name(reinterpret_cast<String**>(entry->key));
334 // We need to treat "this" differently.
335 if (name.is_identical_to(this_string)) continue;
336 list_out->Add(Handle<String>(reinterpret_cast<String**>(entry->key)));
337 }
338 }
339
340
341 bool ScopeIterator::ThisIsNonLocal() {
342 Handle<String> this_string = isolate_->factory()->this_string();
343 void* key = reinterpret_cast<void*>(this_string.location());
344 HashMap::Entry* entry = non_locals_->Lookup(key, this_string->Hash());
345 return entry != nullptr;
346 }
347
348
323 #ifdef DEBUG 349 #ifdef DEBUG
324 // Debug print of the content of the current scope. 350 // Debug print of the content of the current scope.
325 void ScopeIterator::DebugPrint() { 351 void ScopeIterator::DebugPrint() {
326 OFStream os(stdout); 352 OFStream os(stdout);
327 DCHECK(!failed_); 353 DCHECK(!failed_);
328 switch (Type()) { 354 switch (Type()) {
329 case ScopeIterator::ScopeTypeGlobal: 355 case ScopeIterator::ScopeTypeGlobal:
330 os << "Global:\n"; 356 os << "Global:\n";
331 CurrentContext()->Print(os); 357 CurrentContext()->Print(os);
332 break; 358 break;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 break; 404 break;
379 405
380 default: 406 default:
381 UNREACHABLE(); 407 UNREACHABLE();
382 } 408 }
383 PrintF("\n"); 409 PrintF("\n");
384 } 410 }
385 #endif 411 #endif
386 412
387 413
388 void ScopeIterator::RetrieveScopeChain(Scope* scope, 414 void ScopeIterator::RetrieveScopeChain(Scope* scope) {
389 Handle<SharedFunctionInfo> shared_info) {
390 if (scope != NULL) { 415 if (scope != NULL) {
391 int source_position = frame_inspector_->GetSourcePosition(); 416 int source_position = frame_inspector_->GetSourcePosition();
392 scope->GetNestedScopeChain(isolate_, &nested_scope_chain_, source_position); 417 scope->GetNestedScopeChain(isolate_, &nested_scope_chain_, source_position);
393 } else { 418 } else {
394 // A failed reparse indicates that the preparser has diverged from the 419 // A failed reparse indicates that the preparser has diverged from the
395 // parser or that the preparse data given to the initial parse has been 420 // parser or that the preparse data given to the initial parse has been
396 // faulty. We fail in debug mode but in release mode we only provide the 421 // faulty. We fail in debug mode but in release mode we only provide the
397 // information we get from the context chain but nothing about 422 // information we get from the context chain but nothing about
398 // completely stack allocated scopes or stack allocated locals. 423 // completely stack allocated scopes or stack allocated locals.
399 // Or it could be due to stack overflow. 424 // Or it could be due to stack overflow.
400 DCHECK(isolate_->has_pending_exception()); 425 DCHECK(isolate_->has_pending_exception());
401 failed_ = true; 426 failed_ = true;
402 } 427 }
403 } 428 }
404 429
405 430
431 void ScopeIterator::CollectNonLocals(Scope* scope) {
432 if (scope != NULL) {
433 DCHECK_NULL(non_locals_);
434 non_locals_ = new HashMap(InternalizedStringMatch);
435 scope->CollectNonLocals(non_locals_);
436 }
437 }
438
439
406 MaybeHandle<JSObject> ScopeIterator::MaterializeScriptScope() { 440 MaybeHandle<JSObject> ScopeIterator::MaterializeScriptScope() {
407 Handle<JSGlobalObject> global(CurrentContext()->global_object()); 441 Handle<JSGlobalObject> global(CurrentContext()->global_object());
408 Handle<ScriptContextTable> script_contexts( 442 Handle<ScriptContextTable> script_contexts(
409 global->native_context()->script_context_table()); 443 global->native_context()->script_context_table());
410 444
411 Handle<JSObject> script_scope = 445 Handle<JSObject> script_scope =
412 isolate_->factory()->NewJSObject(isolate_->object_function()); 446 isolate_->factory()->NewJSObject(isolate_->object_function());
413 447
414 for (int context_index = 0; context_index < script_contexts->used(); 448 for (int context_index = 0; context_index < script_contexts->used();
415 context_index++) { 449 context_index++) {
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
783 isolate_, value, Object::GetPropertyOrElement(extension, key), false); 817 isolate_, value, Object::GetPropertyOrElement(extension, key), false);
784 RETURN_ON_EXCEPTION_VALUE( 818 RETURN_ON_EXCEPTION_VALUE(
785 isolate_, JSObject::SetOwnPropertyIgnoreAttributes( 819 isolate_, JSObject::SetOwnPropertyIgnoreAttributes(
786 scope_object, key, value, NONE), false); 820 scope_object, key, value, NONE), false);
787 } 821 }
788 return true; 822 return true;
789 } 823 }
790 824
791 } // namespace internal 825 } // namespace internal
792 } // namespace v8 826 } // namespace v8
OLDNEW
« src/ast/scopes.h ('K') | « src/debug/debug-scopes.h ('k') | src/runtime/runtime-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698