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

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

Issue 8347008: Address review comments of previously submitted cl 8329005. (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
« no previous file with comments | « runtime/vm/code_generator.cc ('k') | runtime/vm/object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 837 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 node->scope()->PreserveOuterScope(current_context_level)); 848 node->scope()->PreserveOuterScope(current_context_level));
849 ASSERT(!function.HasCode()); 849 ASSERT(!function.HasCode());
850 ASSERT(function.context_scope() == ContextScope::null()); 850 ASSERT(function.context_scope() == ContextScope::null());
851 function.set_context_scope(context_scope); 851 function.set_context_scope(context_scope);
852 } else { 852 } else {
853 ASSERT(function.context_scope() != ContextScope::null()); 853 ASSERT(function.context_scope() != ContextScope::null());
854 if (function.IsImplicitInstanceClosureFunction()) { 854 if (function.IsImplicitInstanceClosureFunction()) {
855 node->receiver()->Visit(this); 855 node->receiver()->Visit(this);
856 } 856 }
857 } 857 }
858 // The function type of a closure may be parameterized. In that case, pass 858 // The function type of a closure may have type arguments. In that case, pass
859 // the type arguments of the instantiator. 859 // the type arguments of the instantiator.
860 const Class& cls = Class::Handle(function.signature_class()); 860 const Class& cls = Class::Handle(function.signature_class());
861 ASSERT(!cls.IsNull()); 861 ASSERT(!cls.IsNull());
862 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; 862 const bool requires_type_arguments = cls.HasTypeArguments();
863 if (is_cls_parameterized) { 863 if (requires_type_arguments) {
864 ASSERT(!function.IsImplicitStaticClosureFunction()); 864 ASSERT(!function.IsImplicitStaticClosureFunction());
865 GenerateInstantiatorTypeArguments(); 865 GenerateInstantiatorTypeArguments();
866 } 866 }
867 const Code& stub = Code::Handle( 867 const Code& stub = Code::Handle(
868 StubCode::GetAllocationStubForClosure(function)); 868 StubCode::GetAllocationStubForClosure(function));
869 const ExternalLabel label(function.ToCString(), stub.EntryPoint()); 869 const ExternalLabel label(function.ToCString(), stub.EntryPoint());
870 GenerateCall(node->token_index(), &label); 870 GenerateCall(node->token_index(), &label);
871 if (is_cls_parameterized) { 871 if (requires_type_arguments) {
872 __ popl(ECX); // Pop type arguments. 872 __ popl(ECX); // Pop type arguments.
873 } 873 }
874 if (function.IsImplicitInstanceClosureFunction()) { 874 if (function.IsImplicitInstanceClosureFunction()) {
875 __ popl(ECX); // Pop receiver. 875 __ popl(ECX); // Pop receiver.
876 } 876 }
877 if (IsResultNeeded(node)) { 877 if (IsResultNeeded(node)) {
878 __ pushl(EAX); 878 __ pushl(EAX);
879 } 879 }
880 } 880 }
881 881
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
1372 __ cmpl(EAX, raw_null); 1372 __ cmpl(EAX, raw_null);
1373 __ j(NOT_EQUAL, &non_null, Assembler::kNearJump); 1373 __ j(NOT_EQUAL, &non_null, Assembler::kNearJump);
1374 __ PushObject(negate_result ? bool_true : bool_false); 1374 __ PushObject(negate_result ? bool_true : bool_false);
1375 __ jmp(&done, Assembler::kNearJump); 1375 __ jmp(&done, Assembler::kNearJump);
1376 1376
1377 __ Bind(&non_null); 1377 __ Bind(&non_null);
1378 // If type is instantiated and non-parameterized, we can inline code 1378 // If type is instantiated and non-parameterized, we can inline code
1379 // checking whether the tested instance is a Smi. 1379 // checking whether the tested instance is a Smi.
1380 if (type.IsInstantiated()) { 1380 if (type.IsInstantiated()) {
1381 const Class& type_class = Class::ZoneHandle(type.type_class()); 1381 const Class& type_class = Class::ZoneHandle(type.type_class());
1382 const bool is_type_class_parameterized = type_class.NumTypeArguments() > 0; 1382 const bool requires_type_arguments = type_class.HasTypeArguments();
1383 // A Smi object cannot be the instance of a parameterized class. 1383 // A Smi object cannot be the instance of a parameterized class.
1384 // A class equality check is only applicable to a non-parameterized class. 1384 // A class equality check is only applicable to a non-parameterized class.
1385 // TODO(regis): Should we still inline a Smi type check when checking for a 1385 // TODO(regis): Should we still inline a Smi type check when checking for a
1386 // parameterized type and return false for a Smi's without calling the 1386 // parameterized type and return false for a Smi's without calling the
1387 // runtime? 1387 // runtime?
1388 if (!is_type_class_parameterized) { 1388 if (!requires_type_arguments) {
1389 Label compare_classes; 1389 Label compare_classes;
1390 __ testl(EAX, Immediate(kSmiTagMask)); 1390 __ testl(EAX, Immediate(kSmiTagMask));
1391 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1391 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1392 // Object is Smi. 1392 // Object is Smi.
1393 const Class& smi_class = Class::Handle(Smi::Class()); 1393 const Class& smi_class = Class::Handle(Smi::Class());
1394 // TODO(regis): We should introduce a SmiType. 1394 // TODO(regis): We should introduce a SmiType.
1395 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1395 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1396 type_class, 1396 type_class,
1397 TypeArguments::Handle())) { 1397 TypeArguments::Handle())) {
1398 __ PushObject(negate_result ? bool_false : bool_true); 1398 __ PushObject(negate_result ? bool_false : bool_true);
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1491 const Immediate raw_null = 1491 const Immediate raw_null =
1492 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1492 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1493 Label done, runtime_call; 1493 Label done, runtime_call;
1494 __ cmpl(EAX, raw_null); 1494 __ cmpl(EAX, raw_null);
1495 __ j(EQUAL, &done, Assembler::kNearJump); 1495 __ j(EQUAL, &done, Assembler::kNearJump);
1496 1496
1497 // If dst_type is instantiated and non-parameterized, we can inline code 1497 // If dst_type is instantiated and non-parameterized, we can inline code
1498 // checking whether the assigned instance is a Smi. 1498 // checking whether the assigned instance is a Smi.
1499 if (dst_type.IsInstantiated()) { 1499 if (dst_type.IsInstantiated()) {
1500 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); 1500 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class());
1501 const bool is_dst_type_parameterized = 1501 const bool dst_has_type_arguments = dst_type_class.HasTypeArguments();
1502 dst_type_class.NumTypeArguments() > 0;
1503 // A Smi object cannot be the instance of a parameterized class. 1502 // A Smi object cannot be the instance of a parameterized class.
1504 // A class equality check is only applicable to a non-parameterized class. 1503 // A class equality check is only applicable to a non-parameterized class.
1505 if (!is_dst_type_parameterized) { 1504 if (!dst_has_type_arguments) {
1506 Label compare_classes; 1505 Label compare_classes;
1507 __ testl(EAX, Immediate(kSmiTagMask)); 1506 __ testl(EAX, Immediate(kSmiTagMask));
1508 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1507 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1509 // Object is Smi. 1508 // Object is Smi.
1510 const Class& smi_class = Class::Handle(Smi::Class()); 1509 const Class& smi_class = Class::Handle(Smi::Class());
1511 // TODO(regis): We should introduce a SmiType. 1510 // TODO(regis): We should introduce a SmiType.
1512 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1511 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1513 dst_type_class, 1512 dst_type_class,
1514 TypeArguments::Handle())) { 1513 TypeArguments::Handle())) {
1515 // Successful assignable type check: return object in EAX. 1514 // Successful assignable type check: return object in EAX.
(...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after
2188 // call) and pushes the type argument vector that will be passed as implicit 2187 // call) and pushes the type argument vector that will be passed as implicit
2189 // first parameter to the factory. 2188 // first parameter to the factory.
2190 // For a constructor call allocating an object of a parameterized class, pushes 2189 // For a constructor call allocating an object of a parameterized class, pushes
2191 // the type arguments and the type arguments of the instantiator, without ever 2190 // the type arguments and the type arguments of the instantiator, without ever
2192 // generating an additional run time call. 2191 // generating an additional run time call.
2193 // Does nothing for a constructor call allocating an object of a non 2192 // Does nothing for a constructor call allocating an object of a non
2194 // parameterized class. 2193 // parameterized class.
2195 // Note that a class without proper type parameters may still be parameterized, 2194 // Note that a class without proper type parameters may still be parameterized,
2196 // e.g. class A extends Array<int>. 2195 // e.g. class A extends Array<int>.
2197 void CodeGenerator::GenerateTypeArguments(ConstructorCallNode* node, 2196 void CodeGenerator::GenerateTypeArguments(ConstructorCallNode* node,
2198 bool is_cls_parameterized) { 2197 bool requires_type_arguments) {
2199 const Immediate raw_null = 2198 const Immediate raw_null =
2200 Immediate(reinterpret_cast<intptr_t>(Object::null())); 2199 Immediate(reinterpret_cast<intptr_t>(Object::null()));
2201 // Instantiate the type arguments if necessary. 2200 // Instantiate the type arguments if necessary.
2202 if (node->type_arguments().IsNull() || 2201 if (node->type_arguments().IsNull() ||
2203 node->type_arguments().IsInstantiated()) { 2202 node->type_arguments().IsInstantiated()) {
2204 if (node->constructor().IsFactory() || is_cls_parameterized) { 2203 if (node->constructor().IsFactory() || requires_type_arguments) {
2205 // A factory requires the type arguments as first parameter. 2204 // A factory requires the type arguments as first parameter.
2206 __ PushObject(node->type_arguments()); 2205 __ PushObject(node->type_arguments());
2207 if (!node->constructor().IsFactory()) { 2206 if (!node->constructor().IsFactory()) {
2208 // The allocator additionally requires the instantiator type arguments. 2207 // The allocator additionally requires the instantiator type arguments.
2209 __ pushl(raw_null); // Null instantiator. 2208 __ pushl(raw_null); // Null instantiator.
2210 } 2209 }
2211 } 2210 }
2212 } else { 2211 } else {
2213 // The type arguments are uninstantiated. 2212 // The type arguments are uninstantiated.
2214 ASSERT(node->constructor().IsFactory() || is_cls_parameterized); 2213 ASSERT(node->constructor().IsFactory() || requires_type_arguments);
2215 GenerateInstantiatorTypeArguments(); 2214 GenerateInstantiatorTypeArguments();
2216 __ popl(EAX); // Pop instantiator. 2215 __ popl(EAX); // Pop instantiator.
2217 // EAX is the instantiator TypeArguments object (or null). 2216 // EAX is the instantiator TypeArguments object (or null).
2218 // If EAX is null, no need to instantiate the type arguments, use null, and 2217 // If EAX is null, no need to instantiate the type arguments, use null, and
2219 // allocate an object of a raw type. 2218 // allocate an object of a raw type.
2220 Label type_arguments_instantiated, type_arguments_uninstantiated; 2219 Label type_arguments_instantiated, type_arguments_uninstantiated;
2221 __ cmpl(EAX, raw_null); 2220 __ cmpl(EAX, raw_null);
2222 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 2221 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
2223 2222
2224 // Instantiate non-null type arguments. 2223 // Instantiate non-null type arguments.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2260 __ pushl(EAX); // Instantiated type arguments. 2259 __ pushl(EAX); // Instantiated type arguments.
2261 __ pushl(raw_null); // Null instantiator. 2260 __ pushl(raw_null); // Null instantiator.
2262 __ Bind(&type_arguments_pushed); 2261 __ Bind(&type_arguments_pushed);
2263 } 2262 }
2264 } 2263 }
2265 } 2264 }
2266 2265
2267 2266
2268 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { 2267 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) {
2269 const Class& cls = Class::ZoneHandle(node->constructor().owner()); 2268 const Class& cls = Class::ZoneHandle(node->constructor().owner());
2270 const bool is_cls_parameterized = cls.NumTypeArguments() > 0; 2269 const bool requires_type_arguments = cls.HasTypeArguments();
2271 GenerateTypeArguments(node, is_cls_parameterized); 2270 GenerateTypeArguments(node, requires_type_arguments);
2272 if (node->constructor().IsFactory()) { 2271 if (node->constructor().IsFactory()) {
2273 // The top of stack is an instantiated TypeArguments object (or null). 2272 // The top of stack is an instantiated TypeArguments object (or null).
2274 int num_args = node->arguments()->length() + 1; // +1 to include type args. 2273 int num_args = node->arguments()->length() + 1; // +1 to include type args.
2275 node->arguments()->Visit(this); 2274 node->arguments()->Visit(this);
2276 // Call the factory. 2275 // Call the factory.
2277 __ LoadObject(ECX, node->constructor()); 2276 __ LoadObject(ECX, node->constructor());
2278 __ LoadObject(EDX, ArgumentsDescriptor(num_args, 2277 __ LoadObject(EDX, ArgumentsDescriptor(num_args,
2279 node->arguments()->names())); 2278 node->arguments()->names()));
2280 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); 2279 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel());
2281 // Factory constructor returns object in EAX. 2280 // Factory constructor returns object in EAX.
2282 __ addl(ESP, Immediate(num_args * kWordSize)); 2281 __ addl(ESP, Immediate(num_args * kWordSize));
2283 if (IsResultNeeded(node)) { 2282 if (IsResultNeeded(node)) {
2284 __ pushl(EAX); 2283 __ pushl(EAX);
2285 } 2284 }
2286 return; 2285 return;
2287 } 2286 }
2288 2287
2289 // If cls is parameterized, the type arguments and the instantiator's 2288 // If cls is parameterized, the type arguments and the instantiator's
2290 // type arguments are on the stack. 2289 // type arguments are on the stack.
2291 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); 2290 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
2292 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); 2291 const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
2293 GenerateCall(node->token_index(), &label); 2292 GenerateCall(node->token_index(), &label);
2294 if (is_cls_parameterized) { 2293 if (requires_type_arguments) {
2295 __ popl(ECX); // Pop type arguments. 2294 __ popl(ECX); // Pop type arguments.
2296 __ popl(ECX); // Pop instantiator type arguments. 2295 __ popl(ECX); // Pop instantiator type arguments.
2297 } 2296 }
2298 2297
2299 if (IsResultNeeded(node)) { 2298 if (IsResultNeeded(node)) {
2300 __ pushl(EAX); // Set up return value from allocate. 2299 __ pushl(EAX); // Set up return value from allocate.
2301 } 2300 }
2302 __ pushl(EAX); // First argument(this) for constructor call which follows. 2301 __ pushl(EAX); // First argument(this) for constructor call which follows.
2303 2302
2304 // Now setup rest of the arguments for the constructor call. 2303 // Now setup rest of the arguments for the constructor call.
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
2622 const Class& cls = Class::Handle(parsed_function_.function().owner()); 2621 const Class& cls = Class::Handle(parsed_function_.function().owner());
2623 const Script& script = Script::Handle(cls.script()); 2622 const Script& script = Script::Handle(cls.script());
2624 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); 2623 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args);
2625 Isolate::Current()->long_jump_base()->Jump(1, error_msg); 2624 Isolate::Current()->long_jump_base()->Jump(1, error_msg);
2626 UNREACHABLE(); 2625 UNREACHABLE();
2627 } 2626 }
2628 2627
2629 } // namespace dart 2628 } // namespace dart
2630 2629
2631 #endif // defined TARGET_ARCH_IA32 2630 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/code_generator.cc ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698