| 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 2237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2248 __ popl(CTX); | 2248 __ popl(CTX); |
| 2249 // Result is in EAX. | 2249 // Result is in EAX. |
| 2250 if (IsResultNeeded(node)) { | 2250 if (IsResultNeeded(node)) { |
| 2251 __ pushl(EAX); | 2251 __ pushl(EAX); |
| 2252 } | 2252 } |
| 2253 } | 2253 } |
| 2254 | 2254 |
| 2255 | 2255 |
| 2256 // Pushes the type arguments of the instantiator on the stack. | 2256 // Pushes the type arguments of the instantiator on the stack. |
| 2257 void CodeGenerator::GenerateInstantiatorTypeArguments(intptr_t token_index) { | 2257 void CodeGenerator::GenerateInstantiatorTypeArguments(intptr_t token_index) { |
| 2258 const Class& instantiator_class = | 2258 Class& instantiator_class = Class::Handle(); |
| 2259 Class::Handle(parsed_function().function().owner()); | 2259 Function& outer_function = |
| 2260 Function::Handle(parsed_function().function().raw()); |
| 2261 while (outer_function.IsLocalFunction()) { |
| 2262 outer_function = outer_function.parent_function(); |
| 2263 } |
| 2264 if (outer_function.IsFactory()) { |
| 2265 instantiator_class = outer_function.signature_class(); |
| 2266 } else { |
| 2267 instantiator_class = outer_function.owner(); |
| 2268 } |
| 2260 if (instantiator_class.NumTypeParameters() == 0) { | 2269 if (instantiator_class.NumTypeParameters() == 0) { |
| 2261 // The type arguments are compile time constants. | 2270 // The type arguments are compile time constants. |
| 2262 TypeArguments& type_arguments = TypeArguments::ZoneHandle(); | 2271 TypeArguments& type_arguments = TypeArguments::ZoneHandle(); |
| 2272 // TODO(regis): Temporary type should be allocated in new gen heap. |
| 2263 Type& type = Type::Handle( | 2273 Type& type = Type::Handle( |
| 2264 Type::NewParameterizedType(instantiator_class, type_arguments)); | 2274 Type::NewParameterizedType(instantiator_class, type_arguments)); |
| 2265 String& errmsg = String::Handle(); | 2275 String& errmsg = String::Handle(); |
| 2266 type = ClassFinalizer::FinalizeAndCanonicalizeType(type, &errmsg); | 2276 type = ClassFinalizer::FinalizeAndCanonicalizeType(type, &errmsg); |
| 2267 if (!errmsg.IsNull()) { | 2277 if (!errmsg.IsNull()) { |
| 2268 ErrorMsg(token_index, errmsg.ToCString()); | 2278 ErrorMsg(token_index, errmsg.ToCString()); |
| 2269 } | 2279 } |
| 2270 type_arguments = type.arguments(); | 2280 type_arguments = type.arguments(); |
| 2271 __ PushObject(type_arguments); | 2281 __ PushObject(type_arguments); |
| 2272 } else { | 2282 } else { |
| 2273 ASSERT(parsed_function().instantiator() != NULL); | 2283 ASSERT(parsed_function().instantiator() != NULL); |
| 2274 parsed_function().instantiator()->Visit(this); | 2284 parsed_function().instantiator()->Visit(this); |
| 2275 if (!parsed_function().function().IsInFactoryScope()) { | 2285 if (!outer_function.IsFactory()) { |
| 2276 __ popl(EAX); // Pop instantiator. | 2286 __ popl(EAX); // Pop instantiator. |
| 2277 // The instantiator is the receiver of the caller, which is not a factory. | 2287 // The instantiator is the receiver of the caller, which is not a factory. |
| 2278 // The receiver cannot be null; extract its TypeArguments object. | 2288 // The receiver cannot be null; extract its TypeArguments object. |
| 2279 // Note that in the factory case, the instantiator is the first parameter | 2289 // Note that in the factory case, the instantiator is the first parameter |
| 2280 // of the factory, i.e. already a TypeArguments object. | 2290 // of the factory, i.e. already a TypeArguments object. |
| 2281 intptr_t type_arguments_instance_field_offset = | 2291 intptr_t type_arguments_instance_field_offset = |
| 2282 instantiator_class.type_arguments_instance_field_offset(); | 2292 instantiator_class.type_arguments_instance_field_offset(); |
| 2283 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); | 2293 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); |
| 2284 __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); | 2294 __ movl(EAX, FieldAddress(EAX, type_arguments_instance_field_offset)); |
| 2285 __ pushl(EAX); | 2295 __ pushl(EAX); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 2300 // parameterized class. | 2310 // parameterized class. |
| 2301 // Note that a class without proper type parameters may still be parameterized, | 2311 // Note that a class without proper type parameters may still be parameterized, |
| 2302 // e.g. class A extends Array<int>. | 2312 // e.g. class A extends Array<int>. |
| 2303 void CodeGenerator::GenerateTypeArguments(ConstructorCallNode* node, | 2313 void CodeGenerator::GenerateTypeArguments(ConstructorCallNode* node, |
| 2304 bool requires_type_arguments) { | 2314 bool requires_type_arguments) { |
| 2305 const Immediate raw_null = | 2315 const Immediate raw_null = |
| 2306 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2316 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 2307 // Instantiate the type arguments if necessary. | 2317 // Instantiate the type arguments if necessary. |
| 2308 if (node->type_arguments().IsNull() || | 2318 if (node->type_arguments().IsNull() || |
| 2309 node->type_arguments().IsInstantiated()) { | 2319 node->type_arguments().IsInstantiated()) { |
| 2310 if (node->constructor().IsFactory() || requires_type_arguments) { | 2320 if (requires_type_arguments) { |
| 2311 // A factory requires the type arguments as first parameter. | 2321 // A factory requires the type arguments as first parameter. |
| 2312 __ PushObject(node->type_arguments()); | 2322 __ PushObject(node->type_arguments()); |
| 2313 if (!node->constructor().IsFactory()) { | 2323 if (!node->constructor().IsFactory()) { |
| 2314 // The allocator additionally requires the instantiator type arguments. | 2324 // The allocator additionally requires the instantiator type arguments. |
| 2315 __ pushl(raw_null); // Null instantiator. | 2325 __ pushl(raw_null); // Null instantiator. |
| 2316 } | 2326 } |
| 2317 } | 2327 } |
| 2318 } else { | 2328 } else { |
| 2319 // The type arguments are uninstantiated. | 2329 // The type arguments are uninstantiated. |
| 2320 ASSERT(node->constructor().IsFactory() || requires_type_arguments); | 2330 ASSERT(requires_type_arguments); |
| 2321 GenerateInstantiatorTypeArguments(node->token_index()); | 2331 GenerateInstantiatorTypeArguments(node->token_index()); |
| 2322 __ popl(EAX); // Pop instantiator. | 2332 __ popl(EAX); // Pop instantiator. |
| 2323 // EAX is the instantiator TypeArguments object (or null). | 2333 // EAX is the instantiator TypeArguments object (or null). |
| 2324 // If EAX is null, no need to instantiate the type arguments, use null, and | 2334 // If EAX is null, no need to instantiate the type arguments, use null, and |
| 2325 // allocate an object of a raw type. | 2335 // allocate an object of a raw type. |
| 2326 Label type_arguments_instantiated, type_arguments_uninstantiated; | 2336 Label type_arguments_instantiated, type_arguments_uninstantiated; |
| 2327 __ cmpl(EAX, raw_null); | 2337 __ cmpl(EAX, raw_null); |
| 2328 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2338 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2329 | 2339 |
| 2330 // Instantiate non-null type arguments. | 2340 // Instantiate non-null type arguments. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2366 __ Bind(&type_arguments_instantiated); | 2376 __ Bind(&type_arguments_instantiated); |
| 2367 __ pushl(EAX); // Instantiated type arguments. | 2377 __ pushl(EAX); // Instantiated type arguments. |
| 2368 __ pushl(raw_null); // Null instantiator. | 2378 __ pushl(raw_null); // Null instantiator. |
| 2369 __ Bind(&type_arguments_pushed); | 2379 __ Bind(&type_arguments_pushed); |
| 2370 } | 2380 } |
| 2371 } | 2381 } |
| 2372 } | 2382 } |
| 2373 | 2383 |
| 2374 | 2384 |
| 2375 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { | 2385 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { |
| 2376 const Class& cls = Class::ZoneHandle(node->constructor().owner()); | |
| 2377 const bool requires_type_arguments = cls.HasTypeArguments(); | |
| 2378 GenerateTypeArguments(node, requires_type_arguments); | |
| 2379 if (node->constructor().IsFactory()) { | 2386 if (node->constructor().IsFactory()) { |
| 2387 const bool requires_type_arguments = true; // Always first arg to factory. |
| 2388 GenerateTypeArguments(node, requires_type_arguments); |
| 2380 // The top of stack is an instantiated TypeArguments object (or null). | 2389 // The top of stack is an instantiated TypeArguments object (or null). |
| 2381 int num_args = node->arguments()->length() + 1; // +1 to include type args. | 2390 int num_args = node->arguments()->length() + 1; // +1 to include type args. |
| 2382 node->arguments()->Visit(this); | 2391 node->arguments()->Visit(this); |
| 2383 // Call the factory. | 2392 // Call the factory. |
| 2384 __ LoadObject(ECX, node->constructor()); | 2393 __ LoadObject(ECX, node->constructor()); |
| 2385 __ LoadObject(EDX, ArgumentsDescriptor(num_args, | 2394 __ LoadObject(EDX, ArgumentsDescriptor(num_args, |
| 2386 node->arguments()->names())); | 2395 node->arguments()->names())); |
| 2387 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); | 2396 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); |
| 2388 // Factory constructor returns object in EAX. | 2397 // Factory constructor returns object in EAX. |
| 2389 __ addl(ESP, Immediate(num_args * kWordSize)); | 2398 __ addl(ESP, Immediate(num_args * kWordSize)); |
| 2390 if (IsResultNeeded(node)) { | 2399 if (IsResultNeeded(node)) { |
| 2391 __ pushl(EAX); | 2400 __ pushl(EAX); |
| 2392 } | 2401 } |
| 2393 return; | 2402 return; |
| 2394 } | 2403 } |
| 2395 | 2404 |
| 2405 const Class& cls = Class::ZoneHandle(node->constructor().owner()); |
| 2406 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 2407 GenerateTypeArguments(node, requires_type_arguments); |
| 2408 |
| 2396 // If cls is parameterized, the type arguments and the instantiator's | 2409 // If cls is parameterized, the type arguments and the instantiator's |
| 2397 // type arguments are on the stack. | 2410 // type arguments are on the stack. |
| 2398 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); | 2411 const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| 2399 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); | 2412 const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| 2400 GenerateCall(node->token_index(), &label); | 2413 GenerateCall(node->token_index(), &label); |
| 2401 if (requires_type_arguments) { | 2414 if (requires_type_arguments) { |
| 2402 __ popl(ECX); // Pop type arguments. | 2415 __ popl(ECX); // Pop type arguments. |
| 2403 __ popl(ECX); // Pop instantiator type arguments. | 2416 __ popl(ECX); // Pop instantiator type arguments. |
| 2404 } | 2417 } |
| 2405 | 2418 |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2737 const Class& cls = Class::Handle(parsed_function_.function().owner()); | 2750 const Class& cls = Class::Handle(parsed_function_.function().owner()); |
| 2738 const Script& script = Script::Handle(cls.script()); | 2751 const Script& script = Script::Handle(cls.script()); |
| 2739 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); | 2752 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); |
| 2740 Isolate::Current()->long_jump_base()->Jump(1, error_msg); | 2753 Isolate::Current()->long_jump_base()->Jump(1, error_msg); |
| 2741 UNREACHABLE(); | 2754 UNREACHABLE(); |
| 2742 } | 2755 } |
| 2743 | 2756 |
| 2744 } // namespace dart | 2757 } // namespace dart |
| 2745 | 2758 |
| 2746 #endif // defined TARGET_ARCH_IA32 | 2759 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |