Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(876)

Side by Side Diff: runtime/vm/code_generator_ia32.cc

Issue 8271008: Set type argument vector at run time in instantiated closure objects. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698