| 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);
|
| }
|
| }
|
|
|