OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "vm/flow_graph_builder.h" | 5 #include "vm/flow_graph_builder.h" |
6 | 6 |
7 #include "lib/invocation_mirror.h" | 7 #include "lib/invocation_mirror.h" |
8 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
9 #include "vm/bit_vector.h" | 9 #include "vm/bit_vector.h" |
10 #include "vm/class_finalizer.h" | 10 #include "vm/class_finalizer.h" |
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 ValueGraphVisitor::VisitBinaryOpNode(node); | 998 ValueGraphVisitor::VisitBinaryOpNode(node); |
999 } | 999 } |
1000 | 1000 |
1001 | 1001 |
1002 void EffectGraphVisitor::Bailout(const char* reason) const { | 1002 void EffectGraphVisitor::Bailout(const char* reason) const { |
1003 owner()->Bailout(reason); | 1003 owner()->Bailout(reason); |
1004 } | 1004 } |
1005 | 1005 |
1006 | 1006 |
1007 void EffectGraphVisitor::InlineBailout(const char* reason) const { | 1007 void EffectGraphVisitor::InlineBailout(const char* reason) const { |
1008 owner()->parsed_function()->function().set_is_inlinable(false); | 1008 owner()->function().set_is_inlinable(false); |
1009 if (owner()->IsInlining()) owner()->Bailout(reason); | 1009 if (owner()->IsInlining()) owner()->Bailout(reason); |
1010 } | 1010 } |
1011 | 1011 |
1012 | 1012 |
1013 // <Statement> ::= Return { value: <Expression> | 1013 // <Statement> ::= Return { value: <Expression> |
1014 // inlined_finally_list: <InlinedFinally>* } | 1014 // inlined_finally_list: <InlinedFinally>* } |
1015 void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) { | 1015 void EffectGraphVisitor::VisitReturnNode(ReturnNode* node) { |
1016 ValueGraphVisitor for_value(owner()); | 1016 ValueGraphVisitor for_value(owner()); |
1017 node->value()->Visit(&for_value); | 1017 node->value()->Visit(&for_value); |
1018 Append(for_value); | 1018 Append(for_value); |
(...skipping 13 matching lines...) Expand all Loading... |
1032 } | 1032 } |
1033 } | 1033 } |
1034 return_value = Bind(BuildLoadLocal(*temp)); | 1034 return_value = Bind(BuildLoadLocal(*temp)); |
1035 } | 1035 } |
1036 | 1036 |
1037 // Call to stub that checks whether the debugger is in single | 1037 // Call to stub that checks whether the debugger is in single |
1038 // step mode. This call must happen before the contexts are | 1038 // step mode. This call must happen before the contexts are |
1039 // unchained so that captured variables can be inspected. | 1039 // unchained so that captured variables can be inspected. |
1040 // No debugger check is done in native functions or for return | 1040 // No debugger check is done in native functions or for return |
1041 // statements for which there is no associated source position. | 1041 // statements for which there is no associated source position. |
1042 const Function& function = owner()->parsed_function()->function(); | 1042 const Function& function = owner()->function(); |
1043 if ((node->token_pos() != Scanner::kNoSourcePos) && !function.is_native()) { | 1043 if ((node->token_pos() != Scanner::kNoSourcePos) && !function.is_native()) { |
1044 AddInstruction(new(I) DebugStepCheckInstr(node->token_pos(), | 1044 AddInstruction(new(I) DebugStepCheckInstr(node->token_pos(), |
1045 RawPcDescriptors::kRuntimeCall)); | 1045 RawPcDescriptors::kRuntimeCall)); |
1046 } | 1046 } |
1047 | 1047 |
1048 if (FLAG_enable_type_checks) { | 1048 if (FLAG_enable_type_checks) { |
1049 const bool is_implicit_dynamic_getter = | 1049 const bool is_implicit_dynamic_getter = |
1050 (!function.is_static() && | 1050 (!function.is_static() && |
1051 ((function.kind() == RawFunction::kImplicitGetter) || | 1051 ((function.kind() == RawFunction::kImplicitGetter) || |
1052 (function.kind() == RawFunction::kImplicitStaticFinalGetter))); | 1052 (function.kind() == RawFunction::kImplicitStaticFinalGetter))); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1136 | 1136 |
1137 | 1137 |
1138 void ValueGraphVisitor::VisitTypeNode(TypeNode* node) { | 1138 void ValueGraphVisitor::VisitTypeNode(TypeNode* node) { |
1139 const AbstractType& type = node->type(); | 1139 const AbstractType& type = node->type(); |
1140 // Type may be malbounded, but not malformed. | 1140 // Type may be malbounded, but not malformed. |
1141 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 1141 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
1142 if (type.IsInstantiated()) { | 1142 if (type.IsInstantiated()) { |
1143 ReturnDefinition(new(I) ConstantInstr(type)); | 1143 ReturnDefinition(new(I) ConstantInstr(type)); |
1144 } else { | 1144 } else { |
1145 const Class& instantiator_class = Class::ZoneHandle( | 1145 const Class& instantiator_class = Class::ZoneHandle( |
1146 I, owner()->parsed_function()->function().Owner()); | 1146 I, owner()->function().Owner()); |
1147 Value* instantiator_value = BuildInstantiatorTypeArguments( | 1147 Value* instantiator_value = BuildInstantiatorTypeArguments( |
1148 node->token_pos(), instantiator_class, NULL); | 1148 node->token_pos(), instantiator_class, NULL); |
1149 ReturnDefinition(new(I) InstantiateTypeInstr( | 1149 ReturnDefinition(new(I) InstantiateTypeInstr( |
1150 node->token_pos(), type, instantiator_class, instantiator_value)); | 1150 node->token_pos(), type, instantiator_class, instantiator_value)); |
1151 } | 1151 } |
1152 } | 1152 } |
1153 | 1153 |
1154 | 1154 |
1155 // Returns true if the type check can be skipped, for example, if the | 1155 // Returns true if the type check can be skipped, for example, if the |
1156 // destination type is dynamic or if the compile type of the value is a subtype | 1156 // destination type is dynamic or if the compile type of the value is a subtype |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1389 owner()->ic_data_array()); | 1389 owner()->ic_data_array()); |
1390 ReturnDefinition(call); | 1390 ReturnDefinition(call); |
1391 } | 1391 } |
1392 | 1392 |
1393 | 1393 |
1394 void EffectGraphVisitor::BuildTypecheckPushArguments( | 1394 void EffectGraphVisitor::BuildTypecheckPushArguments( |
1395 intptr_t token_pos, | 1395 intptr_t token_pos, |
1396 PushArgumentInstr** push_instantiator_result, | 1396 PushArgumentInstr** push_instantiator_result, |
1397 PushArgumentInstr** push_instantiator_type_arguments_result) { | 1397 PushArgumentInstr** push_instantiator_type_arguments_result) { |
1398 const Class& instantiator_class = Class::Handle( | 1398 const Class& instantiator_class = Class::Handle( |
1399 I, owner()->parsed_function()->function().Owner()); | 1399 I, owner()->function().Owner()); |
1400 // Since called only when type tested against is not instantiated. | 1400 // Since called only when type tested against is not instantiated. |
1401 ASSERT(instantiator_class.NumTypeParameters() > 0); | 1401 ASSERT(instantiator_class.NumTypeParameters() > 0); |
1402 Value* instantiator_type_arguments = NULL; | 1402 Value* instantiator_type_arguments = NULL; |
1403 Value* instantiator = BuildInstantiator(instantiator_class); | 1403 Value* instantiator = BuildInstantiator(instantiator_class); |
1404 if (instantiator == NULL) { | 1404 if (instantiator == NULL) { |
1405 // No instantiator when inside factory. | 1405 // No instantiator when inside factory. |
1406 *push_instantiator_result = PushArgument(BuildNullValue()); | 1406 *push_instantiator_result = PushArgument(BuildNullValue()); |
1407 instantiator_type_arguments = | 1407 instantiator_type_arguments = |
1408 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); | 1408 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); |
1409 } else { | 1409 } else { |
1410 instantiator = Bind(BuildStoreExprTemp(instantiator)); | 1410 instantiator = Bind(BuildStoreExprTemp(instantiator)); |
1411 *push_instantiator_result = PushArgument(instantiator); | 1411 *push_instantiator_result = PushArgument(instantiator); |
1412 Value* loaded = Bind(BuildLoadExprTemp()); | 1412 Value* loaded = Bind(BuildLoadExprTemp()); |
1413 instantiator_type_arguments = | 1413 instantiator_type_arguments = |
1414 BuildInstantiatorTypeArguments(token_pos, instantiator_class, loaded); | 1414 BuildInstantiatorTypeArguments(token_pos, instantiator_class, loaded); |
1415 } | 1415 } |
1416 *push_instantiator_type_arguments_result = | 1416 *push_instantiator_type_arguments_result = |
1417 PushArgument(instantiator_type_arguments); | 1417 PushArgument(instantiator_type_arguments); |
1418 } | 1418 } |
1419 | 1419 |
1420 | 1420 |
1421 | 1421 |
1422 void EffectGraphVisitor::BuildTypecheckArguments( | 1422 void EffectGraphVisitor::BuildTypecheckArguments( |
1423 intptr_t token_pos, | 1423 intptr_t token_pos, |
1424 Value** instantiator_result, | 1424 Value** instantiator_result, |
1425 Value** instantiator_type_arguments_result) { | 1425 Value** instantiator_type_arguments_result) { |
1426 Value* instantiator = NULL; | 1426 Value* instantiator = NULL; |
1427 Value* instantiator_type_arguments = NULL; | 1427 Value* instantiator_type_arguments = NULL; |
1428 const Class& instantiator_class = Class::Handle( | 1428 const Class& instantiator_class = Class::Handle( |
1429 I, owner()->parsed_function()->function().Owner()); | 1429 I, owner()->function().Owner()); |
1430 // Since called only when type tested against is not instantiated. | 1430 // Since called only when type tested against is not instantiated. |
1431 ASSERT(instantiator_class.NumTypeParameters() > 0); | 1431 ASSERT(instantiator_class.NumTypeParameters() > 0); |
1432 instantiator = BuildInstantiator(instantiator_class); | 1432 instantiator = BuildInstantiator(instantiator_class); |
1433 if (instantiator == NULL) { | 1433 if (instantiator == NULL) { |
1434 // No instantiator when inside factory. | 1434 // No instantiator when inside factory. |
1435 instantiator = BuildNullValue(); | 1435 instantiator = BuildNullValue(); |
1436 instantiator_type_arguments = | 1436 instantiator_type_arguments = |
1437 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); | 1437 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); |
1438 } else { | 1438 } else { |
1439 // Preserve instantiator. | 1439 // Preserve instantiator. |
(...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2442 // The context scope may have already been set by the non-optimizing | 2442 // The context scope may have already been set by the non-optimizing |
2443 // compiler. If it was not, set it here. | 2443 // compiler. If it was not, set it here. |
2444 if (function.context_scope() == ContextScope::null()) { | 2444 if (function.context_scope() == ContextScope::null()) { |
2445 ASSERT(!is_implicit); | 2445 ASSERT(!is_implicit); |
2446 const ContextScope& context_scope = ContextScope::ZoneHandle( | 2446 const ContextScope& context_scope = ContextScope::ZoneHandle( |
2447 I, node->scope()->PreserveOuterScope(owner()->context_level())); | 2447 I, node->scope()->PreserveOuterScope(owner()->context_level())); |
2448 ASSERT(!function.HasCode()); | 2448 ASSERT(!function.HasCode()); |
2449 ASSERT(function.context_scope() == ContextScope::null()); | 2449 ASSERT(function.context_scope() == ContextScope::null()); |
2450 function.set_context_scope(context_scope); | 2450 function.set_context_scope(context_scope); |
2451 const Class& cls = Class::Handle( | 2451 const Class& cls = Class::Handle( |
2452 I, owner()->parsed_function()->function().Owner()); | 2452 I, owner()->function().Owner()); |
2453 // The closure is now properly setup, add it to the lookup table. | 2453 // The closure is now properly setup, add it to the lookup table. |
2454 // It is possible that the compiler creates more than one function | 2454 // It is possible that the compiler creates more than one function |
2455 // object for the same closure, e.g. when inlining nodes from | 2455 // object for the same closure, e.g. when inlining nodes from |
2456 // finally clauses. If we already have a function object for the | 2456 // finally clauses. If we already have a function object for the |
2457 // same closure, do not add a second one. We compare the origin | 2457 // same closure, do not add a second one. We compare the origin |
2458 // class, token position, and parent function to detect duplicates. | 2458 // class, token position, and parent function to detect duplicates. |
2459 // Note that we can have two different closure object for the same | 2459 // Note that we can have two different closure object for the same |
2460 // source text representation of the closure: one with a non-closurized | 2460 // source text representation of the closure: one with a non-closurized |
2461 // parent, and one with a closurized parent function. | 2461 // parent, and one with a closurized parent function. |
2462 | 2462 |
(...skipping 15 matching lines...) Expand all Loading... |
2478 // pass the type arguments of the instantiator. | 2478 // pass the type arguments of the instantiator. |
2479 const Class& cls = Class::ZoneHandle(I, function.signature_class()); | 2479 const Class& cls = Class::ZoneHandle(I, function.signature_class()); |
2480 ASSERT(!cls.IsNull()); | 2480 ASSERT(!cls.IsNull()); |
2481 const bool requires_type_arguments = cls.NumTypeArguments() > 0; | 2481 const bool requires_type_arguments = cls.NumTypeArguments() > 0; |
2482 Value* type_arguments = NULL; | 2482 Value* type_arguments = NULL; |
2483 if (requires_type_arguments) { | 2483 if (requires_type_arguments) { |
2484 ASSERT(cls.type_arguments_field_offset() == | 2484 ASSERT(cls.type_arguments_field_offset() == |
2485 Closure::type_arguments_offset()); | 2485 Closure::type_arguments_offset()); |
2486 ASSERT(cls.instance_size() == Closure::InstanceSize()); | 2486 ASSERT(cls.instance_size() == Closure::InstanceSize()); |
2487 const Class& instantiator_class = Class::Handle( | 2487 const Class& instantiator_class = Class::Handle( |
2488 I, owner()->parsed_function()->function().Owner()); | 2488 I, owner()->function().Owner()); |
2489 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), | 2489 type_arguments = BuildInstantiatorTypeArguments(node->token_pos(), |
2490 instantiator_class, | 2490 instantiator_class, |
2491 NULL); | 2491 NULL); |
2492 arguments->Add(PushArgument(type_arguments)); | 2492 arguments->Add(PushArgument(type_arguments)); |
2493 } | 2493 } |
2494 AllocateObjectInstr* alloc = new(I) AllocateObjectInstr(node->token_pos(), | 2494 AllocateObjectInstr* alloc = new(I) AllocateObjectInstr(node->token_pos(), |
2495 cls, | 2495 cls, |
2496 arguments); | 2496 arguments); |
2497 alloc->set_closure_function(function); | 2497 alloc->set_closure_function(function); |
2498 | 2498 |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2800 // StaticCall(constructor, t_n+1, t_n+2, ...) | 2800 // StaticCall(constructor, t_n+1, t_n+2, ...) |
2801 // No need to preserve allocated value (simpler than in ValueGraphVisitor). | 2801 // No need to preserve allocated value (simpler than in ValueGraphVisitor). |
2802 Value* allocated_value = BuildObjectAllocation(node); | 2802 Value* allocated_value = BuildObjectAllocation(node); |
2803 PushArgumentInstr* push_allocated_value = PushArgument(allocated_value); | 2803 PushArgumentInstr* push_allocated_value = PushArgument(allocated_value); |
2804 BuildConstructorCall(node, push_allocated_value); | 2804 BuildConstructorCall(node, push_allocated_value); |
2805 } | 2805 } |
2806 | 2806 |
2807 | 2807 |
2808 Value* EffectGraphVisitor::BuildInstantiator(const Class& instantiator_class) { | 2808 Value* EffectGraphVisitor::BuildInstantiator(const Class& instantiator_class) { |
2809 ASSERT(instantiator_class.NumTypeParameters() > 0); | 2809 ASSERT(instantiator_class.NumTypeParameters() > 0); |
2810 Function& outer_function = | 2810 Function& outer_function = Function::Handle(I, owner()->function().raw()); |
2811 Function::Handle(I, owner()->parsed_function()->function().raw()); | |
2812 while (outer_function.IsLocalFunction()) { | 2811 while (outer_function.IsLocalFunction()) { |
2813 outer_function = outer_function.parent_function(); | 2812 outer_function = outer_function.parent_function(); |
2814 } | 2813 } |
2815 if (outer_function.IsFactory()) { | 2814 if (outer_function.IsFactory()) { |
2816 return NULL; | 2815 return NULL; |
2817 } | 2816 } |
2818 | 2817 |
2819 LocalVariable* instantiator = owner()->parsed_function()->instantiator(); | 2818 LocalVariable* instantiator = owner()->parsed_function()->instantiator(); |
2820 ASSERT(instantiator != NULL); | 2819 ASSERT(instantiator != NULL); |
2821 Value* result = Bind(BuildLoadLocal(*instantiator)); | 2820 Value* result = Bind(BuildLoadLocal(*instantiator)); |
(...skipping 15 matching lines...) Expand all Loading... |
2837 Type& type = Type::Handle( | 2836 Type& type = Type::Handle( |
2838 I, | 2837 I, |
2839 Type::New(instantiator_class, type_arguments, token_pos, Heap::kNew)); | 2838 Type::New(instantiator_class, type_arguments, token_pos, Heap::kNew)); |
2840 type ^= ClassFinalizer::FinalizeType( | 2839 type ^= ClassFinalizer::FinalizeType( |
2841 instantiator_class, type, ClassFinalizer::kFinalize); | 2840 instantiator_class, type, ClassFinalizer::kFinalize); |
2842 ASSERT(!type.IsMalformedOrMalbounded()); | 2841 ASSERT(!type.IsMalformedOrMalbounded()); |
2843 type_arguments = type.arguments(); | 2842 type_arguments = type.arguments(); |
2844 type_arguments = type_arguments.Canonicalize(); | 2843 type_arguments = type_arguments.Canonicalize(); |
2845 return Bind(new(I) ConstantInstr(type_arguments)); | 2844 return Bind(new(I) ConstantInstr(type_arguments)); |
2846 } | 2845 } |
2847 Function& outer_function = | 2846 Function& outer_function = Function::Handle(I, owner()->function().raw()); |
2848 Function::Handle(I, owner()->parsed_function()->function().raw()); | |
2849 while (outer_function.IsLocalFunction()) { | 2847 while (outer_function.IsLocalFunction()) { |
2850 outer_function = outer_function.parent_function(); | 2848 outer_function = outer_function.parent_function(); |
2851 } | 2849 } |
2852 if (outer_function.IsFactory()) { | 2850 if (outer_function.IsFactory()) { |
2853 // No instantiator for factories. | 2851 // No instantiator for factories. |
2854 ASSERT(instantiator == NULL); | 2852 ASSERT(instantiator == NULL); |
2855 LocalVariable* instantiator_var = | 2853 LocalVariable* instantiator_var = |
2856 owner()->parsed_function()->instantiator(); | 2854 owner()->parsed_function()->instantiator(); |
2857 ASSERT(instantiator_var != NULL); | 2855 ASSERT(instantiator_var != NULL); |
2858 return Bind(BuildLoadLocal(*instantiator_var)); | 2856 return Bind(BuildLoadLocal(*instantiator_var)); |
(...skipping 18 matching lines...) Expand all Loading... |
2877 | 2875 |
2878 | 2876 |
2879 Value* EffectGraphVisitor::BuildInstantiatedTypeArguments( | 2877 Value* EffectGraphVisitor::BuildInstantiatedTypeArguments( |
2880 intptr_t token_pos, | 2878 intptr_t token_pos, |
2881 const TypeArguments& type_arguments) { | 2879 const TypeArguments& type_arguments) { |
2882 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { | 2880 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { |
2883 return Bind(new(I) ConstantInstr(type_arguments)); | 2881 return Bind(new(I) ConstantInstr(type_arguments)); |
2884 } | 2882 } |
2885 // The type arguments are uninstantiated. | 2883 // The type arguments are uninstantiated. |
2886 const Class& instantiator_class = Class::ZoneHandle( | 2884 const Class& instantiator_class = Class::ZoneHandle( |
2887 I, owner()->parsed_function()->function().Owner()); | 2885 I, owner()->function().Owner()); |
2888 Value* instantiator_value = | 2886 Value* instantiator_value = |
2889 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); | 2887 BuildInstantiatorTypeArguments(token_pos, instantiator_class, NULL); |
2890 const bool use_instantiator_type_args = | 2888 const bool use_instantiator_type_args = |
2891 type_arguments.IsUninstantiatedIdentity() || | 2889 type_arguments.IsUninstantiatedIdentity() || |
2892 type_arguments.CanShareInstantiatorTypeArguments(instantiator_class); | 2890 type_arguments.CanShareInstantiatorTypeArguments(instantiator_class); |
2893 if (use_instantiator_type_args) { | 2891 if (use_instantiator_type_args) { |
2894 return instantiator_value; | 2892 return instantiator_value; |
2895 } else { | 2893 } else { |
2896 return Bind(new(I) InstantiateTypeArgumentsInstr(token_pos, | 2894 return Bind(new(I) InstantiateTypeArgumentsInstr(token_pos, |
2897 type_arguments, | 2895 type_arguments, |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3183 | 3181 |
3184 | 3182 |
3185 LoadLocalInstr* EffectGraphVisitor::BuildLoadThisVar(LocalScope* scope) { | 3183 LoadLocalInstr* EffectGraphVisitor::BuildLoadThisVar(LocalScope* scope) { |
3186 LocalVariable* receiver_var = scope->LookupVariable(Symbols::This(), | 3184 LocalVariable* receiver_var = scope->LookupVariable(Symbols::This(), |
3187 true); // Test only. | 3185 true); // Test only. |
3188 return new(I) LoadLocalInstr(*receiver_var); | 3186 return new(I) LoadLocalInstr(*receiver_var); |
3189 } | 3187 } |
3190 | 3188 |
3191 | 3189 |
3192 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { | 3190 void EffectGraphVisitor::VisitNativeBodyNode(NativeBodyNode* node) { |
3193 const Function& function = owner()->parsed_function()->function(); | 3191 const Function& function = owner()->function(); |
3194 if (!function.IsClosureFunction()) { | 3192 if (!function.IsClosureFunction()) { |
3195 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); | 3193 MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function); |
3196 switch (kind) { | 3194 switch (kind) { |
3197 case MethodRecognizer::kObjectEquals: { | 3195 case MethodRecognizer::kObjectEquals: { |
3198 Value* receiver = Bind(BuildLoadThisVar(node->scope())); | 3196 Value* receiver = Bind(BuildLoadThisVar(node->scope())); |
3199 LocalVariable* other_var = | 3197 LocalVariable* other_var = |
3200 node->scope()->LookupVariable(Symbols::Other(), | 3198 node->scope()->LookupVariable(Symbols::Other(), |
3201 true); // Test only. | 3199 true); // Test only. |
3202 Value* other = Bind(new(I) LoadLocalInstr(*other_var)); | 3200 Value* other = Bind(new(I) LoadLocalInstr(*other_var)); |
3203 // Receiver is not a number because numbers override equality. | 3201 // Receiver is not a number because numbers override equality. |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3704 } | 3702 } |
3705 | 3703 |
3706 | 3704 |
3707 void ValueGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { | 3705 void ValueGraphVisitor::VisitStoreIndexedNode(StoreIndexedNode* node) { |
3708 ReturnDefinition(BuildStoreIndexedValues(node, kResultNeeded)); | 3706 ReturnDefinition(BuildStoreIndexedValues(node, kResultNeeded)); |
3709 } | 3707 } |
3710 | 3708 |
3711 | 3709 |
3712 bool EffectGraphVisitor::HasContextScope() const { | 3710 bool EffectGraphVisitor::HasContextScope() const { |
3713 const ContextScope& context_scope = ContextScope::Handle( | 3711 const ContextScope& context_scope = ContextScope::Handle( |
3714 owner()->parsed_function()->function().context_scope()); | 3712 owner()->function().context_scope()); |
3715 return !context_scope.IsNull() && (context_scope.num_variables() > 0); | 3713 return !context_scope.IsNull() && (context_scope.num_variables() > 0); |
3716 } | 3714 } |
3717 | 3715 |
3718 | 3716 |
3719 void EffectGraphVisitor::UnchainContexts(intptr_t n) { | 3717 void EffectGraphVisitor::UnchainContexts(intptr_t n) { |
3720 if (n > 0) { | 3718 if (n > 0) { |
3721 Value* context = Bind(BuildCurrentContext()); | 3719 Value* context = Bind(BuildCurrentContext()); |
3722 while (n-- > 0) { | 3720 while (n-- > 0) { |
3723 context = Bind( | 3721 context = Bind( |
3724 new(I) LoadFieldInstr(context, | 3722 new(I) LoadFieldInstr(context, |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3762 kEmitStoreBarrier, | 3760 kEmitStoreBarrier, |
3763 Scanner::kNoSourcePos)); | 3761 Scanner::kNoSourcePos)); |
3764 } | 3762 } |
3765 Do(BuildStoreContext(Bind(ExitTempLocalScope(tmp_var)))); | 3763 Do(BuildStoreContext(Bind(ExitTempLocalScope(tmp_var)))); |
3766 } | 3764 } |
3767 | 3765 |
3768 // If this node_sequence is the body of the function being compiled, copy | 3766 // If this node_sequence is the body of the function being compiled, copy |
3769 // the captured parameters from the frame into the context. | 3767 // the captured parameters from the frame into the context. |
3770 if (is_top_level_sequence) { | 3768 if (is_top_level_sequence) { |
3771 ASSERT(scope->context_level() == 1); | 3769 ASSERT(scope->context_level() == 1); |
3772 const Function& function = owner()->parsed_function()->function(); | 3770 const Function& function = owner()->function(); |
3773 const int num_params = function.NumParameters(); | 3771 const int num_params = function.NumParameters(); |
3774 int param_frame_index = (num_params == function.num_fixed_parameters()) ? | 3772 int param_frame_index = (num_params == function.num_fixed_parameters()) ? |
3775 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp; | 3773 (kParamEndSlotFromFp + num_params) : kFirstLocalSlotFromFp; |
3776 for (int pos = 0; pos < num_params; param_frame_index--, pos++) { | 3774 for (int pos = 0; pos < num_params; param_frame_index--, pos++) { |
3777 const LocalVariable& parameter = *scope->VariableAt(pos); | 3775 const LocalVariable& parameter = *scope->VariableAt(pos); |
3778 ASSERT(parameter.owner() == scope); | 3776 ASSERT(parameter.owner() == scope); |
3779 if (parameter.is_captured()) { | 3777 if (parameter.is_captured()) { |
3780 // Create a temporary local describing the original position. | 3778 // Create a temporary local describing the original position. |
3781 const String& temp_name = Symbols::TempParam(); | 3779 const String& temp_name = Symbols::TempParam(); |
3782 LocalVariable* temp_local = new(I) LocalVariable( | 3780 LocalVariable* temp_local = new(I) LocalVariable( |
(...skipping 17 matching lines...) Expand all Loading... |
3800 Value* null_constant = Bind(new(I) ConstantInstr( | 3798 Value* null_constant = Bind(new(I) ConstantInstr( |
3801 Object::ZoneHandle(I, Object::null()))); | 3799 Object::ZoneHandle(I, Object::null()))); |
3802 Do(BuildStoreLocal(*temp_local, null_constant)); | 3800 Do(BuildStoreLocal(*temp_local, null_constant)); |
3803 } | 3801 } |
3804 } | 3802 } |
3805 } | 3803 } |
3806 } | 3804 } |
3807 | 3805 |
3808 // This check may be deleted if the generated code is leaf. | 3806 // This check may be deleted if the generated code is leaf. |
3809 // Native functions don't need a stack check at entry. | 3807 // Native functions don't need a stack check at entry. |
3810 const Function& function = owner()->parsed_function()->function(); | 3808 const Function& function = owner()->function(); |
3811 if (is_top_level_sequence && !function.is_native()) { | 3809 if (is_top_level_sequence && !function.is_native()) { |
3812 // Always allocate CheckOverflowInstr so that deopt-ids match regardless | 3810 // Always allocate CheckOverflowInstr so that deopt-ids match regardless |
3813 // if we inline or not. | 3811 // if we inline or not. |
3814 if (!function.IsImplicitGetterFunction() && | 3812 if (!function.IsImplicitGetterFunction() && |
3815 !function.IsImplicitSetterFunction()) { | 3813 !function.IsImplicitSetterFunction()) { |
3816 CheckStackOverflowInstr* check = | 3814 CheckStackOverflowInstr* check = |
3817 new(I) CheckStackOverflowInstr(function.token_pos(), 0); | 3815 new(I) CheckStackOverflowInstr(function.token_pos(), 0); |
3818 // If we are inlining don't actually attach the stack check. We must still | 3816 // If we are inlining don't actually attach the stack check. We must still |
3819 // create the stack check in order to allocate a deopt id. | 3817 // create the stack check in order to allocate a deopt id. |
3820 if (!owner()->IsInlining()) { | 3818 if (!owner()->IsInlining()) { |
3821 AddInstruction(check); | 3819 AddInstruction(check); |
3822 } | 3820 } |
3823 } | 3821 } |
3824 } | 3822 } |
3825 | 3823 |
3826 if (FLAG_enable_type_checks && is_top_level_sequence) { | 3824 if (FLAG_enable_type_checks && is_top_level_sequence) { |
3827 const Function& function = owner()->parsed_function()->function(); | 3825 const Function& function = owner()->function(); |
3828 const int num_params = function.NumParameters(); | 3826 const int num_params = function.NumParameters(); |
3829 int pos = 0; | 3827 int pos = 0; |
3830 if (function.IsConstructor()) { | 3828 if (function.IsConstructor()) { |
3831 // Skip type checking of receiver and phase for constructor functions. | 3829 // Skip type checking of receiver and phase for constructor functions. |
3832 pos = 2; | 3830 pos = 2; |
3833 } else if (function.IsFactory() || function.IsDynamicFunction()) { | 3831 } else if (function.IsFactory() || function.IsDynamicFunction()) { |
3834 // Skip type checking of type arguments for factory functions. | 3832 // Skip type checking of type arguments for factory functions. |
3835 // Skip type checking of receiver for instance functions. | 3833 // Skip type checking of receiver for instance functions. |
3836 pos = 1; | 3834 pos = 1; |
3837 } | 3835 } |
(...skipping 11 matching lines...) Expand all Loading... |
3849 parameter.name())); | 3847 parameter.name())); |
3850 } | 3848 } |
3851 pos++; | 3849 pos++; |
3852 } | 3850 } |
3853 } | 3851 } |
3854 | 3852 |
3855 // Continuation part: | 3853 // Continuation part: |
3856 // If this node sequence is the body of an async closure leave room for a | 3854 // If this node sequence is the body of an async closure leave room for a |
3857 // preamble. The preamble is generated after visiting the body. | 3855 // preamble. The preamble is generated after visiting the body. |
3858 GotoInstr* preamble_start = NULL; | 3856 GotoInstr* preamble_start = NULL; |
3859 if (is_top_level_sequence && | 3857 if (is_top_level_sequence && (owner()->function().is_async_closure())) { |
3860 (owner()->parsed_function()->function().is_async_closure())) { | |
3861 JoinEntryInstr* preamble_end = new(I) JoinEntryInstr( | 3858 JoinEntryInstr* preamble_end = new(I) JoinEntryInstr( |
3862 owner()->AllocateBlockId(), owner()->try_index()); | 3859 owner()->AllocateBlockId(), owner()->try_index()); |
3863 ASSERT(exit() != NULL); | 3860 ASSERT(exit() != NULL); |
3864 exit()->Goto(preamble_end); | 3861 exit()->Goto(preamble_end); |
3865 ASSERT(exit()->next()->IsGoto()); | 3862 ASSERT(exit()->next()->IsGoto()); |
3866 preamble_start = exit()->next()->AsGoto(); | 3863 preamble_start = exit()->next()->AsGoto(); |
3867 ASSERT(preamble_start->IsGoto()); | 3864 ASSERT(preamble_start->IsGoto()); |
3868 exit_ = preamble_end; | 3865 exit_ = preamble_end; |
3869 } | 3866 } |
3870 | 3867 |
3871 intptr_t i = 0; | 3868 intptr_t i = 0; |
3872 while (is_open() && (i < node->length())) { | 3869 while (is_open() && (i < node->length())) { |
3873 EffectGraphVisitor for_effect(owner()); | 3870 EffectGraphVisitor for_effect(owner()); |
3874 node->NodeAt(i++)->Visit(&for_effect); | 3871 node->NodeAt(i++)->Visit(&for_effect); |
3875 Append(for_effect); | 3872 Append(for_effect); |
3876 if (!is_open()) { | 3873 if (!is_open()) { |
3877 // E.g., because of a JumpNode. | 3874 // E.g., because of a JumpNode. |
3878 break; | 3875 break; |
3879 } | 3876 } |
3880 } | 3877 } |
3881 | 3878 |
3882 // Continuation part: | 3879 // Continuation part: |
3883 // After generating the CFG for the body we can create the preamble because we | 3880 // After generating the CFG for the body we can create the preamble because we |
3884 // know exactly how many continuation states we need. | 3881 // know exactly how many continuation states we need. |
3885 if (is_top_level_sequence && | 3882 if (is_top_level_sequence && (owner()->function().is_async_closure())) { |
3886 (owner()->parsed_function()->function().is_async_closure())) { | |
3887 ASSERT(preamble_start != NULL); | 3883 ASSERT(preamble_start != NULL); |
3888 // We are at the top level. Fetch the corresponding scope. | 3884 // We are at the top level. Fetch the corresponding scope. |
3889 LocalScope* top_scope = node->scope(); | 3885 LocalScope* top_scope = node->scope(); |
3890 LocalVariable* jump_var = top_scope->LookupVariable( | 3886 LocalVariable* jump_var = top_scope->LookupVariable( |
3891 Symbols::AwaitJumpVar(), false); | 3887 Symbols::AwaitJumpVar(), false); |
3892 ASSERT(jump_var != NULL && jump_var->is_captured()); | 3888 ASSERT(jump_var != NULL && jump_var->is_captured()); |
3893 | 3889 |
3894 Instruction* saved_entry = entry_; | 3890 Instruction* saved_entry = entry_; |
3895 Instruction* saved_exit = exit_; | 3891 Instruction* saved_exit = exit_; |
3896 entry_ = NULL; | 3892 entry_ = NULL; |
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4316 Report::MessageF(Report::kBailout, | 4312 Report::MessageF(Report::kBailout, |
4317 Script::Handle(function.script()), | 4313 Script::Handle(function.script()), |
4318 function.token_pos(), | 4314 function.token_pos(), |
4319 "FlowGraphBuilder Bailout: %s %s", | 4315 "FlowGraphBuilder Bailout: %s %s", |
4320 String::Handle(function.name()).ToCString(), | 4316 String::Handle(function.name()).ToCString(), |
4321 reason); | 4317 reason); |
4322 UNREACHABLE(); | 4318 UNREACHABLE(); |
4323 } | 4319 } |
4324 | 4320 |
4325 } // namespace dart | 4321 } // namespace dart |
OLD | NEW |