| 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 |