| 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/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 1215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1226 return; | 1226 return; |
| 1227 } | 1227 } |
| 1228 const TokenPosition token_pos = node->token_pos(); | 1228 const TokenPosition token_pos = node->token_pos(); |
| 1229 Value* instantiator_type_arguments = NULL; | 1229 Value* instantiator_type_arguments = NULL; |
| 1230 if (type.IsInstantiated(kCurrentClass)) { | 1230 if (type.IsInstantiated(kCurrentClass)) { |
| 1231 instantiator_type_arguments = BuildNullValue(token_pos); | 1231 instantiator_type_arguments = BuildNullValue(token_pos); |
| 1232 } else { | 1232 } else { |
| 1233 instantiator_type_arguments = BuildInstantiatorTypeArguments(token_pos); | 1233 instantiator_type_arguments = BuildInstantiatorTypeArguments(token_pos); |
| 1234 } | 1234 } |
| 1235 Value* function_type_arguments = NULL; | 1235 Value* function_type_arguments = NULL; |
| 1236 if (type.IsInstantiated(kCurrentFunction)) { | 1236 if (type.IsInstantiated(kFunctions)) { |
| 1237 function_type_arguments = BuildNullValue(token_pos); | 1237 function_type_arguments = BuildNullValue(token_pos); |
| 1238 } else { | 1238 } else { |
| 1239 function_type_arguments = BuildFunctionTypeArguments(token_pos); | 1239 function_type_arguments = BuildFunctionTypeArguments(token_pos); |
| 1240 } | 1240 } |
| 1241 ReturnDefinition(new (Z) InstantiateTypeInstr( | 1241 ReturnDefinition(new (Z) InstantiateTypeInstr( |
| 1242 token_pos, type, instantiator_type_arguments, function_type_arguments)); | 1242 token_pos, type, instantiator_type_arguments, function_type_arguments)); |
| 1243 } | 1243 } |
| 1244 | 1244 |
| 1245 | 1245 |
| 1246 // Returns true if the type check can be skipped, for example, if the | 1246 // Returns true if the type check can be skipped, for example, if the |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1426 } else { | 1426 } else { |
| 1427 Value* instantiator_type_args = BuildInstantiatorTypeArguments(token_pos); | 1427 Value* instantiator_type_args = BuildInstantiatorTypeArguments(token_pos); |
| 1428 return PushArgument(instantiator_type_args); | 1428 return PushArgument(instantiator_type_args); |
| 1429 } | 1429 } |
| 1430 } | 1430 } |
| 1431 | 1431 |
| 1432 | 1432 |
| 1433 PushArgumentInstr* EffectGraphVisitor::PushFunctionTypeArguments( | 1433 PushArgumentInstr* EffectGraphVisitor::PushFunctionTypeArguments( |
| 1434 const AbstractType& type, | 1434 const AbstractType& type, |
| 1435 TokenPosition token_pos) { | 1435 TokenPosition token_pos) { |
| 1436 if (type.IsInstantiated(kCurrentFunction)) { | 1436 if (type.IsInstantiated(kFunctions)) { |
| 1437 return PushArgument(BuildNullValue(token_pos)); | 1437 return PushArgument(BuildNullValue(token_pos)); |
| 1438 } else { | 1438 } else { |
| 1439 Value* function_type_args = BuildFunctionTypeArguments(token_pos); | 1439 Value* function_type_args = BuildFunctionTypeArguments(token_pos); |
| 1440 return PushArgument(function_type_args); | 1440 return PushArgument(function_type_args); |
| 1441 } | 1441 } |
| 1442 } | 1442 } |
| 1443 | 1443 |
| 1444 | 1444 |
| 1445 Value* EffectGraphVisitor::BuildNullValue(TokenPosition token_pos) { | 1445 Value* EffectGraphVisitor::BuildNullValue(TokenPosition token_pos) { |
| 1446 return Bind( | 1446 return Bind( |
| 1447 new (Z) ConstantInstr(Object::ZoneHandle(Z, Object::null()), token_pos)); | 1447 new (Z) ConstantInstr(Object::ZoneHandle(Z, Object::null()), token_pos)); |
| 1448 } | 1448 } |
| 1449 | 1449 |
| 1450 | 1450 |
| 1451 Value* EffectGraphVisitor::BuildEmptyTypeArguments(TokenPosition token_pos) { |
| 1452 return Bind(new (Z) ConstantInstr( |
| 1453 TypeArguments::ZoneHandle(Z, Object::empty_type_arguments().raw()), |
| 1454 token_pos)); |
| 1455 } |
| 1456 |
| 1457 |
| 1451 // Used for testing incoming arguments. | 1458 // Used for testing incoming arguments. |
| 1452 AssertAssignableInstr* EffectGraphVisitor::BuildAssertAssignable( | 1459 AssertAssignableInstr* EffectGraphVisitor::BuildAssertAssignable( |
| 1453 TokenPosition token_pos, | 1460 TokenPosition token_pos, |
| 1454 Value* value, | 1461 Value* value, |
| 1455 const AbstractType& dst_type, | 1462 const AbstractType& dst_type, |
| 1456 const String& dst_name) { | 1463 const String& dst_name) { |
| 1457 // Build the type check computation. | 1464 // Build the type check computation. |
| 1458 Value* instantiator_type_arguments = NULL; | 1465 Value* instantiator_type_arguments = NULL; |
| 1459 Value* function_type_arguments = NULL; | 1466 Value* function_type_arguments = NULL; |
| 1460 if (dst_type.IsInstantiated(kCurrentClass)) { | 1467 if (dst_type.IsInstantiated(kCurrentClass)) { |
| 1461 instantiator_type_arguments = BuildNullValue(token_pos); | 1468 instantiator_type_arguments = BuildNullValue(token_pos); |
| 1462 } else { | 1469 } else { |
| 1463 instantiator_type_arguments = BuildInstantiatorTypeArguments(token_pos); | 1470 instantiator_type_arguments = BuildInstantiatorTypeArguments(token_pos); |
| 1464 } | 1471 } |
| 1465 if (dst_type.IsInstantiated(kCurrentFunction)) { | 1472 if (dst_type.IsInstantiated(kFunctions)) { |
| 1466 function_type_arguments = BuildNullValue(token_pos); | 1473 function_type_arguments = BuildNullValue(token_pos); |
| 1467 } else { | 1474 } else { |
| 1468 function_type_arguments = BuildFunctionTypeArguments(token_pos); | 1475 function_type_arguments = BuildFunctionTypeArguments(token_pos); |
| 1469 } | 1476 } |
| 1470 | 1477 |
| 1471 const intptr_t deopt_id = Thread::Current()->GetNextDeoptId(); | 1478 const intptr_t deopt_id = Thread::Current()->GetNextDeoptId(); |
| 1472 return new (Z) AssertAssignableInstr( | 1479 return new (Z) AssertAssignableInstr( |
| 1473 token_pos, value, instantiator_type_arguments, function_type_arguments, | 1480 token_pos, value, instantiator_type_arguments, function_type_arguments, |
| 1474 dst_type, dst_name, deopt_id); | 1481 dst_type, dst_name, deopt_id); |
| 1475 } | 1482 } |
| (...skipping 861 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2337 Class::ZoneHandle(Z, isolate()->object_store()->closure_class()); | 2344 Class::ZoneHandle(Z, isolate()->object_store()->closure_class()); |
| 2338 ZoneGrowableArray<PushArgumentInstr*>* no_arguments = | 2345 ZoneGrowableArray<PushArgumentInstr*>* no_arguments = |
| 2339 new (Z) ZoneGrowableArray<PushArgumentInstr*>(0); | 2346 new (Z) ZoneGrowableArray<PushArgumentInstr*>(0); |
| 2340 AllocateObjectInstr* alloc = new (Z) | 2347 AllocateObjectInstr* alloc = new (Z) |
| 2341 AllocateObjectInstr(node->token_pos(), closure_class, no_arguments); | 2348 AllocateObjectInstr(node->token_pos(), closure_class, no_arguments); |
| 2342 alloc->set_closure_function(function); | 2349 alloc->set_closure_function(function); |
| 2343 | 2350 |
| 2344 Value* closure_val = Bind(alloc); | 2351 Value* closure_val = Bind(alloc); |
| 2345 { | 2352 { |
| 2346 LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val); | 2353 LocalVariable* closure_tmp_var = EnterTempLocalScope(closure_val); |
| 2347 // Store instantiator type arguments if signature is uninstantiated. | 2354 // Store instantiator type arguments if signature is class-uninstantiated. |
| 2348 if (!function.HasInstantiatedSignature(kCurrentClass)) { | 2355 if (!function.HasInstantiatedSignature(kCurrentClass)) { |
| 2349 Value* closure_tmp_val = | 2356 Value* closure_tmp_val = |
| 2350 Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); | 2357 Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); |
| 2351 Value* type_arguments = BuildInstantiatorTypeArguments(node->token_pos()); | 2358 Value* type_arguments = BuildInstantiatorTypeArguments(node->token_pos()); |
| 2352 Do(new (Z) StoreInstanceFieldInstr(Closure::instantiator_offset(), | 2359 Do(new (Z) StoreInstanceFieldInstr( |
| 2353 closure_tmp_val, type_arguments, | 2360 Closure::instantiator_type_arguments_offset(), closure_tmp_val, |
| 2354 kEmitStoreBarrier, node->token_pos())); | 2361 type_arguments, kEmitStoreBarrier, node->token_pos())); |
| 2362 } |
| 2363 |
| 2364 // Store function type arguments if signature is function-uninstantiated. |
| 2365 if (!function.HasInstantiatedSignature(kFunctions)) { |
| 2366 Value* closure_tmp_val = |
| 2367 Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); |
| 2368 Value* type_arguments = BuildFunctionTypeArguments(node->token_pos()); |
| 2369 Do(new (Z) StoreInstanceFieldInstr( |
| 2370 Closure::function_type_arguments_offset(), closure_tmp_val, |
| 2371 type_arguments, kEmitStoreBarrier, node->token_pos())); |
| 2355 } | 2372 } |
| 2356 | 2373 |
| 2357 // Store function. | 2374 // Store function. |
| 2358 Value* closure_tmp_val = | 2375 Value* closure_tmp_val = |
| 2359 Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); | 2376 Bind(new (Z) LoadLocalInstr(*closure_tmp_var, node->token_pos())); |
| 2360 Value* func_val = | 2377 Value* func_val = |
| 2361 Bind(new (Z) ConstantInstr(Function::ZoneHandle(Z, function.raw()))); | 2378 Bind(new (Z) ConstantInstr(Function::ZoneHandle(Z, function.raw()))); |
| 2362 Do(new (Z) StoreInstanceFieldInstr(Closure::function_offset(), | 2379 Do(new (Z) StoreInstanceFieldInstr(Closure::function_offset(), |
| 2363 closure_tmp_val, func_val, | 2380 closure_tmp_val, func_val, |
| 2364 kEmitStoreBarrier, node->token_pos())); | 2381 kEmitStoreBarrier, node->token_pos())); |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2708 ASSERT(type_arguments_field_offset != Class::kNoTypeArguments); | 2725 ASSERT(type_arguments_field_offset != Class::kNoTypeArguments); |
| 2709 | 2726 |
| 2710 return Bind(new (Z) LoadFieldInstr( | 2727 return Bind(new (Z) LoadFieldInstr( |
| 2711 instantiator, type_arguments_field_offset, | 2728 instantiator, type_arguments_field_offset, |
| 2712 Type::ZoneHandle(Z, Type::null()), // Not an instance, no type. | 2729 Type::ZoneHandle(Z, Type::null()), // Not an instance, no type. |
| 2713 token_pos)); | 2730 token_pos)); |
| 2714 } | 2731 } |
| 2715 | 2732 |
| 2716 | 2733 |
| 2717 Value* EffectGraphVisitor::BuildFunctionTypeArguments(TokenPosition token_pos) { | 2734 Value* EffectGraphVisitor::BuildFunctionTypeArguments(TokenPosition token_pos) { |
| 2718 UNIMPLEMENTED(); | 2735 LocalVariable* function_type_arguments_var = |
| 2719 return NULL; | 2736 owner()->parsed_function().function_type_arguments(); |
| 2737 if (function_type_arguments_var == NULL) { |
| 2738 // We encountered an uninstantiated type referring to type parameters of a |
| 2739 // signature that is local to the function being compiled. The type remains |
| 2740 // uninstantiated. Example: Foo(f<T>(T t)) => null; |
| 2741 // Foo is non-generic, but takes a generic function f as argument. |
| 2742 // The uninstantiated function type of f cannot be instantiated from within |
| 2743 // Foo and should not be instantiated. It is used in uninstantiated form to |
| 2744 // check incoming closures for assignability. We pass an empty function |
| 2745 // type argument vector. |
| 2746 return BuildEmptyTypeArguments(token_pos); |
| 2747 |
| 2748 // Note that the function type could also get partially instantiated: |
| 2749 // Bar<B>(B g<T>(T t)) => null; |
| 2750 // In this case, function_type_arguments_var will not be null, since Bar |
| 2751 // is generic, and will be used to partially instantiate the type of g, more |
| 2752 // specifically the result type of g. Note that the instantiator vector will |
| 2753 // have length 1, and type parameters with indices above 0, e.g. T, must |
| 2754 // remain uninstantiated. |
| 2755 } |
| 2756 return Bind(BuildLoadLocal(*function_type_arguments_var, token_pos)); |
| 2720 } | 2757 } |
| 2721 | 2758 |
| 2722 | 2759 |
| 2723 Value* EffectGraphVisitor::BuildInstantiatedTypeArguments( | 2760 Value* EffectGraphVisitor::BuildInstantiatedTypeArguments( |
| 2724 TokenPosition token_pos, | 2761 TokenPosition token_pos, |
| 2725 const TypeArguments& type_arguments) { | 2762 const TypeArguments& type_arguments) { |
| 2726 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { | 2763 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { |
| 2727 return Bind(new (Z) ConstantInstr(type_arguments)); | 2764 return Bind(new (Z) ConstantInstr(type_arguments)); |
| 2728 } | 2765 } |
| 2729 // The type arguments are uninstantiated. | 2766 // The type arguments are uninstantiated. |
| 2730 const Class& instantiator_class = | 2767 const Class& instantiator_class = |
| 2731 Class::ZoneHandle(Z, owner()->function().Owner()); | 2768 Class::ZoneHandle(Z, owner()->function().Owner()); |
| 2732 Value* instantiator_type_args = BuildInstantiatorTypeArguments(token_pos); | 2769 Value* instantiator_type_args = NULL; |
| 2733 const bool use_instantiator_type_args = | 2770 if (type_arguments.IsInstantiated(kCurrentClass)) { |
| 2734 type_arguments.IsUninstantiatedIdentity() || | 2771 instantiator_type_args = BuildNullValue(token_pos); |
| 2735 type_arguments.CanShareInstantiatorTypeArguments(instantiator_class); | 2772 } else { |
| 2736 if (use_instantiator_type_args) { | 2773 instantiator_type_args = BuildInstantiatorTypeArguments(token_pos); |
| 2737 return instantiator_type_args; | 2774 const bool use_instantiator_type_args = |
| 2775 type_arguments.IsUninstantiatedIdentity() || |
| 2776 type_arguments.CanShareInstantiatorTypeArguments(instantiator_class); |
| 2777 if (use_instantiator_type_args) { |
| 2778 return instantiator_type_args; |
| 2779 } |
| 2738 } | 2780 } |
| 2739 Value* function_type_args = NULL; | 2781 Value* function_type_args = NULL; |
| 2740 if (type_arguments.IsInstantiated(kCurrentFunction)) { | 2782 if (type_arguments.IsInstantiated(kFunctions)) { |
| 2741 function_type_args = BuildNullValue(token_pos); | 2783 function_type_args = BuildNullValue(token_pos); |
| 2742 } else { | 2784 } else { |
| 2743 function_type_args = BuildFunctionTypeArguments(token_pos); | 2785 function_type_args = BuildFunctionTypeArguments(token_pos); |
| 2744 } | 2786 } |
| 2745 return Bind(new (Z) InstantiateTypeArgumentsInstr( | 2787 return Bind(new (Z) InstantiateTypeArgumentsInstr( |
| 2746 token_pos, type_arguments, instantiator_class, instantiator_type_args, | 2788 token_pos, type_arguments, instantiator_class, instantiator_type_args, |
| 2747 function_type_args)); | 2789 function_type_args)); |
| 2748 } | 2790 } |
| 2749 | 2791 |
| 2750 | 2792 |
| (...skipping 1600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4351 ASSERT(type.HasResolvedTypeClass()); | 4393 ASSERT(type.HasResolvedTypeClass()); |
| 4352 const Class& type_class = Class::Handle(type.type_class()); | 4394 const Class& type_class = Class::Handle(type.type_class()); |
| 4353 // Bail if the type has any type parameters. | 4395 // Bail if the type has any type parameters. |
| 4354 if (type_class.IsGeneric()) return false; | 4396 if (type_class.IsGeneric()) return false; |
| 4355 | 4397 |
| 4356 // Finally a simple class for instance of checking. | 4398 // Finally a simple class for instance of checking. |
| 4357 return true; | 4399 return true; |
| 4358 } | 4400 } |
| 4359 | 4401 |
| 4360 } // namespace dart | 4402 } // namespace dart |
| OLD | NEW |