OLD | NEW |
---|---|
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/globals.h" // Needed here to get TARGET_ARCH_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/code_generator.h" | 8 #include "vm/code_generator.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
847 | 847 |
848 void CodeGenerator::VisitClosureNode(ClosureNode* node) { | 848 void CodeGenerator::VisitClosureNode(ClosureNode* node) { |
849 const int current_context_level = state()->context_level(); | 849 const int current_context_level = state()->context_level(); |
850 const ContextScope& context_scope = ContextScope::ZoneHandle( | 850 const ContextScope& context_scope = ContextScope::ZoneHandle( |
851 node->scope()->PreserveOuterScope(current_context_level)); | 851 node->scope()->PreserveOuterScope(current_context_level)); |
852 const Function& function = node->function(); | 852 const Function& function = node->function(); |
853 ASSERT(function.IsNonImplicitClosureFunction()); | 853 ASSERT(function.IsNonImplicitClosureFunction()); |
854 ASSERT(!function.HasCode()); | 854 ASSERT(!function.HasCode()); |
855 ASSERT(function.context_scope() == ContextScope::null()); | 855 ASSERT(function.context_scope() == ContextScope::null()); |
856 function.set_context_scope(context_scope); | 856 function.set_context_scope(context_scope); |
857 // The function type of a closure may be parameterized. In that case, pass | |
858 // the type arguments of the instantiator. | |
859 const Class& cls = Class::Handle(function.signature_class()); | |
860 ASSERT(!cls.IsNull()); | |
861 const bool is_cls_parameterized = cls.IsParameterized(); | |
862 if (is_cls_parameterized) { | |
863 GenerateInstantiatorTypeArguments(); | |
864 } | |
857 const Code& stub = Code::Handle( | 865 const Code& stub = Code::Handle( |
858 StubCode::GetAllocationStubForClosure(function)); | 866 StubCode::GetAllocationStubForClosure(function)); |
859 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); | 867 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
860 GenerateCall(node->token_index(), &label); | 868 GenerateCall(node->token_index(), &label); |
869 if (is_cls_parameterized) { | |
870 __ popl(ECX); // Pop type arguments. | |
871 } | |
861 if (IsResultNeeded(node)) { | 872 if (IsResultNeeded(node)) { |
862 __ pushl(EAX); | 873 __ pushl(EAX); |
863 } | 874 } |
864 } | 875 } |
865 | 876 |
866 | 877 |
867 void CodeGenerator::VisitImplicitStaticClosureNode( | 878 void CodeGenerator::VisitImplicitStaticClosureNode( |
868 ImplicitStaticClosureNode* node) { | 879 ImplicitStaticClosureNode* node) { |
869 const Function& function = node->function(); | 880 const Function& function = node->function(); |
870 ASSERT(function.IsImplicitStaticClosureFunction()); | 881 ASSERT(function.IsImplicitStaticClosureFunction()); |
871 ASSERT(function.context_scope() != ContextScope::null()); | 882 ASSERT(function.context_scope() != ContextScope::null()); |
872 const Code& stub = Code::Handle( | 883 const Code& stub = Code::Handle( |
873 StubCode::GetAllocationStubForClosure(function)); | 884 StubCode::GetAllocationStubForClosure(function)); |
874 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); | 885 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
875 GenerateCall(node->token_index(), &label); | 886 GenerateCall(node->token_index(), &label); |
876 if (IsResultNeeded(node)) { | 887 if (IsResultNeeded(node)) { |
877 __ pushl(EAX); | 888 __ pushl(EAX); |
878 } | 889 } |
879 } | 890 } |
880 | 891 |
881 | 892 |
882 void CodeGenerator::VisitImplicitInstanceClosureNode( | 893 void CodeGenerator::VisitImplicitInstanceClosureNode( |
883 ImplicitInstanceClosureNode* node) { | 894 ImplicitInstanceClosureNode* node) { |
884 const Function& function = node->function(); | 895 const Function& function = node->function(); |
885 ASSERT(function.IsImplicitInstanceClosureFunction()); | 896 ASSERT(function.IsImplicitInstanceClosureFunction()); |
886 ASSERT(function.context_scope() != ContextScope::null()); | 897 ASSERT(function.context_scope() != ContextScope::null()); |
887 node->receiver()->Visit(this); | 898 node->receiver()->Visit(this); |
899 // The function type of a closure may be parameterized. In that case, pass | |
900 // the type arguments of the instantiator. | |
901 const Class& cls = Class::Handle(function.signature_class()); | |
902 ASSERT(!cls.IsNull()); | |
903 const bool is_cls_parameterized = cls.IsParameterized(); | |
904 if (is_cls_parameterized) { | |
905 GenerateInstantiatorTypeArguments(); | |
906 } | |
888 const Code& stub = Code::Handle( | 907 const Code& stub = Code::Handle( |
889 StubCode::GetAllocationStubForClosure(function)); | 908 StubCode::GetAllocationStubForClosure(function)); |
890 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); | 909 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); |
891 GenerateCall(node->token_index(), &label); | 910 GenerateCall(node->token_index(), &label); |
911 if (is_cls_parameterized) { | |
912 __ popl(ECX); // Pop type arguments. | |
913 } | |
892 __ popl(ECX); // Pop receiver. | 914 __ popl(ECX); // Pop receiver. |
siva
2011/10/13 20:52:21
The code for VisitClosureNode and VisitImplicitIns
regis
2011/10/13 21:33:46
I tried to factorize the visiting code of all 3 cl
| |
893 if (IsResultNeeded(node)) { | 915 if (IsResultNeeded(node)) { |
894 __ pushl(EAX); | 916 __ pushl(EAX); |
895 } | 917 } |
896 } | 918 } |
897 | 919 |
898 | 920 |
899 void CodeGenerator::VisitPrimaryNode(PrimaryNode* node) { | 921 void CodeGenerator::VisitPrimaryNode(PrimaryNode* node) { |
900 // PrimaryNodes are temporary during parsing. | 922 // PrimaryNodes are temporary during parsing. |
901 ErrorMsg(node->token_index(), | 923 ErrorMsg(node->token_index(), |
902 "Unexpected primary node: %s", node->primary().ToCString()); | 924 "Unexpected primary node: %s", node->primary().ToCString()); |
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1429 __ jmp(&done, Assembler::kNearJump); | 1451 __ jmp(&done, Assembler::kNearJump); |
1430 __ Bind(&runtime_call); | 1452 __ Bind(&runtime_call); |
1431 } | 1453 } |
1432 } | 1454 } |
1433 } | 1455 } |
1434 const Object& result = Object::ZoneHandle(); | 1456 const Object& result = Object::ZoneHandle(); |
1435 __ PushObject(result); // Make room for the result of the runtime call. | 1457 __ PushObject(result); // Make room for the result of the runtime call. |
1436 __ pushl(EAX); // Push the instance. | 1458 __ pushl(EAX); // Push the instance. |
1437 __ PushObject(type); // Push the type. | 1459 __ PushObject(type); // Push the type. |
1438 if (!type.IsInstantiated()) { | 1460 if (!type.IsInstantiated()) { |
1439 ASSERT(parsed_function().instantiator() != NULL); | 1461 GenerateInstantiatorTypeArguments(); |
1440 parsed_function().instantiator()->Visit(this); // Instantiator on stack. | |
1441 if (!parsed_function().function().IsInFactoryScope()) { | |
1442 __ popl(EAX); // Pop instantiator. | |
1443 const Class& instantiator_class = | |
1444 Class::Handle(parsed_function().function().owner()); | |
1445 // The instantiator is the receiver of the caller, which is not a factory. | |
1446 // The receiver cannot be null; extract its TypeArguments object. | |
1447 // Note that in the factory case, the instantiator is the first parameter | |
1448 // of the factory, i.e. already a TypeArguments object. | |
1449 intptr_t type_arguments_instance_field_offset = | |
1450 instantiator_class.type_arguments_instance_field_offset(); | |
1451 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); | |
1452 __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); | |
1453 __ pushl(EAX); // Push instantiator. | |
1454 } | |
1455 } else { | 1462 } else { |
1456 __ PushObject(TypeArguments::ZoneHandle()); // Null instantiator. | 1463 __ PushObject(TypeArguments::ZoneHandle()); // Null instantiator. |
1457 } | 1464 } |
1458 GenerateCallRuntime(token_index, kInstanceofRuntimeEntry); | 1465 GenerateCallRuntime(token_index, kInstanceofRuntimeEntry); |
1459 // Pop the two parameters supplied to the runtime entry. The result of the | 1466 // Pop the two parameters supplied to the runtime entry. The result of the |
1460 // instanceof runtime call will be left as the result of the operation. | 1467 // instanceof runtime call will be left as the result of the operation. |
1461 __ addl(ESP, Immediate(3 * kWordSize)); | 1468 __ addl(ESP, Immediate(3 * kWordSize)); |
1462 if (negate_result) { | 1469 if (negate_result) { |
1463 Label negate_done; | 1470 Label negate_done; |
1464 __ popl(EDX); | 1471 __ popl(EDX); |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1601 } | 1608 } |
1602 __ Bind(&runtime_call); | 1609 __ Bind(&runtime_call); |
1603 const Object& result = Object::ZoneHandle(); | 1610 const Object& result = Object::ZoneHandle(); |
1604 __ PushObject(result); // Make room for the result of the runtime call. | 1611 __ PushObject(result); // Make room for the result of the runtime call. |
1605 const Immediate location = | 1612 const Immediate location = |
1606 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); | 1613 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); |
1607 __ pushl(location); // Push the source location. | 1614 __ pushl(location); // Push the source location. |
1608 __ pushl(EAX); // Push the source object. | 1615 __ pushl(EAX); // Push the source object. |
1609 __ PushObject(dst_type); // Push the type of the destination. | 1616 __ PushObject(dst_type); // Push the type of the destination. |
1610 if (!dst_type.IsInstantiated()) { | 1617 if (!dst_type.IsInstantiated()) { |
1611 ASSERT(parsed_function().instantiator() != NULL); | 1618 GenerateInstantiatorTypeArguments(); |
1612 parsed_function().instantiator()->Visit(this); // Instantiator on stack. | |
1613 if (!parsed_function().function().IsInFactoryScope()) { | |
1614 __ popl(EAX); // Pop instantiator. | |
1615 const Class& instantiator_class = | |
1616 Class::Handle(parsed_function().function().owner()); | |
1617 // The instantiator is the receiver of the caller, which is not a factory. | |
1618 // The receiver cannot be null; extract its TypeArguments object. | |
1619 // Note that in the factory case, the instantiator is the first parameter | |
1620 // of the factory, i.e. already a TypeArguments object. | |
1621 intptr_t type_arguments_instance_field_offset = | |
1622 instantiator_class.type_arguments_instance_field_offset(); | |
1623 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); | |
1624 __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); | |
1625 __ pushl(EAX); // Push instantiator. | |
1626 } | |
1627 } else { | 1619 } else { |
1628 __ PushObject(TypeArguments::ZoneHandle()); // Null instantiator. | 1620 __ PushObject(TypeArguments::ZoneHandle()); // Null instantiator. |
1629 } | 1621 } |
1630 __ PushObject(dst_name); // Push the name of the destination. | 1622 __ PushObject(dst_name); // Push the name of the destination. |
1631 GenerateCallRuntime(token_index, kTypeCheckRuntimeEntry); | 1623 GenerateCallRuntime(token_index, kTypeCheckRuntimeEntry); |
1632 // Pop the parameters supplied to the runtime entry. The result of the | 1624 // Pop the parameters supplied to the runtime entry. The result of the |
1633 // type check runtime call is the checked value. | 1625 // type check runtime call is the checked value. |
1634 __ addl(ESP, Immediate(5 * kWordSize)); | 1626 __ addl(ESP, Immediate(5 * kWordSize)); |
1635 __ popl(EAX); | 1627 __ popl(EAX); |
1636 | 1628 |
(...skipping 561 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2198 __ addl(ESP, Immediate((node->arguments()->length() + 1) * kWordSize)); | 2190 __ addl(ESP, Immediate((node->arguments()->length() + 1) * kWordSize)); |
2199 // Restore the context. | 2191 // Restore the context. |
2200 __ popl(CTX); | 2192 __ popl(CTX); |
2201 // Result is in EAX. | 2193 // Result is in EAX. |
2202 if (IsResultNeeded(node)) { | 2194 if (IsResultNeeded(node)) { |
2203 __ pushl(EAX); | 2195 __ pushl(EAX); |
2204 } | 2196 } |
2205 } | 2197 } |
2206 | 2198 |
2207 | 2199 |
2200 // Pushes the type arguments of the instantiator on the stack. | |
2201 void CodeGenerator::GenerateInstantiatorTypeArguments() { | |
2202 ASSERT(parsed_function().instantiator() != NULL); | |
2203 parsed_function().instantiator()->Visit(this); | |
2204 if (!parsed_function().function().IsInFactoryScope()) { | |
2205 __ popl(EAX); // Pop instantiator. | |
2206 const Class& instantiator_class = | |
2207 Class::Handle(parsed_function().function().owner()); | |
2208 // The instantiator is the receiver of the caller, which is not a factory. | |
2209 // The receiver cannot be null; extract its TypeArguments object. | |
2210 // Note that in the factory case, the instantiator is the first parameter | |
2211 // of the factory, i.e. already a TypeArguments object. | |
2212 intptr_t type_arguments_instance_field_offset = | |
2213 instantiator_class.type_arguments_instance_field_offset(); | |
2214 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); | |
2215 __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); | |
2216 __ pushl(EAX); | |
2217 } | |
2218 } | |
2219 | |
2220 | |
2208 // Pushes the type arguments on the stack in preparation of a constructor or | 2221 // Pushes the type arguments on the stack in preparation of a constructor or |
2209 // factory call. | 2222 // factory call. |
2210 // For a factory call, instantiates (possibly requiring an additional run time | 2223 // For a factory call, instantiates (possibly requiring an additional run time |
2211 // call) and pushes the type argument vector that will be passed as implicit | 2224 // call) and pushes the type argument vector that will be passed as implicit |
2212 // first parameter to the factory. | 2225 // first parameter to the factory. |
2213 // For a constructor call allocating an object of a parameterized class, pushes | 2226 // For a constructor call allocating an object of a parameterized class, pushes |
2214 // the type arguments and the type arguments of the instantiator, without ever | 2227 // the type arguments and the type arguments of the instantiator, without ever |
2215 // generating an additional run time call. | 2228 // generating an additional run time call. |
2216 // Does nothing for a constructor call allocating an object of a non | 2229 // Does nothing for a constructor call allocating an object of a non |
2217 // parameterized class. | 2230 // parameterized class. |
2218 // Note that a class without proper type parameters may still be parameterized, | 2231 // Note that a class without proper type parameters may still be parameterized, |
2219 // e.g. class A extends Array<int>. | 2232 // e.g. class A extends Array<int>. |
2220 void CodeGenerator::GenerateTypeArguments(ConstructorCallNode* node, | 2233 void CodeGenerator::GenerateTypeArguments(ConstructorCallNode* node, |
2221 bool is_cls_parameterized) { | 2234 bool is_cls_parameterized) { |
2222 // Instantiate the type arguments if necessary. | 2235 // Instantiate the type arguments if necessary. |
2223 if (node->type_arguments().IsNull() || | 2236 if (node->type_arguments().IsNull() || |
2224 node->type_arguments().IsInstantiated()) { | 2237 node->type_arguments().IsInstantiated()) { |
2225 if (node->constructor().IsFactory() || is_cls_parameterized) { | 2238 if (node->constructor().IsFactory() || is_cls_parameterized) { |
2226 // A factory requires the type arguments as first parameter. | 2239 // A factory requires the type arguments as first parameter. |
2227 __ PushObject(node->type_arguments()); | 2240 __ PushObject(node->type_arguments()); |
2228 if (!node->constructor().IsFactory()) { | 2241 if (!node->constructor().IsFactory()) { |
2229 // The allocator additionally requires the instantiator type arguments. | 2242 // The allocator additionally requires the instantiator type arguments. |
2230 __ PushObject(TypeArguments::ZoneHandle()); // Null instantiator. | 2243 __ PushObject(TypeArguments::ZoneHandle()); // Null instantiator. |
2231 } | 2244 } |
2232 } | 2245 } |
2233 } else { | 2246 } else { |
2234 // The type arguments are uninstantiated. | 2247 // The type arguments are uninstantiated. |
2235 ASSERT(parsed_function().instantiator() != NULL); | |
2236 ASSERT(node->constructor().IsFactory() || is_cls_parameterized); | 2248 ASSERT(node->constructor().IsFactory() || is_cls_parameterized); |
2237 parsed_function().instantiator()->Visit(this); | 2249 GenerateInstantiatorTypeArguments(); |
2238 __ popl(EAX); // Pop instantiator. | 2250 __ popl(EAX); |
siva
2011/10/13 20:52:21
// Pop instantiator.
regis
2011/10/13 21:33:46
Done.
| |
2239 if (!parsed_function().function().IsInFactoryScope()) { | |
2240 const Class& instantiator_class = | |
2241 Class::Handle(parsed_function().function().owner()); | |
2242 // The instantiator is the receiver of the caller, which is not a factory. | |
2243 // The receiver cannot be null; extract its TypeArguments object. | |
2244 // Note that in the factory case, the instantiator is the first parameter | |
2245 // of the factory, i.e. already a TypeArguments object. | |
2246 intptr_t type_arguments_instance_field_offset = | |
2247 instantiator_class.type_arguments_instance_field_offset(); | |
2248 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); | |
2249 __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); | |
2250 } | |
2251 // EAX is the instantiator TypeArguments object (or null). | 2251 // EAX is the instantiator TypeArguments object (or null). |
2252 // If EAX is null, no need to instantiate the type arguments, use null, and | 2252 // If EAX is null, no need to instantiate the type arguments, use null, and |
2253 // allocate an object of a raw type. | 2253 // allocate an object of a raw type. |
2254 Label type_arguments_instantiated, type_arguments_uninstantiated; | 2254 Label type_arguments_instantiated, type_arguments_uninstantiated; |
2255 const Immediate raw_null = | 2255 const Immediate raw_null = |
2256 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2256 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
2257 __ cmpl(EAX, raw_null); | 2257 __ cmpl(EAX, raw_null); |
2258 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2258 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
2259 | 2259 |
2260 // Instantiate non-null type arguments. | 2260 // Instantiate non-null type arguments. |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2658 const Class& cls = Class::Handle(parsed_function_.function().owner()); | 2658 const Class& cls = Class::Handle(parsed_function_.function().owner()); |
2659 const Script& script = Script::Handle(cls.script()); | 2659 const Script& script = Script::Handle(cls.script()); |
2660 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); | 2660 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); |
2661 Isolate::Current()->long_jump_base()->Jump(1, error_msg); | 2661 Isolate::Current()->long_jump_base()->Jump(1, error_msg); |
2662 UNREACHABLE(); | 2662 UNREACHABLE(); |
2663 } | 2663 } |
2664 | 2664 |
2665 } // namespace dart | 2665 } // namespace dart |
2666 | 2666 |
2667 #endif // defined TARGET_ARCH_IA32 | 2667 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |