Chromium Code Reviews| 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 |