Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include <map> | 5 #include <map> |
| 6 #include <set> | 6 #include <set> |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "vm/kernel_to_il.h" | 9 #include "vm/kernel_to_il.h" |
| 10 | 10 |
| (...skipping 1503 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1514 | 1514 |
| 1515 // Dart does not support generic methods yet. | 1515 // Dart does not support generic methods yet. |
| 1516 ASSERT(kernel_arguments->types().length() == 0); | 1516 ASSERT(kernel_arguments->types().length() == 0); |
| 1517 | 1517 |
| 1518 const dart::Instance& receiver = EvaluateExpression(node->receiver()); | 1518 const dart::Instance& receiver = EvaluateExpression(node->receiver()); |
| 1519 dart::Class& klass = dart::Class::Handle( | 1519 dart::Class& klass = dart::Class::Handle( |
| 1520 Z, isolate_->class_table()->At(receiver.GetClassId())); | 1520 Z, isolate_->class_table()->At(receiver.GetClassId())); |
| 1521 ASSERT(!klass.IsNull()); | 1521 ASSERT(!klass.IsNull()); |
| 1522 | 1522 |
| 1523 // Search the superclass chain for the selector. | 1523 // Search the superclass chain for the selector. |
| 1524 // TODO(27590): Can we assume this will never be a no-such-method error? | |
| 1525 dart::Function& function = dart::Function::Handle(Z); | 1524 dart::Function& function = dart::Function::Handle(Z); |
| 1526 const dart::String& method_name = H.DartMethodName(node->name()); | 1525 const dart::String& method_name = H.DartMethodName(node->name()); |
| 1527 while (!klass.IsNull()) { | 1526 while (!klass.IsNull()) { |
| 1528 function = klass.LookupDynamicFunctionAllowPrivate(method_name); | 1527 function = klass.LookupDynamicFunctionAllowPrivate(method_name); |
| 1529 if (!function.IsNull()) break; | 1528 if (!function.IsNull()) break; |
| 1530 klass = klass.SuperClass(); | 1529 klass = klass.SuperClass(); |
| 1531 } | 1530 } |
| 1531 | |
| 1532 // The frontend should guarantee that [MethodInvocation]s inside constant | |
| 1533 // expressions are always valid. | |
| 1532 ASSERT(!function.IsNull()); | 1534 ASSERT(!function.IsNull()); |
| 1533 | 1535 |
| 1534 // Run the method and canonicalize the result. | 1536 // Run the method and canonicalize the result. |
| 1535 const Object& result = RunFunction(function, kernel_arguments, &receiver); | 1537 const Object& result = RunFunction(function, kernel_arguments, &receiver); |
| 1536 result_ ^= result.raw(); | 1538 result_ ^= result.raw(); |
| 1537 result_ = H.Canonicalize(result_); | 1539 result_ = H.Canonicalize(result_); |
| 1538 } | 1540 } |
| 1539 | 1541 |
| 1540 | 1542 |
| 1541 void ConstantEvaluator::VisitStaticGet(StaticGet* node) { | 1543 void ConstantEvaluator::VisitStaticGet(StaticGet* node) { |
| (...skipping 2189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3731 arguments->data()[i] = stack_->definition()->AsPushArgument(); | 3733 arguments->data()[i] = stack_->definition()->AsPushArgument(); |
| 3732 Drop(); | 3734 Drop(); |
| 3733 } | 3735 } |
| 3734 pending_argument_count_ -= count; | 3736 pending_argument_count_ -= count; |
| 3735 ASSERT(pending_argument_count_ >= 0); | 3737 ASSERT(pending_argument_count_ >= 0); |
| 3736 return arguments; | 3738 return arguments; |
| 3737 } | 3739 } |
| 3738 | 3740 |
| 3739 | 3741 |
| 3740 void FlowGraphBuilder::VisitInvalidExpression(InvalidExpression* node) { | 3742 void FlowGraphBuilder::VisitInvalidExpression(InvalidExpression* node) { |
| 3741 // TODO(27590): Once we have better error information we might need to | 3743 // The frontend will take care of emitting normal errors (like |
| 3742 // make some invalid expressions not NSM errors but type/compile-time/... | 3744 // [NoSuchMethodError]s) and only emit [InvalidExpression]s in very special |
| 3743 // errors. | 3745 // situations (e.g. an invalid annotation). |
| 3744 fragment_ = ThrowNoSuchMethodError(); | 3746 fragment_ = ThrowNoSuchMethodError(); |
| 3745 } | 3747 } |
| 3746 | 3748 |
| 3747 | 3749 |
| 3748 void FlowGraphBuilder::VisitNullLiteral(NullLiteral* node) { | 3750 void FlowGraphBuilder::VisitNullLiteral(NullLiteral* node) { |
| 3749 fragment_ = Constant(Instance::ZoneHandle(Z, Instance::null())); | 3751 fragment_ = Constant(Instance::ZoneHandle(Z, Instance::null())); |
| 3750 } | 3752 } |
| 3751 | 3753 |
| 3752 | 3754 |
| 3753 void FlowGraphBuilder::VisitBoolLiteral(BoolLiteral* node) { | 3755 void FlowGraphBuilder::VisitBoolLiteral(BoolLiteral* node) { |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4020 } | 4022 } |
| 4021 | 4023 |
| 4022 | 4024 |
| 4023 void FlowGraphBuilder::VisitVariableGet(VariableGet* node) { | 4025 void FlowGraphBuilder::VisitVariableGet(VariableGet* node) { |
| 4024 fragment_ = LoadLocal(LookupVariable(node->variable())); | 4026 fragment_ = LoadLocal(LookupVariable(node->variable())); |
| 4025 } | 4027 } |
| 4026 | 4028 |
| 4027 | 4029 |
| 4028 void FlowGraphBuilder::VisitVariableSet(VariableSet* node) { | 4030 void FlowGraphBuilder::VisitVariableSet(VariableSet* node) { |
| 4029 Fragment instructions = TranslateExpression(node->expression()); | 4031 Fragment instructions = TranslateExpression(node->expression()); |
| 4030 // The IR should not include assignments to final or const variables. | 4032 instructions += StoreLocal(LookupVariable(node->variable())); |
| 4031 // This is https://github.com/dart-lang/rasta/issues/83. | 4033 fragment_ = instructions; |
| 4032 // | |
| 4033 // TODO(27590): simply ASSERT that the variable is not const or final | |
| 4034 // when that issue is fixed. | |
| 4035 fragment_ = instructions + | |
| 4036 ((node->variable()->IsFinal() || node->variable()->IsConst()) | |
| 4037 ? Drop() + ThrowNoSuchMethodError() | |
| 4038 : StoreLocal(LookupVariable(node->variable()))); | |
| 4039 } | 4034 } |
| 4040 | 4035 |
| 4041 | 4036 |
| 4042 void FlowGraphBuilder::VisitStaticGet(StaticGet* node) { | 4037 void FlowGraphBuilder::VisitStaticGet(StaticGet* node) { |
| 4043 Member* target = node->target(); | 4038 Member* target = node->target(); |
| 4044 if (target->IsField()) { | 4039 if (target->IsField()) { |
| 4045 Field* kernel_field = Field::Cast(target); | 4040 Field* kernel_field = Field::Cast(target); |
| 4046 const dart::Field& field = | 4041 const dart::Field& field = |
| 4047 dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(kernel_field)); | 4042 dart::Field::ZoneHandle(Z, H.LookupFieldByKernelField(kernel_field)); |
| 4048 if (kernel_field->IsConst()) { | 4043 if (kernel_field->IsConst()) { |
| 4049 fragment_ = Constant(constant_evaluator_.EvaluateExpression(node)); | 4044 fragment_ = Constant(constant_evaluator_.EvaluateExpression(node)); |
| 4050 } else { | 4045 } else { |
| 4051 const dart::Class& owner = dart::Class::Handle(Z, field.Owner()); | 4046 const dart::Class& owner = dart::Class::Handle(Z, field.Owner()); |
| 4052 const dart::String& getter_name = H.DartGetterName(kernel_field->name()); | 4047 const dart::String& getter_name = H.DartGetterName(kernel_field->name()); |
| 4053 const Function& getter = | 4048 const Function& getter = |
| 4054 Function::ZoneHandle(Z, owner.LookupStaticFunction(getter_name)); | 4049 Function::ZoneHandle(Z, owner.LookupStaticFunction(getter_name)); |
| 4055 if (getter.IsNull() || !field.has_initializer()) { | 4050 if (getter.IsNull() || !field.has_initializer()) { |
| 4056 Fragment instructions = Constant(field); | 4051 Fragment instructions = Constant(field); |
| 4057 fragment_ = instructions + LoadStaticField(); | 4052 fragment_ = instructions + LoadStaticField(); |
| 4058 } else { | 4053 } else { |
| 4059 // TODO(27590): figure out how to trigger this case and add tests. | |
|
kustermann
2016/11/02 18:41:34
Not sure why this one was here. We hit this case e
| |
| 4060 fragment_ = StaticCall(getter, 0); | 4054 fragment_ = StaticCall(getter, 0); |
| 4061 } | 4055 } |
| 4062 } | 4056 } |
| 4063 } else { | 4057 } else { |
| 4064 Procedure* procedure = Procedure::Cast(target); | 4058 Procedure* procedure = Procedure::Cast(target); |
| 4065 const Function& target = Function::ZoneHandle( | 4059 const Function& target = Function::ZoneHandle( |
| 4066 Z, H.LookupStaticMethodByKernelProcedure(procedure)); | 4060 Z, H.LookupStaticMethodByKernelProcedure(procedure)); |
| 4067 | 4061 |
| 4068 if (procedure->kind() == Procedure::kGetter) { | 4062 if (procedure->kind() == Procedure::kGetter) { |
| 4069 fragment_ = StaticCall(target, 0); | 4063 fragment_ = StaticCall(target, 0); |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4189 void FlowGraphBuilder::VisitStaticInvocation(StaticInvocation* node) { | 4183 void FlowGraphBuilder::VisitStaticInvocation(StaticInvocation* node) { |
| 4190 const Function& target = Function::ZoneHandle( | 4184 const Function& target = Function::ZoneHandle( |
| 4191 Z, H.LookupStaticMethodByKernelProcedure(node->procedure())); | 4185 Z, H.LookupStaticMethodByKernelProcedure(node->procedure())); |
| 4192 const dart::Class& klass = dart::Class::ZoneHandle(Z, target.Owner()); | 4186 const dart::Class& klass = dart::Class::ZoneHandle(Z, target.Owner()); |
| 4193 intptr_t argument_count = node->arguments()->count(); | 4187 intptr_t argument_count = node->arguments()->count(); |
| 4194 if (target.IsGenerativeConstructor() || target.IsFactory()) { | 4188 if (target.IsGenerativeConstructor() || target.IsFactory()) { |
| 4195 // The VM requires a TypeArguments object as first parameter for | 4189 // The VM requires a TypeArguments object as first parameter for |
| 4196 // every factory constructor. | 4190 // every factory constructor. |
| 4197 ++argument_count; | 4191 ++argument_count; |
| 4198 } | 4192 } |
| 4193 | |
| 4199 List<NamedExpression>& named = node->arguments()->named(); | 4194 List<NamedExpression>& named = node->arguments()->named(); |
| 4200 const Array& argument_names = H.ArgumentNames(&named); | 4195 const Array& argument_names = H.ArgumentNames(&named); |
| 4201 | 4196 |
| 4197 // The frontend ensures we the [StaticInvocation] has matching arguments. | |
| 4198 ASSERT(target.AreValidArguments(argument_count, argument_names, NULL)); | |
| 4199 | |
| 4202 Fragment instructions; | 4200 Fragment instructions; |
| 4203 if (!target.AreValidArguments(argument_count, argument_names, NULL)) { | |
| 4204 // An argument mismatch for a static invocation really should not occur | |
| 4205 // in the IR. This is issue https://github.com/dart-lang/rasta/issues/76. | |
| 4206 // | |
| 4207 // TODO(27590): Change this to an ASSERT when that issue is fixed. | |
| 4208 List<Expression>& positional = node->arguments()->positional(); | |
| 4209 for (intptr_t i = 0; i < positional.length(); ++i) { | |
| 4210 instructions += TranslateExpression(positional[i]); | |
| 4211 instructions += Drop(); | |
| 4212 } | |
| 4213 | |
| 4214 for (intptr_t i = 0; i < named.length(); ++i) { | |
| 4215 instructions += TranslateExpression(named[i]->expression()); | |
| 4216 instructions += Drop(); | |
| 4217 } | |
| 4218 | |
| 4219 fragment_ = instructions + ThrowNoSuchMethodError(); | |
| 4220 return; | |
| 4221 } | |
| 4222 | |
| 4223 LocalVariable* instance_variable = NULL; | 4201 LocalVariable* instance_variable = NULL; |
| 4224 | 4202 |
| 4225 // If we cross the Kernel -> VM core library boundary, a [StaticInvocation] | 4203 // If we cross the Kernel -> VM core library boundary, a [StaticInvocation] |
| 4226 // can appear, but the thing we're calling is not a static method, but a | 4204 // can appear, but the thing we're calling is not a static method, but a |
| 4227 // factory constructor. | 4205 // factory constructor. |
| 4228 // The `H.LookupStaticmethodByKernelProcedure` will potentially resolve to the | 4206 // The `H.LookupStaticmethodByKernelProcedure` will potentially resolve to the |
| 4229 // forwarded constructor. | 4207 // forwarded constructor. |
| 4230 // In that case we'll make an instance and pass it as first argument. | 4208 // In that case we'll make an instance and pass it as first argument. |
| 4231 // | 4209 // |
| 4232 // TODO(27590): Get rid of this after we're using core libraries compiled | 4210 // TODO(27590): Get rid of this after we're using core libraries compiled |
| (...skipping 1431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5664 instructions += LoadLocal(closure); | 5642 instructions += LoadLocal(closure); |
| 5665 instructions += LoadLocal(parsed_function_->current_context_var()); | 5643 instructions += LoadLocal(parsed_function_->current_context_var()); |
| 5666 instructions += StoreInstanceField(Closure::context_offset()); | 5644 instructions += StoreInstanceField(Closure::context_offset()); |
| 5667 | 5645 |
| 5668 return instructions; | 5646 return instructions; |
| 5669 } | 5647 } |
| 5670 | 5648 |
| 5671 | 5649 |
| 5672 } // namespace kernel | 5650 } // namespace kernel |
| 5673 } // namespace dart | 5651 } // namespace dart |
| OLD | NEW |