| Index: runtime/vm/kernel_to_il.cc
|
| diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc
|
| index 38900f10b9a2efb5a1c96073f314a77ec985e258..02f54379e86e50ca0231e41aa207ddafc84e2afb 100644
|
| --- a/runtime/vm/kernel_to_il.cc
|
| +++ b/runtime/vm/kernel_to_il.cc
|
| @@ -30,6 +30,33 @@ namespace kernel {
|
| #define I Isolate::Current()
|
|
|
|
|
| +static void DiscoverEnclosingElements(Zone* zone,
|
| + const Function& function,
|
| + Function* outermost_function,
|
| + TreeNode** outermost_node,
|
| + Class** klass) {
|
| + // Find out if there is an enclosing kernel class (which will be used to
|
| + // resolve type parameters).
|
| + *outermost_function = function.raw();
|
| + while (outermost_function->parent_function() != Object::null()) {
|
| + *outermost_function = outermost_function->parent_function();
|
| + }
|
| + *outermost_node =
|
| + static_cast<TreeNode*>(outermost_function->kernel_function());
|
| + if (*outermost_node != NULL) {
|
| + TreeNode* parent = NULL;
|
| + if ((*outermost_node)->IsProcedure()) {
|
| + parent = Procedure::Cast(*outermost_node)->parent();
|
| + } else if ((*outermost_node)->IsConstructor()) {
|
| + parent = Constructor::Cast(*outermost_node)->parent();
|
| + } else if ((*outermost_node)->IsField()) {
|
| + parent = Field::Cast(*outermost_node)->parent();
|
| + }
|
| + if (parent != NULL && parent->IsClass()) *klass = Class::Cast(parent);
|
| + }
|
| +}
|
| +
|
| +
|
| void ScopeBuilder::EnterScope(TreeNode* node) {
|
| scope_ = new (Z) LocalScope(scope_, depth_.function_, depth_.loop_);
|
| result_->scopes.Insert(node, scope_);
|
| @@ -39,17 +66,8 @@ void ScopeBuilder::EnterScope(TreeNode* node) {
|
| void ScopeBuilder::ExitScope() { scope_ = scope_->parent(); }
|
|
|
|
|
| -LocalVariable* ScopeBuilder::MakeVariable(const dart::String& name) {
|
| - return new (Z)
|
| - LocalVariable(TokenPosition::kNoSource,
|
| - TokenPosition::kNoSource,
|
| - name,
|
| - Object::dynamic_type());
|
| -}
|
| -
|
| -
|
| LocalVariable* ScopeBuilder::MakeVariable(const dart::String& name,
|
| - const Type& type) {
|
| + const AbstractType& type) {
|
| return new (Z) LocalVariable(TokenPosition::kNoSource,
|
| TokenPosition::kNoSource,
|
| name,
|
| @@ -71,7 +89,9 @@ void ScopeBuilder::AddParameters(FunctionNode* function, intptr_t pos) {
|
|
|
| void ScopeBuilder::AddParameter(VariableDeclaration* declaration,
|
| intptr_t pos) {
|
| - LocalVariable* variable = MakeVariable(H.DartSymbol(declaration->name()));
|
| + LocalVariable* variable =
|
| + MakeVariable(H.DartSymbol(declaration->name()),
|
| + T.TranslateVariableType(declaration));
|
| if (declaration->IsFinal()) {
|
| variable->set_is_final();
|
| }
|
| @@ -117,7 +137,8 @@ void ScopeBuilder::AddExceptionVariable(
|
| // If variable was not lifted by the transformer introduce a new
|
| // one into the current function scope.
|
| if (v == NULL) {
|
| - v = MakeVariable(GenerateName(prefix, nesting_depth - 1));
|
| + v = MakeVariable(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.
|
| @@ -149,7 +170,8 @@ void ScopeBuilder::AddIteratorVariable() {
|
|
|
| ASSERT(result_->iterator_variables.length() == depth_.for_in_ - 1);
|
| LocalVariable* iterator =
|
| - MakeVariable(GenerateName(":iterator", depth_.for_in_ - 1));
|
| + MakeVariable(GenerateName(":iterator", depth_.for_in_ - 1),
|
| + AbstractType::dynamic_type());
|
| current_function_scope_->AddVariable(iterator);
|
| result_->iterator_variables.Add(iterator);
|
| }
|
| @@ -213,7 +235,8 @@ void ScopeBuilder::AddVariable(VariableDeclaration* declaration) {
|
| const dart::String& name = declaration->name()->is_empty()
|
| ? GenerateName(":var", name_index_++)
|
| : H.DartSymbol(declaration->name());
|
| - LocalVariable* variable = MakeVariable(name);
|
| + LocalVariable* variable =
|
| + MakeVariable(name, T.TranslateVariableType(declaration));
|
| if (declaration->IsFinal()) {
|
| variable->set_is_final();
|
| }
|
| @@ -238,6 +261,25 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
|
| ParsedFunction* parsed_function = parsed_function_;
|
| const dart::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_klass = NULL;
|
| + DiscoverEnclosingElements(
|
| + Z, function, &outermost_function, &outermost_node, &kernel_klass);
|
| + // Use [klass]/[kernel_klass] as active class. Type parameters will get
|
| + // resolved via [kernel_klass] unless we are nested inside a static factory
|
| + // in which case we will use [member].
|
| + ActiveClassScope active_class_scope(&active_class_, kernel_klass, &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(
|
| @@ -271,7 +313,9 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
|
|
|
| intptr_t pos = 0;
|
| if (function.IsClosureFunction()) {
|
| - LocalVariable* variable = MakeVariable(Symbols::ClosureParameter());
|
| + LocalVariable* variable =
|
| + MakeVariable(Symbols::ClosureParameter(),
|
| + AbstractType::dynamic_type());
|
| variable->set_is_forced_stack();
|
| scope_->InsertParameterAt(pos++, variable);
|
| } else if (!function.is_static()) {
|
| @@ -299,7 +343,8 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
|
| }
|
| } else if (function.IsFactory()) {
|
| LocalVariable* variable = MakeVariable(
|
| - Symbols::TypeArgumentsParameter(), AbstractType::dynamic_type());
|
| + Symbols::TypeArgumentsParameter(),
|
| + AbstractType::dynamic_type());
|
| scope_->InsertParameterAt(pos++, variable);
|
| result_->type_arguments_variable = variable;
|
| }
|
| @@ -332,7 +377,8 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
|
| result_->this_variable = variable;
|
| }
|
| if (is_setter) {
|
| - result_->setter_value = MakeVariable(Symbols::Value());
|
| + result_->setter_value = MakeVariable(
|
| + Symbols::Value(), AbstractType::dynamic_type());
|
| scope_->InsertParameterAt(pos++, result_->setter_value);
|
| }
|
| break;
|
| @@ -353,7 +399,8 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
|
| case RawFunction::kInvokeFieldDispatcher:
|
| for (intptr_t i = 0; i < function.NumParameters(); ++i) {
|
| LocalVariable* variable = MakeVariable(
|
| - dart::String::ZoneHandle(Z, function.ParameterNameAt(i)));
|
| + dart::String::ZoneHandle(Z, function.ParameterNameAt(i)),
|
| + AbstractType::dynamic_type());
|
| scope_->InsertParameterAt(i, variable);
|
| }
|
| break;
|
| @@ -528,7 +575,9 @@ void ScopeBuilder::VisitForInStatement(ForInStatement* node) {
|
|
|
| void ScopeBuilder::AddSwitchVariable() {
|
| if ((depth_.function_ == 0) && (result_->switch_variable == NULL)) {
|
| - LocalVariable* variable = MakeVariable(Symbols::SwitchExpr());
|
| + LocalVariable* variable = MakeVariable(
|
| + Symbols::SwitchExpr(),
|
| + AbstractType::dynamic_type());
|
| variable->set_is_forced_stack();
|
| current_function_scope_->AddVariable(variable);
|
| result_->switch_variable = variable;
|
| @@ -546,7 +595,9 @@ 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(name);
|
| + LocalVariable* variable = MakeVariable(
|
| + name,
|
| + AbstractType::dynamic_type());
|
| current_function_scope_->AddVariable(variable);
|
| result_->finally_return_variable = variable;
|
| }
|
| @@ -2731,34 +2782,18 @@ FlowGraph* FlowGraphBuilder::BuildGraph() {
|
| dart::Class& klass =
|
| dart::Class::Handle(zone_, parsed_function_->function().Owner());
|
|
|
| - // Find out if there is an enclosing kernel class (which will be used to
|
| - // resolve type parameters).
|
| + Function& outermost_function = Function::Handle(Z);
|
| + TreeNode* outermost_node = NULL;
|
| Class* kernel_klass = NULL;
|
| - dart::Function& topmost = dart::Function::Handle(Z, function.raw());
|
| - while (topmost.parent_function() != Object::null()) {
|
| - topmost = topmost.parent_function();
|
| - }
|
| - TreeNode* topmost_node = static_cast<TreeNode*>(topmost.kernel_function());
|
| - if (topmost_node != NULL) {
|
| - // Going up the closure->parent chain needs to result in a Procedure or
|
| - // Constructor.
|
| - TreeNode* parent = NULL;
|
| - if (topmost_node->IsProcedure()) {
|
| - parent = Procedure::Cast(topmost_node)->parent();
|
| - } else if (topmost_node->IsConstructor()) {
|
| - parent = Constructor::Cast(topmost_node)->parent();
|
| - } else if (topmost_node->IsField()) {
|
| - parent = Field::Cast(topmost_node)->parent();
|
| - }
|
| - if (parent != NULL && parent->IsClass()) kernel_klass = Class::Cast(parent);
|
| - }
|
| + DiscoverEnclosingElements(
|
| + Z, function, &outermost_function, &outermost_node, &kernel_klass);
|
|
|
| // Mark that we are using [klass]/[kernell_klass] as active class. Resolving
|
| // of type parameters will get resolved via [kernell_klass] unless we are
|
| // nested inside a static factory in which case we will use [member].
|
| ActiveClassScope active_class_scope(&active_class_, kernel_klass, &klass);
|
| - Member* member = topmost_node != NULL && topmost_node->IsMember()
|
| - ? Member::Cast(topmost_node)
|
| + Member* member = ((outermost_node != NULL) && outermost_node->IsMember())
|
| + ? Member::Cast(outermost_node)
|
| : NULL;
|
| ActiveMemberScope active_member(&active_class_, member);
|
|
|
| @@ -2846,12 +2881,12 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFunction(FunctionNode* function,
|
| LocalVariable* variable = scope->VariableAt(i);
|
| if (variable->is_captured()) {
|
| // There is no LocalVariable describing the on-stack parameter so
|
| - // create one directly.
|
| + // create one directly and use the same type.
|
| LocalVariable* parameter =
|
| new (Z) LocalVariable(TokenPosition::kNoSource,
|
| TokenPosition::kNoSource,
|
| Symbols::TempParam(),
|
| - Object::dynamic_type());
|
| + variable->type());
|
| parameter->set_index(parameter_index);
|
| // Mark the stack variable so it will be ignored by the code for
|
| // try/catch.
|
| @@ -3804,6 +3839,24 @@ AbstractType& DartTypeTranslator::TranslateTypeWithoutFinalization(
|
| }
|
|
|
|
|
| +const AbstractType& DartTypeTranslator::TranslateVariableType(
|
| + VariableDeclaration* variable) {
|
| + AbstractType& abstract_type = TranslateType(variable->type());
|
| +
|
| + // We return a new `ZoneHandle` here on purpose: The intermediate language
|
| + // instructions do not make a copy of the handle, so we do it.
|
| + AbstractType& type = Type::ZoneHandle(Z);
|
| +
|
| + if (abstract_type.IsMalformed()) {
|
| + type = AbstractType::dynamic_type().raw();
|
| + } else {
|
| + type = result_.raw();
|
| + }
|
| +
|
| + return type;
|
| +}
|
| +
|
| +
|
| void DartTypeTranslator::VisitInvalidType(InvalidType* node) {
|
| result_ = ClassFinalizer::NewFinalizedMalformedType(
|
| Error::Handle(Z), // No previous error.
|
|
|