| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 927 } | 927 } |
| 928 | 928 |
| 929 | 929 |
| 930 void CodeGenerator::VisitArrayNode(ArrayNode* node) { | 930 void CodeGenerator::VisitArrayNode(ArrayNode* node) { |
| 931 // Evaluate the array elements. | 931 // Evaluate the array elements. |
| 932 for (int i = 0; i < node->length(); i++) { | 932 for (int i = 0; i < node->length(); i++) { |
| 933 AstNode* element = node->ElementAt(i); | 933 AstNode* element = node->ElementAt(i); |
| 934 element->Visit(this); | 934 element->Visit(this); |
| 935 } | 935 } |
| 936 | 936 |
| 937 const AbstractTypeArguments& element_type = node->type_arguments(); |
| 938 const bool instantiate_type_arguments = true; |
| 939 GenerateTypeArguments(node->id(), |
| 940 node->token_index(), |
| 941 element_type, |
| 942 instantiate_type_arguments); |
| 943 __ popl(ECX); |
| 944 __ movl(EDX, Immediate(Smi::RawValue(node->length()))); |
| 945 |
| 937 // Allocate the array. | 946 // Allocate the array. |
| 938 // EDX : Array length as Smi. | 947 // EDX : Array length as Smi. |
| 939 // ECX : element type for the array. | 948 // ECX : element type for the array. |
| 940 __ movl(EDX, Immediate(Smi::RawValue(node->length()))); | |
| 941 const AbstractTypeArguments& element_type = node->type_arguments(); | |
| 942 ASSERT(element_type.IsNull() || element_type.IsInstantiated()); | |
| 943 __ LoadObject(ECX, element_type); | |
| 944 GenerateCall(node->token_index(), | 949 GenerateCall(node->token_index(), |
| 945 &StubCode::AllocateArrayLabel(), | 950 &StubCode::AllocateArrayLabel(), |
| 946 PcDescriptors::kOther); | 951 PcDescriptors::kOther); |
| 947 | 952 |
| 948 // Pop the element values from the stack into the array. | 953 // Pop the element values from the stack into the array. |
| 949 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); | 954 __ leal(ECX, FieldAddress(EAX, Array::data_offset())); |
| 950 for (int i = node->length() - 1; i >= 0; i--) { | 955 for (int i = node->length() - 1; i >= 0; i--) { |
| 951 __ popl(Address(ECX, i * kWordSize)); | 956 __ popl(Address(ECX, i * kWordSize)); |
| 952 } | 957 } |
| 953 | 958 |
| (...skipping 1434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2388 intptr_t type_arguments_instance_field_offset = | 2393 intptr_t type_arguments_instance_field_offset = |
| 2389 instantiator_class.type_arguments_instance_field_offset(); | 2394 instantiator_class.type_arguments_instance_field_offset(); |
| 2390 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); | 2395 ASSERT(type_arguments_instance_field_offset != Class::kNoTypeArguments); |
| 2391 __ movl(EBX, FieldAddress(EBX, type_arguments_instance_field_offset)); | 2396 __ movl(EBX, FieldAddress(EBX, type_arguments_instance_field_offset)); |
| 2392 __ pushl(EBX); | 2397 __ pushl(EBX); |
| 2393 } | 2398 } |
| 2394 } | 2399 } |
| 2395 } | 2400 } |
| 2396 | 2401 |
| 2397 | 2402 |
| 2398 // Pushes the type arguments on the stack in preparation of a constructor or | 2403 // Pushes the type arguments on the stack in preparation of an allocation call. |
| 2399 // factory call. | 2404 // If instantiate_type_arguments is true, the instantiated type arguments |
| 2400 // For a factory call, instantiates (possibly requiring an additional run time | 2405 // are pushed on the stack (after an instantiation run time call, if necessary). |
| 2401 // call) and pushes the type argument vector that will be passed as implicit | 2406 // If instantiate_type_arguments is false, the (possibly uninstantiated) type |
| 2402 // first parameter to the factory. | 2407 // arguments are pushed on the stack, as well as the type arguments of the |
| 2403 // For a constructor call allocating an object of a parameterized class, pushes | 2408 // instantiator (or the special kNoInstantiator Smi marker, if the type |
| 2404 // the type arguments and the type arguments of the instantiator, without ever | 2409 // arguments are instantiated). |
| 2405 // generating an additional run time call. | 2410 void CodeGenerator::GenerateTypeArguments( |
| 2406 // Does nothing for a constructor call allocating an object of a non | 2411 intptr_t node_id, |
| 2407 // parameterized class. | 2412 intptr_t token_index, |
| 2408 // Note that a class without proper type parameters may still be parameterized, | 2413 const AbstractTypeArguments& type_arguments, |
| 2409 // e.g. class A extends Array<int>. | 2414 bool instantiate_type_arguments) { |
| 2410 void CodeGenerator::GenerateTypeArguments(ConstructorCallNode* node, | |
| 2411 bool requires_type_arguments) { | |
| 2412 const Immediate raw_null = | 2415 const Immediate raw_null = |
| 2413 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2416 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 2414 // Instantiate the type arguments if necessary. | 2417 if (type_arguments.IsNull() || type_arguments.IsInstantiated()) { |
| 2415 if (node->type_arguments().IsNull() || | 2418 // The type arguments are instantiated. |
| 2416 node->type_arguments().IsInstantiated()) { | 2419 __ PushObject(type_arguments); |
| 2417 if (requires_type_arguments) { | 2420 if (!instantiate_type_arguments) { |
| 2418 // A factory requires the type arguments as first parameter. | 2421 // The type arguments of the instantiator are not needed, since the |
| 2419 __ PushObject(node->type_arguments()); | 2422 // type arguments are instantiated. |
| 2420 if (!node->constructor().IsFactory()) { | 2423 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2421 // The non-factory allocator additionally requires the instantiator | |
| 2422 // type arguments which are not needed here, since the type arguments | |
| 2423 // are instantiated. | |
| 2424 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | |
| 2425 } | |
| 2426 } | 2424 } |
| 2427 } else { | 2425 } else { |
| 2428 // The type arguments are uninstantiated. | 2426 // The type arguments are uninstantiated. |
| 2429 ASSERT(requires_type_arguments); | 2427 GenerateInstantiatorTypeArguments(token_index); |
| 2430 GenerateInstantiatorTypeArguments(node->token_index()); | |
| 2431 __ popl(EAX); // Pop instantiator. | 2428 __ popl(EAX); // Pop instantiator. |
| 2432 // EAX is the instantiator AbstractTypeArguments object (or null). | 2429 // EAX is the instantiator AbstractTypeArguments object (or null). |
| 2433 // If the instantiator is null and if the type argument vector | 2430 // If the instantiator is null and if the type argument vector |
| 2434 // instantiated from null becomes a vector of Dynamic, then use null as | 2431 // instantiated from null becomes a vector of Dynamic, then use null as |
| 2435 // the type arguments. | 2432 // the type arguments. |
| 2436 Label type_arguments_instantiated; | 2433 Label type_arguments_instantiated; |
| 2437 const intptr_t len = node->type_arguments().Length(); | 2434 const intptr_t len = type_arguments.Length(); |
| 2438 if (node->type_arguments().IsRawInstantiatedRaw(len)) { | 2435 if (type_arguments.IsRawInstantiatedRaw(len)) { |
| 2439 __ cmpl(EAX, raw_null); | 2436 __ cmpl(EAX, raw_null); |
| 2440 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2437 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2441 } | 2438 } |
| 2442 // Instantiate non-null type arguments. | 2439 // Instantiate non-null type arguments. |
| 2443 if (node->type_arguments().IsUninstantiatedIdentity()) { | 2440 if (type_arguments.IsUninstantiatedIdentity()) { |
| 2444 // Check if the instantiator type argument vector is a TypeArguments of a | 2441 // Check if the instantiator type argument vector is a TypeArguments of a |
| 2445 // matching length and, if so, use it as the instantiated type_arguments. | 2442 // matching length and, if so, use it as the instantiated type_arguments. |
| 2446 // No need to check RAX for null (again), because a null instance will | 2443 // No need to check RAX for null (again), because a null instance will |
| 2447 // have the wrong class (Null instead of TypeArguments). | 2444 // have the wrong class (Null instead of TypeArguments). |
| 2448 Label type_arguments_uninstantiated; | 2445 Label type_arguments_uninstantiated; |
| 2449 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class())); | 2446 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class())); |
| 2450 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset())); | 2447 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 2451 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 2448 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 2452 Immediate arguments_length = | |
| 2453 Immediate(Smi::RawValue(node->type_arguments().Length())); | |
| 2454 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), | 2449 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), |
| 2455 arguments_length); | 2450 Immediate(Smi::RawValue(len))); |
| 2456 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2451 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2457 __ Bind(&type_arguments_uninstantiated); | 2452 __ Bind(&type_arguments_uninstantiated); |
| 2458 } | 2453 } |
| 2459 if (node->constructor().IsFactory()) { | 2454 if (instantiate_type_arguments) { |
| 2460 // A runtime call to instantiate the type arguments is required before | 2455 // A runtime call to instantiate the type arguments is required. |
| 2461 // calling the factory. | |
| 2462 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 2456 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 2463 __ PushObject(node->type_arguments()); | 2457 __ PushObject(type_arguments); |
| 2464 __ pushl(EAX); // Push instantiator type arguments. | 2458 __ pushl(EAX); // Push instantiator type arguments. |
| 2465 GenerateCallRuntime(node->id(), | 2459 GenerateCallRuntime(node_id, |
| 2466 node->token_index(), | 2460 token_index, |
| 2467 kInstantiateTypeArgumentsRuntimeEntry); | 2461 kInstantiateTypeArgumentsRuntimeEntry); |
| 2468 __ popl(EAX); // Pop instantiator type arguments. | 2462 __ popl(EAX); // Pop instantiator type arguments. |
| 2469 __ popl(EAX); // Pop uninstantiated type arguments. | 2463 __ popl(EAX); // Pop uninstantiated type arguments. |
| 2470 __ popl(EAX); // Pop instantiated type arguments. | 2464 __ popl(EAX); // Pop instantiated type arguments. |
| 2471 __ Bind(&type_arguments_instantiated); | 2465 __ Bind(&type_arguments_instantiated); |
| 2472 __ pushl(EAX); // Instantiated type arguments. | 2466 __ pushl(EAX); // Instantiated type arguments. |
| 2473 } else { | 2467 } else { |
| 2474 // In the non-factory case, we rely on the allocation stub to | 2468 // The allocation stub will instantiate the type arguments. |
| 2475 // instantiate the type arguments. | 2469 __ PushObject(type_arguments); |
| 2476 __ PushObject(node->type_arguments()); | |
| 2477 __ pushl(EAX); // Instantiator type arguments. | 2470 __ pushl(EAX); // Instantiator type arguments. |
| 2478 Label type_arguments_pushed; | 2471 Label type_arguments_pushed; |
| 2479 __ jmp(&type_arguments_pushed, Assembler::kNearJump); | 2472 __ jmp(&type_arguments_pushed, Assembler::kNearJump); |
| 2480 | 2473 |
| 2481 __ Bind(&type_arguments_instantiated); | 2474 __ Bind(&type_arguments_instantiated); |
| 2482 __ pushl(EAX); // Instantiated type arguments. | 2475 __ pushl(EAX); // Instantiated type arguments. |
| 2483 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 2476 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2484 __ Bind(&type_arguments_pushed); | 2477 __ Bind(&type_arguments_pushed); |
| 2485 } | 2478 } |
| 2486 } | 2479 } |
| 2487 } | 2480 } |
| 2488 | 2481 |
| 2489 | 2482 |
| 2490 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { | 2483 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { |
| 2491 if (node->constructor().IsFactory()) { | 2484 if (node->constructor().IsFactory()) { |
| 2492 const bool requires_type_arguments = true; // Always first arg to factory. | 2485 const bool instantiate_type_arguments = true; // First argument to factory. |
| 2493 GenerateTypeArguments(node, requires_type_arguments); | 2486 GenerateTypeArguments(node->id(), |
| 2487 node->token_index(), |
| 2488 node->type_arguments(), |
| 2489 instantiate_type_arguments); |
| 2494 // The top of stack is an instantiated AbstractTypeArguments object | 2490 // The top of stack is an instantiated AbstractTypeArguments object |
| 2495 // (or null). | 2491 // (or null). |
| 2496 int num_args = node->arguments()->length() + 1; // +1 to include type args. | 2492 int num_args = node->arguments()->length() + 1; // +1 to include type args. |
| 2497 node->arguments()->Visit(this); | 2493 node->arguments()->Visit(this); |
| 2498 // Call the factory. | 2494 // Call the factory. |
| 2499 __ LoadObject(ECX, node->constructor()); | 2495 __ LoadObject(ECX, node->constructor()); |
| 2500 __ LoadObject(EDX, ArgumentsDescriptor(num_args, | 2496 __ LoadObject(EDX, ArgumentsDescriptor(num_args, |
| 2501 node->arguments()->names())); | 2497 node->arguments()->names())); |
| 2502 GenerateCall(node->token_index(), | 2498 GenerateCall(node->token_index(), |
| 2503 &StubCode::CallStaticFunctionLabel(), | 2499 &StubCode::CallStaticFunctionLabel(), |
| 2504 PcDescriptors::kFuncCall); | 2500 PcDescriptors::kFuncCall); |
| 2505 // Factory constructor returns object in EAX. | 2501 // Factory constructor returns object in EAX. |
| 2506 __ addl(ESP, Immediate(num_args * kWordSize)); | 2502 __ addl(ESP, Immediate(num_args * kWordSize)); |
| 2507 if (IsResultNeeded(node)) { | 2503 if (IsResultNeeded(node)) { |
| 2508 __ pushl(EAX); | 2504 __ pushl(EAX); |
| 2509 } | 2505 } |
| 2510 return; | 2506 return; |
| 2511 } | 2507 } |
| 2512 | 2508 |
| 2513 const Class& cls = Class::ZoneHandle(node->constructor().owner()); | 2509 const Class& cls = Class::ZoneHandle(node->constructor().owner()); |
| 2514 const bool requires_type_arguments = cls.HasTypeArguments(); | 2510 const bool requires_type_arguments = cls.HasTypeArguments(); |
| 2515 GenerateTypeArguments(node, requires_type_arguments); | 2511 const bool instantiate_type_arguments = false; // Done in stub or runtime. |
| 2512 if (requires_type_arguments) { |
| 2513 GenerateTypeArguments(node->id(), |
| 2514 node->token_index(), |
| 2515 node->type_arguments(), |
| 2516 instantiate_type_arguments); |
| 2517 } |
| 2516 | 2518 |
| 2517 // If cls is parameterized, the type arguments and the instantiator's | 2519 // If cls is parameterized, the type arguments and the instantiator's |
| 2518 // type arguments are on the stack. | 2520 // type arguments are on the stack. |
| 2519 // In checked mode, if the type arguments are uninstantiated, they may need to | 2521 // In checked mode, if the type arguments are uninstantiated, they may need to |
| 2520 // be checked against declared bounds at run time. | 2522 // be checked against declared bounds at run time. |
| 2521 Error& malformed_error = Error::Handle(); | 2523 Error& malformed_error = Error::Handle(); |
| 2522 if (FLAG_enable_type_checks && | 2524 if (FLAG_enable_type_checks && |
| 2523 requires_type_arguments && | 2525 requires_type_arguments && |
| 2524 !node->type_arguments().IsNull() && | 2526 !node->type_arguments().IsNull() && |
| 2525 !node->type_arguments().IsInstantiated() && | 2527 !node->type_arguments().IsInstantiated() && |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2903 const Error& error = Error::Handle( | 2905 const Error& error = Error::Handle( |
| 2904 Parser::FormatError(script, token_index, "Error", format, args)); | 2906 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2905 va_end(args); | 2907 va_end(args); |
| 2906 Isolate::Current()->long_jump_base()->Jump(1, error); | 2908 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2907 UNREACHABLE(); | 2909 UNREACHABLE(); |
| 2908 } | 2910 } |
| 2909 | 2911 |
| 2910 } // namespace dart | 2912 } // namespace dart |
| 2911 | 2913 |
| 2912 #endif // defined TARGET_ARCH_IA32 | 2914 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |