Index: runtime/vm/kernel_to_il.cc |
diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc |
index 7635053d71dcc957bb8896bc0b7c96266c7faa66..5b10f05fa41a64ffd304d0ef1c7eb76b1348fe06 100644 |
--- a/runtime/vm/kernel_to_il.cc |
+++ b/runtime/vm/kernel_to_il.cc |
@@ -57,225 +57,6 @@ static void DiscoverEnclosingElements(Zone* zone, |
} |
-ScopeBuilder::ScopeBuilder(ParsedFunction* parsed_function, TreeNode* node) |
- : result_(NULL), |
- parsed_function_(parsed_function), |
- node_(node), |
- translation_helper_(Thread::Current()), |
- zone_(translation_helper_.zone()), |
- type_translator_(&translation_helper_, &active_class_, /*finalize=*/true), |
- current_function_scope_(NULL), |
- scope_(NULL), |
- depth_(0), |
- name_index_(0), |
- needs_expr_temp_(false) { |
- Script& script = Script::Handle(Z, parsed_function->function().script()); |
- H.SetStringOffsets(TypedData::Handle(Z, script.kernel_string_offsets())); |
- H.SetStringData(TypedData::Handle(Z, script.kernel_string_data())); |
- H.SetCanonicalNames(TypedData::Handle(Z, script.kernel_canonical_names())); |
-} |
- |
- |
-void ScopeBuilder::EnterScope(TreeNode* node, TokenPosition start_position) { |
- scope_ = new (Z) LocalScope(scope_, depth_.function_, depth_.loop_); |
- scope_->set_begin_token_pos(start_position); |
- ASSERT(node->kernel_offset() >= 0); |
- result_->scopes.Insert(node->kernel_offset(), scope_); |
-} |
- |
- |
-void ScopeBuilder::ExitScope(TokenPosition end_position) { |
- scope_->set_end_token_pos(end_position); |
- scope_ = scope_->parent(); |
-} |
- |
- |
-LocalVariable* ScopeBuilder::MakeVariable(TokenPosition declaration_pos, |
- TokenPosition token_pos, |
- const dart::String& name, |
- const AbstractType& type) { |
- return new (Z) LocalVariable(declaration_pos, token_pos, name, type); |
-} |
- |
- |
-void ScopeBuilder::AddParameters(FunctionNode* function, intptr_t pos) { |
- List<VariableDeclaration>& positional = function->positional_parameters(); |
- for (intptr_t i = 0; i < positional.length(); ++i) { |
- AddParameter(positional[i], pos++); |
- } |
- List<VariableDeclaration>& named = function->named_parameters(); |
- for (intptr_t i = 0; i < named.length(); ++i) { |
- AddParameter(named[i], pos++); |
- } |
-} |
- |
- |
-void ScopeBuilder::AddParameter(VariableDeclaration* declaration, |
- intptr_t pos) { |
- LocalVariable* variable = MakeVariable( |
- declaration->position(), declaration->position(), |
- H.DartSymbol(declaration->name()), T.TranslateVariableType(declaration)); |
- if (declaration->IsFinal()) { |
- variable->set_is_final(); |
- } |
- if (variable->name().raw() == Symbols::IteratorParameter().raw()) { |
- variable->set_is_forced_stack(); |
- } |
- scope_->InsertParameterAt(pos, variable); |
- result_->locals.Insert(declaration->kernel_offset(), variable); |
- |
- // The default value may contain 'let' bindings for which the constant |
- // evaluator needs scope bindings. |
- Expression* defaultValue = declaration->initializer(); |
- if (defaultValue != NULL) { |
- defaultValue->AcceptExpressionVisitor(this); |
- } |
-} |
- |
- |
-void ScopeBuilder::AddExceptionVariable( |
- GrowableArray<LocalVariable*>* variables, |
- const char* prefix, |
- intptr_t nesting_depth) { |
- LocalVariable* v = NULL; |
- |
- // If we are inside a function with yield points then Kernel transformer |
- // could have lifted some of the auxiliary exception variables into the |
- // context to preserve them across yield points because they might |
- // be needed for rethrow. |
- // Check if it did and capture such variables instead of introducing |
- // new local ones. |
- // Note: function that wrap kSyncYielding function does not contain |
- // its own try/catches. |
- if (current_function_node_->async_marker() == FunctionNode::kSyncYielding) { |
- ASSERT(current_function_scope_->parent() != NULL); |
- v = current_function_scope_->parent()->LocalLookupVariable( |
- GenerateName(prefix, nesting_depth - 1)); |
- if (v != NULL) { |
- scope_->CaptureVariable(v); |
- } |
- } |
- |
- // No need to create variables for try/catch-statements inside |
- // nested functions. |
- if (depth_.function_ > 0) return; |
- if (variables->length() >= nesting_depth) return; |
- |
- // If variable was not lifted by the transformer introduce a new |
- // one into the current function scope. |
- if (v == NULL) { |
- v = MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
- GenerateName(prefix, nesting_depth - 1), |
- AbstractType::dynamic_type()); |
- |
- // If transformer did not lift the variable then there is no need |
- // to lift it into the context when we encouter a YieldStatement. |
- v->set_is_forced_stack(); |
- current_function_scope_->AddVariable(v); |
- } |
- |
- variables->Add(v); |
-} |
- |
- |
-void ScopeBuilder::AddTryVariables() { |
- AddExceptionVariable(&result_->catch_context_variables, |
- ":saved_try_context_var", depth_.try_); |
-} |
- |
- |
-void ScopeBuilder::AddCatchVariables() { |
- AddExceptionVariable(&result_->exception_variables, ":exception", |
- depth_.catch_); |
- AddExceptionVariable(&result_->stack_trace_variables, ":stack_trace", |
- depth_.catch_); |
-} |
- |
- |
-void ScopeBuilder::AddIteratorVariable() { |
- if (depth_.function_ > 0) return; |
- if (result_->iterator_variables.length() >= depth_.for_in_) return; |
- |
- ASSERT(result_->iterator_variables.length() == depth_.for_in_ - 1); |
- LocalVariable* iterator = |
- MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
- GenerateName(":iterator", depth_.for_in_ - 1), |
- AbstractType::dynamic_type()); |
- current_function_scope_->AddVariable(iterator); |
- result_->iterator_variables.Add(iterator); |
-} |
- |
- |
-void ScopeBuilder::LookupVariable(VariableDeclaration* declaration) { |
- LocalVariable* variable = |
- result_->locals.Lookup(declaration->kernel_offset()); |
- if (variable == NULL) { |
- // We have not seen a declaration of the variable, so it must be the |
- // case that we are compiling a nested function and the variable is |
- // declared in an outer scope. In that case, look it up in the scope by |
- // name and add it to the variable map to simplify later lookup. |
- ASSERT(current_function_scope_->parent() != NULL); |
- const dart::String& name = H.DartSymbol(declaration->name()); |
- variable = current_function_scope_->parent()->LookupVariable(name, true); |
- ASSERT(variable != NULL); |
- result_->locals.Insert(declaration->kernel_offset(), variable); |
- } |
- if (variable->owner()->function_level() < scope_->function_level()) { |
- // We call `LocalScope->CaptureVariable(variable)` in two scenarios for two |
- // different reasons: |
- // Scenario 1: |
- // We need to know which variables defined in this function |
- // are closed over by nested closures in order to ensure we will |
- // create a [Context] object of appropriate size and store captured |
- // variables there instead of the stack. |
- // Scenario 2: |
- // We need to find out which variables defined in enclosing functions |
- // are closed over by this function/closure or nested closures. This |
- // is necessary in order to build a fat flattened [ContextScope] |
- // object. |
- scope_->CaptureVariable(variable); |
- } else { |
- ASSERT(variable->owner()->function_level() == scope_->function_level()); |
- } |
-} |
- |
- |
-void ScopeBuilder::LookupCapturedVariableByName(LocalVariable** variable, |
- const dart::String& name) { |
- if (*variable == NULL) { |
- *variable = scope_->LookupVariable(name, true); |
- ASSERT(*variable != NULL); |
- scope_->CaptureVariable(*variable); |
- } |
-} |
- |
- |
-const dart::String& ScopeBuilder::GenerateName(const char* prefix, |
- intptr_t suffix) { |
- char name[64]; |
- OS::SNPrint(name, 64, "%s%" Pd "", prefix, suffix); |
- return H.DartSymbol(name); |
-} |
- |
- |
-void ScopeBuilder::AddVariable(VariableDeclaration* declaration) { |
- // In case `declaration->IsConst()` the flow graph building will take care of |
- // evaluating the constant and setting it via |
- // `declaration->SetConstantValue()`. |
- const dart::String& name = (H.StringSize(declaration->name()) == 0) |
- ? GenerateName(":var", name_index_++) |
- : H.DartSymbol(declaration->name()); |
- LocalVariable* variable = |
- MakeVariable(declaration->position(), declaration->end_position(), name, |
- T.TranslateVariableType(declaration)); |
- if (declaration->IsFinal()) { |
- variable->set_is_final(); |
- } |
- scope_->AddVariable(variable); |
- result_->locals.Insert(declaration->kernel_offset(), variable); |
-} |
- |
- |
static bool IsStaticInitializer(const Function& function, Zone* zone) { |
return (function.kind() == RawFunction::kImplicitStaticFinalGetter) && |
dart::String::Handle(zone, function.name()) |
@@ -283,539 +64,6 @@ static bool IsStaticInitializer(const Function& function, Zone* zone) { |
} |
-ScopeBuildingResult* ScopeBuilder::BuildScopes() { |
- if (result_ != NULL) return result_; |
- |
- ASSERT(scope_ == NULL && depth_.loop_ == 0 && depth_.function_ == 0); |
- result_ = new (Z) ScopeBuildingResult(); |
- |
- ParsedFunction* parsed_function = parsed_function_; |
- const Function& function = parsed_function->function(); |
- |
- // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used |
- // e.g. for type translation. |
- const dart::Class& klass = |
- dart::Class::Handle(zone_, parsed_function_->function().Owner()); |
- Function& outermost_function = Function::Handle(Z); |
- TreeNode* outermost_node = NULL; |
- Class* kernel_class = NULL; |
- DiscoverEnclosingElements(Z, function, &outermost_function, &outermost_node, |
- &kernel_class); |
- // Use [klass]/[kernel_class] as active class. Type parameters will get |
- // resolved via [kernel_class] unless we are nested inside a static factory |
- // in which case we will use [member]. |
- ActiveClassScope active_class_scope(&active_class_, kernel_class, &klass); |
- Member* member = ((outermost_node != NULL) && outermost_node->IsMember()) |
- ? Member::Cast(outermost_node) |
- : NULL; |
- ActiveMemberScope active_member(&active_class_, member); |
- |
- |
- LocalScope* enclosing_scope = NULL; |
- if (function.IsLocalFunction()) { |
- enclosing_scope = LocalScope::RestoreOuterScope( |
- ContextScope::Handle(Z, function.context_scope())); |
- } |
- current_function_scope_ = scope_ = new (Z) LocalScope(enclosing_scope, 0, 0); |
- scope_->set_begin_token_pos(function.token_pos()); |
- scope_->set_end_token_pos(function.end_token_pos()); |
- |
- LocalVariable* context_var = parsed_function->current_context_var(); |
- context_var->set_is_forced_stack(); |
- scope_->AddVariable(context_var); |
- |
- parsed_function->SetNodeSequence( |
- new SequenceNode(TokenPosition::kNoSource, scope_)); |
- |
- switch (function.kind()) { |
- case RawFunction::kClosureFunction: |
- case RawFunction::kRegularFunction: |
- case RawFunction::kGetterFunction: |
- case RawFunction::kSetterFunction: |
- case RawFunction::kConstructor: { |
- FunctionNode* node; |
- if (node_->IsProcedure()) { |
- node = Procedure::Cast(node_)->function(); |
- } else if (node_->IsConstructor()) { |
- node = Constructor::Cast(node_)->function(); |
- } else { |
- node = FunctionNode::Cast(node_); |
- } |
- current_function_node_ = node; |
- |
- intptr_t pos = 0; |
- if (function.IsClosureFunction()) { |
- LocalVariable* variable = MakeVariable( |
- TokenPosition::kNoSource, TokenPosition::kNoSource, |
- Symbols::ClosureParameter(), AbstractType::dynamic_type()); |
- variable->set_is_forced_stack(); |
- scope_->InsertParameterAt(pos++, variable); |
- } else if (!function.is_static()) { |
- // We use [is_static] instead of [IsStaticFunction] because the latter |
- // returns `false` for constructors. |
- dart::Class& klass = dart::Class::Handle(Z, function.Owner()); |
- Type& klass_type = H.GetCanonicalType(klass); |
- LocalVariable* variable = |
- MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
- Symbols::This(), klass_type); |
- scope_->InsertParameterAt(pos++, variable); |
- result_->this_variable = variable; |
- |
- // We visit instance field initializers because they might contain |
- // [Let] expressions and we need to have a mapping. |
- if (node_->IsConstructor()) { |
- Class* klass = Class::Cast(Constructor::Cast(node_)->parent()); |
- |
- for (intptr_t i = 0; i < klass->fields().length(); i++) { |
- Field* field = klass->fields()[i]; |
- if (!field->IsStatic() && (field->initializer() != NULL)) { |
- EnterScope(field, field->position()); |
- field->initializer()->AcceptExpressionVisitor(this); |
- ExitScope(field->end_position()); |
- } |
- } |
- } |
- } else if (function.IsFactory()) { |
- LocalVariable* variable = MakeVariable( |
- TokenPosition::kNoSource, TokenPosition::kNoSource, |
- Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type()); |
- scope_->InsertParameterAt(pos++, variable); |
- result_->type_arguments_variable = variable; |
- } |
- AddParameters(node, pos); |
- |
- // We generate a syntethic body for implicit closure functions - which |
- // will forward the call to the real function. |
- // -> see BuildGraphOfImplicitClosureFunction |
- if (!function.IsImplicitClosureFunction()) { |
- // TODO(jensj): HACK: Push the begin token to after any parameters to |
- // avoid crash when breaking on definition line of async method in |
- // debugger. It seems that another scope needs to be added |
- // in which captures are made, but I can't make that work. |
- // This 'solution' doesn't crash, but I cannot see the parameters at |
- // that particular breakpoint either. |
- // Also push the end token to after the "}" to avoid crashing on |
- // stepping past the last line (to the "}" character). |
- if (node->body() != NULL && node->body()->position().IsReal()) { |
- scope_->set_begin_token_pos(node->body()->position()); |
- } |
- if (scope_->end_token_pos().IsReal()) { |
- scope_->set_end_token_pos(scope_->end_token_pos().Next()); |
- } |
- node_->AcceptVisitor(this); |
- } |
- break; |
- } |
- case RawFunction::kImplicitGetter: |
- case RawFunction::kImplicitStaticFinalGetter: |
- case RawFunction::kImplicitSetter: { |
- ASSERT(node_->IsField()); |
- if (IsStaticInitializer(function, Z)) { |
- node_->AcceptVisitor(this); |
- break; |
- } |
- bool is_setter = function.IsImplicitSetterFunction(); |
- bool is_method = !function.IsStaticFunction(); |
- intptr_t pos = 0; |
- if (is_method) { |
- dart::Class& klass = dart::Class::Handle(Z, function.Owner()); |
- Type& klass_type = H.GetCanonicalType(klass); |
- LocalVariable* variable = |
- MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
- Symbols::This(), klass_type); |
- scope_->InsertParameterAt(pos++, variable); |
- result_->this_variable = variable; |
- } |
- if (is_setter) { |
- result_->setter_value = |
- MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
- Symbols::Value(), AbstractType::dynamic_type()); |
- scope_->InsertParameterAt(pos++, result_->setter_value); |
- } |
- break; |
- } |
- case RawFunction::kMethodExtractor: { |
- // Add a receiver parameter. Though it is captured, we emit code to |
- // explicitly copy it to a fixed offset in a freshly-allocated context |
- // instead of using the generic code for regular functions. |
- // Therefore, it isn't necessary to mark it as captured here. |
- dart::Class& klass = dart::Class::Handle(Z, function.Owner()); |
- Type& klass_type = H.GetCanonicalType(klass); |
- LocalVariable* variable = |
- MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
- Symbols::This(), klass_type); |
- scope_->InsertParameterAt(0, variable); |
- result_->this_variable = variable; |
- break; |
- } |
- case RawFunction::kNoSuchMethodDispatcher: |
- case RawFunction::kInvokeFieldDispatcher: |
- for (intptr_t i = 0; i < function.NumParameters(); ++i) { |
- LocalVariable* variable = MakeVariable( |
- TokenPosition::kNoSource, TokenPosition::kNoSource, |
- dart::String::ZoneHandle(Z, function.ParameterNameAt(i)), |
- AbstractType::dynamic_type()); |
- scope_->InsertParameterAt(i, variable); |
- } |
- break; |
- case RawFunction::kSignatureFunction: |
- case RawFunction::kIrregexpFunction: |
- UNREACHABLE(); |
- } |
- if (needs_expr_temp_) { |
- scope_->AddVariable(parsed_function_->EnsureExpressionTemp()); |
- } |
- parsed_function->AllocateVariables(); |
- |
- return result_; |
-} |
- |
- |
-void ScopeBuilder::VisitThisExpression(ThisExpression* node) { |
- HandleSpecialLoad(&result_->this_variable, Symbols::This()); |
-} |
- |
- |
-void ScopeBuilder::VisitTypeParameterType(TypeParameterType* node) { |
- Function& function = Function::Handle(Z, parsed_function_->function().raw()); |
- while (function.IsClosureFunction()) { |
- function = function.parent_function(); |
- } |
- |
- if (function.IsFactory()) { |
- // The type argument vector is passed as the very first argument to the |
- // factory constructor function. |
- HandleSpecialLoad(&result_->type_arguments_variable, |
- Symbols::TypeArgumentsParameter()); |
- } else { |
- // The type argument vector is stored on the instance object. We therefore |
- // need to capture `this`. |
- HandleSpecialLoad(&result_->this_variable, Symbols::This()); |
- } |
-} |
- |
- |
-void ScopeBuilder::VisitVariableGet(VariableGet* node) { |
- LookupVariable(node->variable()); |
-} |
- |
- |
-void ScopeBuilder::VisitVariableSet(VariableSet* node) { |
- LookupVariable(node->variable()); |
- node->VisitChildren(this); |
-} |
- |
- |
-void ScopeBuilder::VisitConditionalExpression(ConditionalExpression* node) { |
- needs_expr_temp_ = true; |
- node->VisitChildren(this); |
-} |
- |
- |
-void ScopeBuilder::VisitLogicalExpression(LogicalExpression* node) { |
- needs_expr_temp_ = true; |
- node->VisitChildren(this); |
-} |
- |
- |
-void ScopeBuilder::HandleLocalFunction(TreeNode* parent, |
- FunctionNode* function) { |
- LocalScope* saved_function_scope = current_function_scope_; |
- FunctionNode* saved_function_node = current_function_node_; |
- ScopeBuilder::DepthState saved_depth_state = depth_; |
- depth_ = DepthState(depth_.function_ + 1); |
- EnterScope(parent, function->position()); |
- current_function_scope_ = scope_; |
- current_function_node_ = function; |
- if (depth_.function_ == 1) { |
- FunctionScope function_scope = {function->kernel_offset(), scope_}; |
- result_->function_scopes.Add(function_scope); |
- } |
- AddParameters(function); |
- VisitFunctionNode(function); |
- ExitScope(function->end_position()); |
- depth_ = saved_depth_state; |
- current_function_scope_ = saved_function_scope; |
- current_function_node_ = saved_function_node; |
-} |
- |
- |
-void ScopeBuilder::HandleSpecialLoad(LocalVariable** variable, |
- const dart::String& symbol) { |
- if (current_function_scope_->parent() != NULL) { |
- // We are building the scope tree of a closure function and saw [node]. We |
- // lazily populate the variable using the parent function scope. |
- if (*variable == NULL) { |
- *variable = |
- current_function_scope_->parent()->LookupVariable(symbol, true); |
- ASSERT(*variable != NULL); |
- } |
- } |
- |
- if ((current_function_scope_->parent() != NULL) || |
- (scope_->function_level() > 0)) { |
- // Every scope we use the [variable] from needs to be notified of the usage |
- // in order to ensure that preserving the context scope on that particular |
- // use-site also includes the [variable]. |
- scope_->CaptureVariable(*variable); |
- } |
-} |
- |
- |
-void ScopeBuilder::VisitFunctionExpression(FunctionExpression* node) { |
- HandleLocalFunction(node, node->function()); |
-} |
- |
- |
-void ScopeBuilder::VisitLet(Let* node) { |
- EnterScope(node, node->position()); |
- node->VisitChildren(this); |
- ExitScope(node->end_position()); |
-} |
- |
- |
-void ScopeBuilder::VisitBlock(Block* node) { |
- EnterScope(node, node->position()); |
- node->VisitChildren(this); |
- ExitScope(node->end_position()); |
-} |
- |
- |
-void ScopeBuilder::VisitVariableDeclaration(VariableDeclaration* node) { |
- AddVariable(node); |
- node->VisitChildren(this); |
-} |
- |
- |
-void ScopeBuilder::VisitFunctionDeclaration(FunctionDeclaration* node) { |
- VisitVariableDeclaration(node->variable()); |
- HandleLocalFunction(node, node->function()); |
-} |
- |
- |
-void ScopeBuilder::VisitWhileStatement(WhileStatement* node) { |
- ++depth_.loop_; |
- node->VisitChildren(this); |
- --depth_.loop_; |
-} |
- |
- |
-void ScopeBuilder::VisitDoStatement(DoStatement* node) { |
- ++depth_.loop_; |
- node->VisitChildren(this); |
- --depth_.loop_; |
-} |
- |
- |
-void ScopeBuilder::VisitForStatement(ForStatement* node) { |
- EnterScope(node, node->position()); |
- List<VariableDeclaration>& variables = node->variables(); |
- for (intptr_t i = 0; i < variables.length(); ++i) { |
- VisitVariableDeclaration(variables[i]); |
- } |
- ++depth_.loop_; |
- if (node->condition() != NULL) { |
- node->condition()->AcceptExpressionVisitor(this); |
- } |
- node->body()->AcceptStatementVisitor(this); |
- List<Expression>& updates = node->updates(); |
- for (intptr_t i = 0; i < updates.length(); ++i) { |
- updates[i]->AcceptExpressionVisitor(this); |
- } |
- --depth_.loop_; |
- ExitScope(node->end_position()); |
-} |
- |
- |
-void ScopeBuilder::VisitForInStatement(ForInStatement* node) { |
- node->iterable()->AcceptExpressionVisitor(this); |
- ++depth_.for_in_; |
- AddIteratorVariable(); |
- ++depth_.loop_; |
- EnterScope(node, node->position()); |
- VisitVariableDeclaration(node->variable()); |
- node->body()->AcceptStatementVisitor(this); |
- ExitScope(node->end_position()); |
- --depth_.loop_; |
- --depth_.for_in_; |
-} |
- |
- |
-void ScopeBuilder::AddSwitchVariable() { |
- if ((depth_.function_ == 0) && (result_->switch_variable == NULL)) { |
- LocalVariable* variable = |
- MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, |
- Symbols::SwitchExpr(), AbstractType::dynamic_type()); |
- variable->set_is_forced_stack(); |
- current_function_scope_->AddVariable(variable); |
- result_->switch_variable = variable; |
- } |
-} |
- |
- |
-void ScopeBuilder::VisitSwitchStatement(SwitchStatement* node) { |
- AddSwitchVariable(); |
- node->VisitChildren(this); |
-} |
- |
- |
-void ScopeBuilder::VisitReturnStatement(ReturnStatement* node) { |
- if ((depth_.function_ == 0) && (depth_.finally_ > 0) && |
- (result_->finally_return_variable == NULL)) { |
- const dart::String& name = H.DartSymbol(":try_finally_return_value"); |
- LocalVariable* variable = |
- MakeVariable(TokenPosition::kNoSource, TokenPosition::kNoSource, name, |
- AbstractType::dynamic_type()); |
- current_function_scope_->AddVariable(variable); |
- result_->finally_return_variable = variable; |
- } |
- node->VisitChildren(this); |
-} |
- |
- |
-void ScopeBuilder::VisitTryCatch(TryCatch* node) { |
- ++depth_.try_; |
- AddTryVariables(); |
- node->body()->AcceptStatementVisitor(this); |
- --depth_.try_; |
- |
- ++depth_.catch_; |
- AddCatchVariables(); |
- List<Catch>& catches = node->catches(); |
- for (intptr_t i = 0; i < catches.length(); ++i) { |
- Catch* ketch = catches[i]; |
- EnterScope(ketch, ketch->position()); |
- if (ketch->exception() != NULL) { |
- VisitVariableDeclaration(ketch->exception()); |
- } |
- if (ketch->stack_trace() != NULL) { |
- VisitVariableDeclaration(ketch->stack_trace()); |
- } |
- ketch->body()->AcceptStatementVisitor(this); |
- ExitScope(ketch->end_position()); |
- } |
- --depth_.catch_; |
-} |
- |
- |
-void ScopeBuilder::VisitTryFinally(TryFinally* node) { |
- ++depth_.try_; |
- ++depth_.finally_; |
- AddTryVariables(); |
- node->body()->AcceptStatementVisitor(this); |
- --depth_.finally_; |
- --depth_.try_; |
- |
- ++depth_.catch_; |
- AddCatchVariables(); |
- node->finalizer()->AcceptStatementVisitor(this); |
- --depth_.catch_; |
-} |
- |
- |
-void ScopeBuilder::VisitFunctionNode(FunctionNode* node) { |
- List<TypeParameter>& type_parameters = node->type_parameters(); |
- for (intptr_t i = 0; i < type_parameters.length(); ++i) { |
- VisitTypeParameter(type_parameters[i]); |
- } |
- |
- if (FLAG_causal_async_stacks && |
- (node->dart_async_marker() == FunctionNode::kAsync || |
- node->dart_async_marker() == FunctionNode::kAsyncStar)) { |
- LocalVariable* asyncStackTraceVar = MakeVariable( |
- TokenPosition::kNoSource, TokenPosition::kNoSource, |
- Symbols::AsyncStackTraceVar(), AbstractType::dynamic_type()); |
- scope_->AddVariable(asyncStackTraceVar); |
- } |
- |
- if (node->async_marker() == FunctionNode::kSyncYielding) { |
- LocalScope* scope = parsed_function_->node_sequence()->scope(); |
- intptr_t offset = parsed_function_->function().num_fixed_parameters(); |
- for (intptr_t i = 0; |
- i < parsed_function_->function().NumOptionalPositionalParameters(); |
- i++) { |
- scope->VariableAt(offset + i)->set_is_forced_stack(); |
- } |
- } |
- |
- // Do not visit the positional and named parameters, because they've |
- // already been added to the scope. |
- if (node->body() != NULL) { |
- node->body()->AcceptStatementVisitor(this); |
- } |
- |
- // Ensure that :await_jump_var, :await_ctx_var, :async_op and |
- // :async_stack_trace are captured. |
- if (node->async_marker() == FunctionNode::kSyncYielding) { |
- { |
- LocalVariable* temp = NULL; |
- LookupCapturedVariableByName( |
- (depth_.function_ == 0) ? &result_->yield_jump_variable : &temp, |
- Symbols::AwaitJumpVar()); |
- } |
- { |
- LocalVariable* temp = NULL; |
- LookupCapturedVariableByName( |
- (depth_.function_ == 0) ? &result_->yield_context_variable : &temp, |
- Symbols::AwaitContextVar()); |
- } |
- { |
- LocalVariable* temp = |
- scope_->LookupVariable(Symbols::AsyncOperation(), true); |
- if (temp != NULL) { |
- scope_->CaptureVariable(temp); |
- } |
- } |
- if (FLAG_causal_async_stacks) { |
- LocalVariable* temp = |
- scope_->LookupVariable(Symbols::AsyncStackTraceVar(), true); |
- if (temp != NULL) { |
- scope_->CaptureVariable(temp); |
- } |
- } |
- } |
-} |
- |
- |
-void ScopeBuilder::VisitYieldStatement(YieldStatement* node) { |
- ASSERT(node->is_native()); |
- if (depth_.function_ == 0) { |
- AddSwitchVariable(); |
- // Promote all currently visible local variables into the context. |
- // TODO(27590) CaptureLocalVariables promotes to many variables into |
- // the scope. Mark those variables as stack_local. |
- // TODO(27590) we don't need to promote those variables that are |
- // not used across yields. |
- scope_->CaptureLocalVariables(current_function_scope_); |
- } |
-} |
- |
- |
-void ScopeBuilder::VisitAssertStatement(AssertStatement* node) { |
- if (I->asserts()) { |
- RecursiveVisitor::VisitAssertStatement(node); |
- } |
-} |
- |
- |
-void ScopeBuilder::VisitConstructor(Constructor* node) { |
- // Field initializers that come from non-static field declarations are |
- // compiled as if they appear in the constructor initializer list. This is |
- // important for closure-valued field initializers because the VM expects the |
- // corresponding closure functions to appear as if they were nested inside the |
- // constructor. |
- List<Field>& fields = Class::Cast(node->parent())->fields(); |
- for (intptr_t i = 0; i < fields.length(); ++i) { |
- Field* field = fields[i]; |
- Expression* initializer = field->initializer(); |
- if (!field->IsStatic() && (initializer != NULL)) { |
- initializer->AcceptExpressionVisitor(this); |
- } |
- } |
- node->VisitChildren(this); |
-} |
- |
- |
Fragment& Fragment::operator+=(const Fragment& other) { |
if (entry == NULL) { |
entry = other.entry; |
@@ -3042,7 +2290,7 @@ intptr_t FlowGraphBuilder::CurrentTryIndex() { |
LocalVariable* FlowGraphBuilder::LookupVariable(VariableDeclaration* var) { |
- LocalVariable* local = scopes_->locals.Lookup(var->kernel_offset()); |
+ LocalVariable* local = scopes_->locals.Lookup(var->kernel_offset_no_tag()); |
ASSERT(local != NULL); |
return local; |
} |
@@ -3225,8 +2473,6 @@ FlowGraph* FlowGraphBuilder::BuildGraph() { |
FunctionNode* kernel_function = node_->IsProcedure() |
? Procedure::Cast(node_)->function() |
: FunctionNode::Cast(node_); |
- ActiveFunctionScope active_function_scope(&active_class_, |
- kernel_function); |
return function.IsImplicitClosureFunction() |
? BuildGraphOfImplicitClosureFunction(kernel_function, |
function) |
@@ -3237,12 +2483,10 @@ FlowGraph* FlowGraphBuilder::BuildGraph() { |
if (is_factory) { |
Procedure* procedure = Procedure::Cast(node_); |
FunctionNode* function = procedure->function(); |
- ActiveFunctionScope active_function_scope(&active_class_, function); |
return BuildGraphOfFunction(function, NULL); |
} else { |
Constructor* constructor = Constructor::Cast(node_); |
FunctionNode* function = constructor->function(); |
- ActiveFunctionScope active_function_scope(&active_class_, function); |
return BuildGraphOfFunction(function, constructor); |
} |
} |