OLD | NEW |
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 <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/ast/ast.h" | 9 #include "src/ast/ast.h" |
10 #include "src/ast/scopes.h" | 10 #include "src/ast/scopes.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 ScopeIterator::Option option) | 23 ScopeIterator::Option option) |
24 : isolate_(isolate), | 24 : isolate_(isolate), |
25 frame_inspector_(frame_inspector), | 25 frame_inspector_(frame_inspector), |
26 nested_scope_chain_(4), | 26 nested_scope_chain_(4), |
27 seen_script_scope_(false) { | 27 seen_script_scope_(false) { |
28 if (!frame_inspector->GetContext()->IsContext()) { | 28 if (!frame_inspector->GetContext()->IsContext()) { |
29 // Optimized frame, context or function cannot be materialized. Give up. | 29 // Optimized frame, context or function cannot be materialized. Give up. |
30 return; | 30 return; |
31 } | 31 } |
32 | 32 |
33 context_ = Handle<Context>::cast(frame_inspector->GetContext()); | |
34 | |
35 // We should not instantiate a ScopeIterator for wasm frames. | 33 // We should not instantiate a ScopeIterator for wasm frames. |
36 DCHECK(frame_inspector->GetScript()->type() != Script::TYPE_WASM); | 34 DCHECK(frame_inspector->GetScript()->type() != Script::TYPE_WASM); |
37 | 35 |
| 36 TryParseAndRetrieveScopes(option); |
| 37 } |
| 38 |
| 39 void ScopeIterator::TryParseAndRetrieveScopes(ScopeIterator::Option option) { |
| 40 context_ = GetContext(); |
| 41 |
38 // Catch the case when the debugger stops in an internal function. | 42 // Catch the case when the debugger stops in an internal function. |
39 Handle<JSFunction> function = GetFunction(); | 43 Handle<JSFunction> function = GetFunction(); |
40 Handle<SharedFunctionInfo> shared_info(function->shared()); | 44 Handle<SharedFunctionInfo> shared_info(function->shared()); |
41 Handle<ScopeInfo> scope_info(shared_info->scope_info()); | 45 Handle<ScopeInfo> scope_info(shared_info->scope_info()); |
42 if (shared_info->script()->IsUndefined(isolate)) { | 46 if (shared_info->script()->IsUndefined(isolate_)) { |
43 while (context_->closure() == *function) { | 47 while (context_->closure() == *function) { |
44 context_ = Handle<Context>(context_->previous(), isolate_); | 48 context_ = Handle<Context>(context_->previous(), isolate_); |
45 } | 49 } |
46 return; | 50 return; |
47 } | 51 } |
48 | 52 |
49 // Currently it takes too much time to find nested scopes due to script | 53 // Currently it takes too much time to find nested scopes due to script |
50 // parsing. Sometimes we want to run the ScopeIterator as fast as possible | 54 // parsing. Sometimes we want to run the ScopeIterator as fast as possible |
51 // (for example, while collecting async call stacks on every | 55 // (for example, while collecting async call stacks on every |
52 // addEventListener call), even if we drop some nested scopes. | 56 // addEventListener call), even if we drop some nested scopes. |
53 // Later we may optimize getting the nested scopes (cache the result?) | 57 // Later we may optimize getting the nested scopes (cache the result?) |
54 // and include nested scopes into the "fast" iteration case as well. | 58 // and include nested scopes into the "fast" iteration case as well. |
55 bool ignore_nested_scopes = (option == IGNORE_NESTED_SCOPES); | 59 bool ignore_nested_scopes = (option == IGNORE_NESTED_SCOPES); |
56 bool collect_non_locals = (option == COLLECT_NON_LOCALS); | 60 bool collect_non_locals = (option == COLLECT_NON_LOCALS); |
57 if (!ignore_nested_scopes && shared_info->HasDebugInfo()) { | 61 if (!ignore_nested_scopes && shared_info->HasDebugInfo() && |
| 62 frame_inspector_ != nullptr) { |
58 // The source position at return is always the end of the function, | 63 // The source position at return is always the end of the function, |
59 // which is not consistent with the current scope chain. Therefore all | 64 // which is not consistent with the current scope chain. Therefore all |
60 // nested with, catch and block contexts are skipped, and we can only | 65 // nested with, catch and block contexts are skipped, and we can only |
61 // inspect the function scope. | 66 // inspect the function scope. |
62 // This can only happen if we set a break point inside right before the | 67 // This can only happen if we set a break point inside right before the |
63 // return, which requires a debug info to be available. | 68 // return, which requires a debug info to be available. |
64 Handle<DebugInfo> debug_info(shared_info->GetDebugInfo()); | 69 Handle<DebugInfo> debug_info(shared_info->GetDebugInfo()); |
65 | 70 |
66 // Find the break point where execution has stopped. | 71 // Find the break point where execution has stopped. |
67 BreakLocation location = BreakLocation::FromFrame(debug_info, GetFrame()); | 72 BreakLocation location = BreakLocation::FromFrame(debug_info, GetFrame()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 info->set_language_mode(shared_info->language_mode()); | 107 info->set_language_mode(shared_info->language_mode()); |
103 } else if (scope_info->scope_type() == MODULE_SCOPE) { | 108 } else if (scope_info->scope_type() == MODULE_SCOPE) { |
104 info->set_module(); | 109 info->set_module(); |
105 } else { | 110 } else { |
106 DCHECK(scope_info->scope_type() == SCRIPT_SCOPE); | 111 DCHECK(scope_info->scope_type() == SCRIPT_SCOPE); |
107 } | 112 } |
108 } else { | 113 } else { |
109 // Inner function. | 114 // Inner function. |
110 info.reset(new ParseInfo(shared_info)); | 115 info.reset(new ParseInfo(shared_info)); |
111 } | 116 } |
112 if (parsing::ParseAny(info.get(), isolate) && | 117 if (parsing::ParseAny(info.get(), isolate_) && |
113 Rewriter::Rewrite(info.get(), isolate)) { | 118 Rewriter::Rewrite(info.get(), isolate_)) { |
114 DeclarationScope* scope = info->literal()->scope(); | 119 DeclarationScope* scope = info->literal()->scope(); |
115 if (!ignore_nested_scopes || collect_non_locals) { | 120 if (!ignore_nested_scopes || collect_non_locals) { |
116 CollectNonLocals(info.get(), scope); | 121 CollectNonLocals(info.get(), scope); |
117 } | 122 } |
118 if (!ignore_nested_scopes) { | 123 if (!ignore_nested_scopes) { |
119 DeclarationScope::Analyze(info.get(), isolate_, AnalyzeMode::kDebugger); | 124 DeclarationScope::Analyze(info.get(), isolate_, AnalyzeMode::kDebugger); |
120 RetrieveScopeChain(scope); | 125 RetrieveScopeChain(scope); |
121 } | 126 } |
122 } else { | 127 } else { |
123 // A failed reparse indicates that the preparser has diverged from the | 128 // A failed reparse indicates that the preparser has diverged from the |
124 // parser or that the preparse data given to the initial parse has been | 129 // parser or that the preparse data given to the initial parse has been |
125 // faulty. We fail in debug mode but in release mode we only provide the | 130 // faulty. We fail in debug mode but in release mode we only provide the |
126 // information we get from the context chain but nothing about | 131 // information we get from the context chain but nothing about |
127 // completely stack allocated scopes or stack allocated locals. | 132 // completely stack allocated scopes or stack allocated locals. |
128 // Or it could be due to stack overflow. | 133 // Or it could be due to stack overflow. |
129 // Silently fail by presenting an empty context chain. | 134 // Silently fail by presenting an empty context chain. |
130 CHECK(isolate_->has_pending_exception()); | 135 CHECK(isolate_->has_pending_exception()); |
131 isolate_->clear_pending_exception(); | 136 isolate_->clear_pending_exception(); |
132 context_ = Handle<Context>(); | 137 context_ = Handle<Context>(); |
133 } | 138 } |
134 UnwrapEvaluationContext(); | 139 UnwrapEvaluationContext(); |
135 } | 140 } |
136 | 141 |
137 ScopeIterator::ScopeIterator(Isolate* isolate, Handle<JSFunction> function) | 142 ScopeIterator::ScopeIterator(Isolate* isolate, Handle<JSFunction> function) |
138 : isolate_(isolate), | 143 : isolate_(isolate), |
139 frame_inspector_(NULL), | |
140 context_(function->context()), | 144 context_(function->context()), |
141 seen_script_scope_(false) { | 145 seen_script_scope_(false) { |
142 if (!function->shared()->IsSubjectToDebugging()) context_ = Handle<Context>(); | 146 if (!function->shared()->IsSubjectToDebugging()) context_ = Handle<Context>(); |
143 UnwrapEvaluationContext(); | 147 UnwrapEvaluationContext(); |
144 } | 148 } |
145 | 149 |
146 ScopeIterator::ScopeIterator(Isolate* isolate, | 150 ScopeIterator::ScopeIterator(Isolate* isolate, |
147 Handle<JSGeneratorObject> generator) | 151 Handle<JSGeneratorObject> generator) |
148 : isolate_(isolate), | 152 : isolate_(isolate), |
149 frame_inspector_(NULL), | 153 generator_(generator), |
150 context_(generator->context()), | 154 context_(generator->context()), |
151 seen_script_scope_(false) { | 155 seen_script_scope_(false) { |
152 if (!generator->function()->shared()->IsSubjectToDebugging()) { | 156 if (!generator->function()->shared()->IsSubjectToDebugging()) { |
153 context_ = Handle<Context>(); | 157 context_ = Handle<Context>(); |
| 158 return; |
154 } | 159 } |
155 UnwrapEvaluationContext(); | 160 TryParseAndRetrieveScopes(DEFAULT); |
156 } | 161 } |
157 | 162 |
158 void ScopeIterator::UnwrapEvaluationContext() { | 163 void ScopeIterator::UnwrapEvaluationContext() { |
159 while (true) { | 164 while (true) { |
160 if (context_.is_null()) return; | 165 if (context_.is_null()) return; |
161 if (!context_->IsDebugEvaluateContext()) return; | 166 if (!context_->IsDebugEvaluateContext()) return; |
162 Handle<Object> wrapped(context_->get(Context::WRAPPED_CONTEXT_INDEX), | 167 Handle<Object> wrapped(context_->get(Context::WRAPPED_CONTEXT_INDEX), |
163 isolate_); | 168 isolate_); |
164 if (wrapped->IsContext()) { | 169 if (wrapped->IsContext()) { |
165 context_ = Handle<Context>::cast(wrapped); | 170 context_ = Handle<Context>::cast(wrapped); |
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 ->Print(os); | 457 ->Print(os); |
453 break; | 458 break; |
454 | 459 |
455 default: | 460 default: |
456 UNREACHABLE(); | 461 UNREACHABLE(); |
457 } | 462 } |
458 PrintF("\n"); | 463 PrintF("\n"); |
459 } | 464 } |
460 #endif | 465 #endif |
461 | 466 |
| 467 inline Handle<Context> ScopeIterator::GetContext() { |
| 468 if (frame_inspector_) { |
| 469 return Handle<Context>::cast(frame_inspector_->GetContext()); |
| 470 } else { |
| 471 DCHECK(!generator_.is_null()); |
| 472 return handle(generator_->context()); |
| 473 } |
| 474 } |
| 475 |
| 476 Handle<JSFunction> ScopeIterator::GetFunction() { |
| 477 if (frame_inspector_) { |
| 478 return frame_inspector_->GetFunction(); |
| 479 } else { |
| 480 DCHECK(!generator_.is_null()); |
| 481 return handle(generator_->function()); |
| 482 } |
| 483 } |
| 484 |
| 485 int ScopeIterator::GetSourcePosition() { |
| 486 if (frame_inspector_) { |
| 487 return frame_inspector_->GetSourcePosition(); |
| 488 } else { |
| 489 DCHECK(!generator_.is_null()); |
| 490 return generator_->source_position(); |
| 491 } |
| 492 } |
| 493 |
462 void ScopeIterator::RetrieveScopeChain(DeclarationScope* scope) { | 494 void ScopeIterator::RetrieveScopeChain(DeclarationScope* scope) { |
463 DCHECK_NOT_NULL(scope); | 495 DCHECK_NOT_NULL(scope); |
464 int source_position = frame_inspector_->GetSourcePosition(); | 496 GetNestedScopeChain(isolate_, scope, GetSourcePosition()); |
465 GetNestedScopeChain(isolate_, scope, source_position); | |
466 } | 497 } |
467 | 498 |
468 void ScopeIterator::CollectNonLocals(ParseInfo* info, DeclarationScope* scope) { | 499 void ScopeIterator::CollectNonLocals(ParseInfo* info, DeclarationScope* scope) { |
469 DCHECK_NOT_NULL(scope); | 500 DCHECK_NOT_NULL(scope); |
470 DCHECK(non_locals_.is_null()); | 501 DCHECK(non_locals_.is_null()); |
471 non_locals_ = scope->CollectNonLocals(info, StringSet::New(isolate_)); | 502 non_locals_ = scope->CollectNonLocals(info, StringSet::New(isolate_)); |
472 } | 503 } |
473 | 504 |
474 | 505 |
475 MaybeHandle<JSObject> ScopeIterator::MaterializeScriptScope() { | 506 MaybeHandle<JSObject> ScopeIterator::MaterializeScriptScope() { |
476 Handle<JSGlobalObject> global(CurrentContext()->global_object()); | 507 Handle<JSGlobalObject> global(CurrentContext()->global_object()); |
477 Handle<ScriptContextTable> script_contexts( | 508 Handle<ScriptContextTable> script_contexts( |
478 global->native_context()->script_context_table()); | 509 global->native_context()->script_context_table()); |
479 | 510 |
480 Handle<JSObject> script_scope = | 511 Handle<JSObject> script_scope = |
481 isolate_->factory()->NewJSObjectWithNullProto(); | 512 isolate_->factory()->NewJSObjectWithNullProto(); |
482 | 513 |
483 for (int context_index = 0; context_index < script_contexts->used(); | 514 for (int context_index = 0; context_index < script_contexts->used(); |
484 context_index++) { | 515 context_index++) { |
485 Handle<Context> context = | 516 Handle<Context> context = |
486 ScriptContextTable::GetContext(script_contexts, context_index); | 517 ScriptContextTable::GetContext(script_contexts, context_index); |
487 Handle<ScopeInfo> scope_info(context->scope_info()); | 518 Handle<ScopeInfo> scope_info(context->scope_info()); |
488 CopyContextLocalsToScopeObject(scope_info, context, script_scope); | 519 CopyContextLocalsToScopeObject(scope_info, context, script_scope); |
489 } | 520 } |
490 return script_scope; | 521 return script_scope; |
491 } | 522 } |
492 | 523 |
| 524 void ScopeIterator::MaterializeStackLocals(Handle<JSObject> local_scope, |
| 525 Handle<ScopeInfo> scope_info) { |
| 526 if (frame_inspector_) { |
| 527 return frame_inspector_->MaterializeStackLocals(local_scope, scope_info); |
| 528 } |
| 529 |
| 530 DCHECK(!generator_.is_null()); |
| 531 // Fill all stack locals. |
| 532 Handle<FixedArray> register_file(generator_->register_file()); |
| 533 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { |
| 534 Handle<String> name = handle(scope_info->StackLocalName(i)); |
| 535 if (ScopeInfo::VariableIsSynthetic(*name)) continue; |
| 536 Handle<Object> value(register_file->get(scope_info->StackLocalIndex(i)), |
| 537 isolate_); |
| 538 // TODO(yangguo): We convert optimized out values to {undefined} when they |
| 539 // are passed to the debugger. Eventually we should handle them somehow. |
| 540 if (value->IsTheHole(isolate_) || value->IsOptimizedOut(isolate_)) { |
| 541 DCHECK(!value.is_identical_to(isolate_->factory()->stale_register())); |
| 542 value = isolate_->factory()->undefined_value(); |
| 543 } |
| 544 JSObject::SetOwnPropertyIgnoreAttributes(local_scope, name, value, NONE) |
| 545 .Check(); |
| 546 } |
| 547 } |
493 | 548 |
494 MaybeHandle<JSObject> ScopeIterator::MaterializeLocalScope() { | 549 MaybeHandle<JSObject> ScopeIterator::MaterializeLocalScope() { |
495 Handle<JSFunction> function = GetFunction(); | 550 Handle<JSFunction> function(GetFunction()); |
| 551 Handle<SharedFunctionInfo> shared(function->shared()); |
| 552 Handle<ScopeInfo> scope_info(shared->scope_info()); |
496 | 553 |
497 Handle<JSObject> local_scope = | 554 Handle<JSObject> local_scope = |
498 isolate_->factory()->NewJSObjectWithNullProto(); | 555 isolate_->factory()->NewJSObjectWithNullProto(); |
499 frame_inspector_->MaterializeStackLocals(local_scope, function); | 556 MaterializeStackLocals(local_scope, scope_info); |
500 | 557 |
501 Handle<Context> frame_context = | 558 Handle<Context> frame_context = GetContext(); |
502 Handle<Context>::cast(frame_inspector_->GetContext()); | |
503 | |
504 HandleScope scope(isolate_); | |
505 Handle<SharedFunctionInfo> shared(function->shared()); | |
506 Handle<ScopeInfo> scope_info(shared->scope_info()); | |
507 | 559 |
508 if (!scope_info->HasContext()) return local_scope; | 560 if (!scope_info->HasContext()) return local_scope; |
509 | 561 |
510 // Fill all context locals. | 562 // Fill all context locals. |
511 Handle<Context> function_context(frame_context->closure_context()); | 563 Handle<Context> function_context(frame_context->closure_context()); |
512 CopyContextLocalsToScopeObject(scope_info, function_context, local_scope); | 564 CopyContextLocalsToScopeObject(scope_info, function_context, local_scope); |
513 | 565 |
514 // Finally copy any properties from the function context extension. | 566 // Finally copy any properties from the function context extension. |
515 // These will be variables introduced by eval. | 567 // These will be variables introduced by eval. |
516 if (function_context->closure() == *function && | 568 if (function_context->closure() == *function && |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
578 | 630 |
579 // Create a plain JSObject which materializes the block scope for the specified | 631 // Create a plain JSObject which materializes the block scope for the specified |
580 // block context. | 632 // block context. |
581 Handle<JSObject> ScopeIterator::MaterializeInnerScope() { | 633 Handle<JSObject> ScopeIterator::MaterializeInnerScope() { |
582 Handle<JSObject> inner_scope = | 634 Handle<JSObject> inner_scope = |
583 isolate_->factory()->NewJSObjectWithNullProto(); | 635 isolate_->factory()->NewJSObjectWithNullProto(); |
584 | 636 |
585 Handle<Context> context = Handle<Context>::null(); | 637 Handle<Context> context = Handle<Context>::null(); |
586 if (!nested_scope_chain_.is_empty()) { | 638 if (!nested_scope_chain_.is_empty()) { |
587 Handle<ScopeInfo> scope_info = nested_scope_chain_.last().scope_info; | 639 Handle<ScopeInfo> scope_info = nested_scope_chain_.last().scope_info; |
588 frame_inspector_->MaterializeStackLocals(inner_scope, scope_info); | 640 MaterializeStackLocals(inner_scope, scope_info); |
589 if (scope_info->HasContext()) context = CurrentContext(); | 641 if (scope_info->HasContext()) context = CurrentContext(); |
590 } else { | 642 } else { |
591 context = CurrentContext(); | 643 context = CurrentContext(); |
592 } | 644 } |
593 | 645 |
594 if (!context.is_null()) { | 646 if (!context.is_null()) { |
595 // Fill all context locals. | 647 // Fill all context locals. |
596 CopyContextLocalsToScopeObject(CurrentScopeInfo(), context, inner_scope); | 648 CopyContextLocalsToScopeObject(CurrentScopeInfo(), context, inner_scope); |
597 CopyContextExtensionToScopeObject(context, inner_scope, | 649 CopyContextExtensionToScopeObject(context, inner_scope, |
598 KeyCollectionMode::kOwnOnly); | 650 KeyCollectionMode::kOwnOnly); |
599 } | 651 } |
600 return inner_scope; | 652 return inner_scope; |
601 } | 653 } |
602 | 654 |
603 | 655 |
604 // Create a plain JSObject which materializes the module scope for the specified | 656 // Create a plain JSObject which materializes the module scope for the specified |
605 // module context. | 657 // module context. |
606 MaybeHandle<JSObject> ScopeIterator::MaterializeModuleScope() { | 658 MaybeHandle<JSObject> ScopeIterator::MaterializeModuleScope() { |
607 Handle<Context> context = CurrentContext(); | 659 Handle<Context> context = CurrentContext(); |
608 DCHECK(context->IsModuleContext()); | 660 DCHECK(context->IsModuleContext()); |
609 Handle<ScopeInfo> scope_info(context->scope_info()); | 661 Handle<ScopeInfo> scope_info(context->scope_info()); |
610 Handle<JSObject> module_scope = | 662 Handle<JSObject> module_scope = |
611 isolate_->factory()->NewJSObjectWithNullProto(); | 663 isolate_->factory()->NewJSObjectWithNullProto(); |
612 CopyContextLocalsToScopeObject(scope_info, context, module_scope); | 664 CopyContextLocalsToScopeObject(scope_info, context, module_scope); |
613 CopyModuleVarsToScopeObject(scope_info, context, module_scope); | 665 CopyModuleVarsToScopeObject(scope_info, context, module_scope); |
614 return module_scope; | 666 return module_scope; |
615 } | 667 } |
616 | 668 |
617 bool ScopeIterator::SetParameterValue(Handle<ScopeInfo> scope_info, | 669 bool ScopeIterator::SetParameterValue(Handle<ScopeInfo> scope_info, |
618 JavaScriptFrame* frame, | |
619 Handle<String> parameter_name, | 670 Handle<String> parameter_name, |
620 Handle<Object> new_value) { | 671 Handle<Object> new_value) { |
621 // Setting stack locals of optimized frames is not supported. | 672 // Setting stack locals of optimized frames is not supported. |
622 if (frame->is_optimized()) return false; | |
623 HandleScope scope(isolate_); | 673 HandleScope scope(isolate_); |
624 for (int i = 0; i < scope_info->ParameterCount(); ++i) { | 674 for (int i = 0; i < scope_info->ParameterCount(); ++i) { |
625 if (String::Equals(handle(scope_info->ParameterName(i)), parameter_name)) { | 675 if (String::Equals(handle(scope_info->ParameterName(i)), parameter_name)) { |
| 676 // Suspended generators should not get here because all parameters should |
| 677 // be context-allocated. |
| 678 DCHECK_NOT_NULL(frame_inspector_); |
| 679 JavaScriptFrame* frame = GetFrame(); |
| 680 if (frame->is_optimized()) { |
| 681 return false; |
| 682 } |
626 frame->SetParameterValue(i, *new_value); | 683 frame->SetParameterValue(i, *new_value); |
627 return true; | 684 return true; |
628 } | 685 } |
629 } | 686 } |
630 return false; | 687 return false; |
631 } | 688 } |
632 | 689 |
633 bool ScopeIterator::SetStackVariableValue(Handle<ScopeInfo> scope_info, | 690 bool ScopeIterator::SetStackVariableValue(Handle<ScopeInfo> scope_info, |
634 Handle<String> variable_name, | 691 Handle<String> variable_name, |
635 Handle<Object> new_value) { | 692 Handle<Object> new_value) { |
636 if (frame_inspector_ == nullptr) return false; | 693 // Setting stack locals of optimized frames is not supported. Suspended |
637 JavaScriptFrame* frame = GetFrame(); | 694 // generators are supported. |
638 // Setting stack locals of optimized frames is not supported. | |
639 if (frame->is_optimized()) return false; | |
640 HandleScope scope(isolate_); | 695 HandleScope scope(isolate_); |
641 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { | 696 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { |
642 if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) { | 697 if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) { |
643 frame->SetExpression(scope_info->StackLocalIndex(i), *new_value); | 698 int stack_local_index = scope_info->StackLocalIndex(i); |
| 699 if (frame_inspector_ != nullptr) { |
| 700 // Set the variable on the stack. |
| 701 JavaScriptFrame* frame = GetFrame(); |
| 702 if (frame->is_optimized()) return false; |
| 703 frame->SetExpression(stack_local_index, *new_value); |
| 704 } else { |
| 705 // Set the variable in the suspended generator. |
| 706 DCHECK(!generator_.is_null()); |
| 707 Handle<FixedArray> register_file(generator_->register_file()); |
| 708 DCHECK_LT(stack_local_index, register_file->length()); |
| 709 register_file->set(stack_local_index, *new_value); |
| 710 } |
644 return true; | 711 return true; |
645 } | 712 } |
646 } | 713 } |
647 return false; | 714 return false; |
648 } | 715 } |
649 | 716 |
650 bool ScopeIterator::SetContextVariableValue(Handle<ScopeInfo> scope_info, | 717 bool ScopeIterator::SetContextVariableValue(Handle<ScopeInfo> scope_info, |
651 Handle<Context> context, | 718 Handle<Context> context, |
652 Handle<String> variable_name, | 719 Handle<String> variable_name, |
653 Handle<Object> new_value) { | 720 Handle<Object> new_value) { |
(...skipping 22 matching lines...) Expand all Loading... |
676 .Check(); | 743 .Check(); |
677 return true; | 744 return true; |
678 } | 745 } |
679 } | 746 } |
680 | 747 |
681 return false; | 748 return false; |
682 } | 749 } |
683 | 750 |
684 bool ScopeIterator::SetLocalVariableValue(Handle<String> variable_name, | 751 bool ScopeIterator::SetLocalVariableValue(Handle<String> variable_name, |
685 Handle<Object> new_value) { | 752 Handle<Object> new_value) { |
686 JavaScriptFrame* frame = GetFrame(); | 753 Handle<ScopeInfo> scope_info(GetFunction()->shared()->scope_info()); |
687 Handle<ScopeInfo> scope_info(frame->function()->shared()->scope_info()); | |
688 | 754 |
689 // Parameter might be shadowed in context. Don't stop here. | 755 // Parameter might be shadowed in context. Don't stop here. |
690 bool result = SetParameterValue(scope_info, frame, variable_name, new_value); | 756 bool result = SetParameterValue(scope_info, variable_name, new_value); |
691 | 757 |
692 // Stack locals. | 758 // Stack locals. |
693 if (SetStackVariableValue(scope_info, variable_name, new_value)) { | 759 if (SetStackVariableValue(scope_info, variable_name, new_value)) { |
694 return true; | 760 return true; |
695 } | 761 } |
696 | 762 |
697 if (scope_info->HasContext() && | 763 if (scope_info->HasContext() && |
698 SetContextVariableValue(scope_info, CurrentContext(), variable_name, | 764 SetContextVariableValue(scope_info, CurrentContext(), variable_name, |
699 new_value)) { | 765 new_value)) { |
700 return true; | 766 return true; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 JSObject::SetOwnPropertyIgnoreAttributes(scope_object, key, value, NONE) | 898 JSObject::SetOwnPropertyIgnoreAttributes(scope_object, key, value, NONE) |
833 .Check(); | 899 .Check(); |
834 } | 900 } |
835 } | 901 } |
836 | 902 |
837 void ScopeIterator::GetNestedScopeChain(Isolate* isolate, Scope* scope, | 903 void ScopeIterator::GetNestedScopeChain(Isolate* isolate, Scope* scope, |
838 int position) { | 904 int position) { |
839 if (scope->is_function_scope()) { | 905 if (scope->is_function_scope()) { |
840 // Do not collect scopes of nested inner functions inside the current one. | 906 // Do not collect scopes of nested inner functions inside the current one. |
841 // Nested arrow functions could have the same end positions. | 907 // Nested arrow functions could have the same end positions. |
842 Handle<JSFunction> function = frame_inspector_->GetFunction(); | 908 Handle<JSFunction> function = GetFunction(); |
843 if (scope->start_position() > function->shared()->start_position() && | 909 if (scope->start_position() > function->shared()->start_position() && |
844 scope->end_position() <= function->shared()->end_position()) { | 910 scope->end_position() <= function->shared()->end_position()) { |
845 return; | 911 return; |
846 } | 912 } |
847 } | 913 } |
848 if (scope->is_hidden()) { | 914 if (scope->is_hidden()) { |
849 // We need to add this chain element in case the scope has a context | 915 // We need to add this chain element in case the scope has a context |
850 // associated. We need to keep the scope chain and context chain in sync. | 916 // associated. We need to keep the scope chain and context chain in sync. |
851 nested_scope_chain_.Add(ExtendedScopeInfo(scope->scope_info())); | 917 nested_scope_chain_.Add(ExtendedScopeInfo(scope->scope_info())); |
852 } else { | 918 } else { |
853 nested_scope_chain_.Add(ExtendedScopeInfo( | 919 nested_scope_chain_.Add(ExtendedScopeInfo( |
854 scope->scope_info(), scope->start_position(), scope->end_position())); | 920 scope->scope_info(), scope->start_position(), scope->end_position())); |
855 } | 921 } |
856 for (Scope* inner_scope = scope->inner_scope(); inner_scope != nullptr; | 922 for (Scope* inner_scope = scope->inner_scope(); inner_scope != nullptr; |
857 inner_scope = inner_scope->sibling()) { | 923 inner_scope = inner_scope->sibling()) { |
858 int beg_pos = inner_scope->start_position(); | 924 int beg_pos = inner_scope->start_position(); |
859 int end_pos = inner_scope->end_position(); | 925 int end_pos = inner_scope->end_position(); |
860 DCHECK((beg_pos >= 0 && end_pos >= 0) || inner_scope->is_hidden()); | 926 DCHECK((beg_pos >= 0 && end_pos >= 0) || inner_scope->is_hidden()); |
861 if (beg_pos <= position && position < end_pos) { | 927 if (beg_pos <= position && position < end_pos) { |
862 GetNestedScopeChain(isolate, inner_scope, position); | 928 GetNestedScopeChain(isolate, inner_scope, position); |
863 return; | 929 return; |
864 } | 930 } |
865 } | 931 } |
866 } | 932 } |
867 | 933 |
868 } // namespace internal | 934 } // namespace internal |
869 } // namespace v8 | 935 } // namespace v8 |
OLD | NEW |