| 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 756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 } | 767 } |
| 768 } else { | 768 } else { |
| 769 // Pop the previously evaluated result value into EAX. | 769 // Pop the previously evaluated result value into EAX. |
| 770 __ popl(EAX); | 770 __ popl(EAX); |
| 771 } | 771 } |
| 772 | 772 |
| 773 // Generate type check. | 773 // Generate type check. |
| 774 if (FLAG_enable_type_checks) { | 774 if (FLAG_enable_type_checks) { |
| 775 const bool returns_null = node->value()->IsLiteralNode() && | 775 const bool returns_null = node->value()->IsLiteralNode() && |
| 776 node->value()->AsLiteralNode()->literal().IsNull(); | 776 node->value()->AsLiteralNode()->literal().IsNull(); |
| 777 const RawFunction::Kind kind = parsed_function().function().kind(); | 777 const RawFunction::Kind kind = parsed_function().function().kind(); |
| 778 // Implicit getters do not need a type check at return. | 778 // Implicit getters do not need a type check at return. |
| 779 if (!returns_null && | 779 if (!returns_null && |
| 780 (kind != RawFunction::kImplicitGetter) && | 780 (kind != RawFunction::kImplicitGetter) && |
| 781 (kind != RawFunction::kConstImplicitGetter)) { | 781 (kind != RawFunction::kConstImplicitGetter)) { |
| 782 GenerateAssertAssignable( | 782 GenerateAssertAssignable( |
| 783 node->id(), | 783 node->id(), |
| 784 node->value()->token_index(), | 784 node->value()->token_index(), |
| 785 AbstractType::ZoneHandle(parsed_function().function().result_type()), | 785 AbstractType::ZoneHandle(parsed_function().function().result_type()), |
| 786 String::ZoneHandle(String::NewSymbol("function result"))); | 786 String::ZoneHandle(String::NewSymbol("function result"))); |
| 787 } | 787 } |
| (...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1381 | 1381 |
| 1382 const Class& type_class = Class::ZoneHandle(type.type_class()); | 1382 const Class& type_class = Class::ZoneHandle(type.type_class()); |
| 1383 const bool requires_type_arguments = type_class.HasTypeArguments(); | 1383 const bool requires_type_arguments = type_class.HasTypeArguments(); |
| 1384 // A Smi object cannot be the instance of a parameterized class. | 1384 // A Smi object cannot be the instance of a parameterized class. |
| 1385 // A class equality check is only applicable with a dst type of a | 1385 // A class equality check is only applicable with a dst type of a |
| 1386 // non-parameterized class or with a raw dst type of a parameterized class. | 1386 // non-parameterized class or with a raw dst type of a parameterized class. |
| 1387 if (requires_type_arguments) { | 1387 if (requires_type_arguments) { |
| 1388 const AbstractTypeArguments& type_arguments = | 1388 const AbstractTypeArguments& type_arguments = |
| 1389 AbstractTypeArguments::Handle(type.arguments()); | 1389 AbstractTypeArguments::Handle(type.arguments()); |
| 1390 const bool is_raw_type = type_arguments.IsNull() || | 1390 const bool is_raw_type = type_arguments.IsNull() || |
| 1391 type_arguments.IsDynamicTypes(type_arguments.Length()); | 1391 type_arguments.IsRaw(type_arguments.Length()); |
| 1392 Label runtime_call; | 1392 Label runtime_call; |
| 1393 __ testl(EAX, Immediate(kSmiTagMask)); | 1393 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1394 __ j(ZERO, &runtime_call, Assembler::kNearJump); | 1394 __ j(ZERO, &runtime_call, Assembler::kNearJump); |
| 1395 // Object not Smi. | 1395 // Object not Smi. |
| 1396 if (is_raw_type) { | 1396 if (is_raw_type) { |
| 1397 if (type.IsListInterface()) { | 1397 if (type.IsListInterface()) { |
| 1398 Label push_result; | 1398 Label push_result; |
| 1399 // TODO(srdjan) also accept List<Object>. | 1399 // TODO(srdjan) also accept List<Object>. |
| 1400 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1400 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1401 __ CompareObject(ECX, *CoreClass("ObjectArray")); | 1401 __ CompareObject(ECX, *CoreClass("ObjectArray")); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1562 if (dst_type.IsInstantiated()) { | 1562 if (dst_type.IsInstantiated()) { |
| 1563 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); | 1563 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); |
| 1564 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments(); | 1564 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments(); |
| 1565 // A Smi object cannot be the instance of a parameterized class. | 1565 // A Smi object cannot be the instance of a parameterized class. |
| 1566 // A class equality check is only applicable with a dst type of a | 1566 // A class equality check is only applicable with a dst type of a |
| 1567 // non-parameterized class or with a raw dst type of a parameterized class. | 1567 // non-parameterized class or with a raw dst type of a parameterized class. |
| 1568 if (dst_class_has_type_arguments) { | 1568 if (dst_class_has_type_arguments) { |
| 1569 const AbstractTypeArguments& dst_type_arguments = | 1569 const AbstractTypeArguments& dst_type_arguments = |
| 1570 AbstractTypeArguments::Handle(dst_type.arguments()); | 1570 AbstractTypeArguments::Handle(dst_type.arguments()); |
| 1571 const bool is_raw_dst_type = dst_type_arguments.IsNull() || | 1571 const bool is_raw_dst_type = dst_type_arguments.IsNull() || |
| 1572 dst_type_arguments.IsDynamicTypes(dst_type_arguments.Length()); | 1572 dst_type_arguments.IsRaw(dst_type_arguments.Length()); |
| 1573 if (is_raw_dst_type) { | 1573 if (is_raw_dst_type) { |
| 1574 // Dynamic type argument, check only classes. | 1574 // Dynamic type argument, check only classes. |
| 1575 if (dst_type.IsListInterface()) { | 1575 if (dst_type.IsListInterface()) { |
| 1576 // TODO(srdjan) also accept List<Object>. | 1576 // TODO(srdjan) also accept List<Object>. |
| 1577 __ testl(EAX, Immediate(kSmiTagMask)); | 1577 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1578 __ j(ZERO, &runtime_call, Assembler::kNearJump); | 1578 __ j(ZERO, &runtime_call, Assembler::kNearJump); |
| 1579 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1579 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1580 TestClassAndJump(*CoreClass("ObjectArray"), &done); | 1580 TestClassAndJump(*CoreClass("ObjectArray"), &done); |
| 1581 TestClassAndJump(*CoreClass("GrowableObjectArray"), &done); | 1581 TestClassAndJump(*CoreClass("GrowableObjectArray"), &done); |
| 1582 } else if (!dst_type_class.is_interface()) { | 1582 } else if (!dst_type_class.is_interface()) { |
| (...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2384 bool requires_type_arguments) { | 2384 bool requires_type_arguments) { |
| 2385 const Immediate raw_null = | 2385 const Immediate raw_null = |
| 2386 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2386 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 2387 // Instantiate the type arguments if necessary. | 2387 // Instantiate the type arguments if necessary. |
| 2388 if (node->type_arguments().IsNull() || | 2388 if (node->type_arguments().IsNull() || |
| 2389 node->type_arguments().IsInstantiated()) { | 2389 node->type_arguments().IsInstantiated()) { |
| 2390 if (requires_type_arguments) { | 2390 if (requires_type_arguments) { |
| 2391 // A factory requires the type arguments as first parameter. | 2391 // A factory requires the type arguments as first parameter. |
| 2392 __ PushObject(node->type_arguments()); | 2392 __ PushObject(node->type_arguments()); |
| 2393 if (!node->constructor().IsFactory()) { | 2393 if (!node->constructor().IsFactory()) { |
| 2394 // The allocator additionally requires the instantiator type arguments. | 2394 // The non-factory allocator additionally requires the instantiator |
| 2395 __ pushl(raw_null); // Null instantiator. | 2395 // type arguments which are not needed here, since the type arguments |
| 2396 // are instantiated. |
| 2397 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2396 } | 2398 } |
| 2397 } | 2399 } |
| 2398 } else { | 2400 } else { |
| 2399 // The type arguments are uninstantiated. | 2401 // The type arguments are uninstantiated. |
| 2400 ASSERT(requires_type_arguments); | 2402 ASSERT(requires_type_arguments); |
| 2401 GenerateInstantiatorTypeArguments(node->token_index()); | 2403 GenerateInstantiatorTypeArguments(node->token_index()); |
| 2402 __ popl(EAX); // Pop instantiator. | 2404 __ popl(EAX); // Pop instantiator. |
| 2403 // EAX is the instantiator AbstractTypeArguments object (or null). | 2405 // EAX is the instantiator AbstractTypeArguments object (or null). |
| 2404 // If EAX is null, no need to instantiate the type arguments, use null, and | 2406 // If the instantiator is null and if the type argument vector |
| 2405 // allocate an object of a raw type. | 2407 // instantiated from null becomes a vector of Dynamic, then use null as |
| 2406 Label type_arguments_instantiated, type_arguments_uninstantiated; | 2408 // the type arguments. |
| 2407 __ cmpl(EAX, raw_null); | 2409 Label type_arguments_instantiated; |
| 2408 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2410 const intptr_t len = node->type_arguments().Length(); |
| 2409 | 2411 if (node->type_arguments().IsRawInstantiatedRaw(len)) { |
| 2412 __ cmpl(EAX, raw_null); |
| 2413 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2414 } |
| 2410 // Instantiate non-null type arguments. | 2415 // Instantiate non-null type arguments. |
| 2411 if (node->type_arguments().IsUninstantiatedIdentity()) { | 2416 if (node->type_arguments().IsUninstantiatedIdentity()) { |
| 2412 // Check if the instantiator type argument vector is a TypeArguments of a | 2417 // Check if the instantiator type argument vector is a TypeArguments of a |
| 2413 // matching length and, if so, use it as the instantiated type_arguments. | 2418 // matching length and, if so, use it as the instantiated type_arguments. |
| 2419 // No need to check RAX for null (again), because a null instance will |
| 2420 // have the wrong class (Null instead of TypeArguments). |
| 2421 Label type_arguments_uninstantiated; |
| 2414 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class())); | 2422 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class())); |
| 2415 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset())); | 2423 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 2416 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 2424 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 2417 Immediate arguments_length = Immediate(reinterpret_cast<int32_t>( | 2425 Immediate arguments_length = Immediate(reinterpret_cast<int32_t>( |
| 2418 Smi::New(node->type_arguments().Length()))); | 2426 Smi::New(node->type_arguments().Length()))); |
| 2419 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), | 2427 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), |
| 2420 arguments_length); | 2428 arguments_length); |
| 2421 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2429 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2430 __ Bind(&type_arguments_uninstantiated); |
| 2422 } | 2431 } |
| 2423 __ Bind(&type_arguments_uninstantiated); | |
| 2424 if (node->constructor().IsFactory()) { | 2432 if (node->constructor().IsFactory()) { |
| 2425 // A runtime call to instantiate the type arguments is required before | 2433 // A runtime call to instantiate the type arguments is required before |
| 2426 // calling the factory. | 2434 // calling the factory. |
| 2427 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 2435 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 2428 __ PushObject(node->type_arguments()); | 2436 __ PushObject(node->type_arguments()); |
| 2429 __ pushl(EAX); // Push instantiator type arguments. | 2437 __ pushl(EAX); // Push instantiator type arguments. |
| 2430 GenerateCallRuntime(node->id(), | 2438 GenerateCallRuntime(node->id(), |
| 2431 node->token_index(), | 2439 node->token_index(), |
| 2432 kInstantiateTypeArgumentsRuntimeEntry); | 2440 kInstantiateTypeArgumentsRuntimeEntry); |
| 2433 __ popl(EAX); // Pop instantiator type arguments. | 2441 __ popl(EAX); // Pop instantiator type arguments. |
| 2434 __ popl(EAX); // Pop uninstantiated type arguments. | 2442 __ popl(EAX); // Pop uninstantiated type arguments. |
| 2435 __ popl(EAX); // Pop instantiated type arguments. | 2443 __ popl(EAX); // Pop instantiated type arguments. |
| 2436 __ Bind(&type_arguments_instantiated); | 2444 __ Bind(&type_arguments_instantiated); |
| 2437 __ pushl(EAX); // Instantiated type arguments. | 2445 __ pushl(EAX); // Instantiated type arguments. |
| 2438 } else { | 2446 } else { |
| 2439 // In the non-factory case, we rely on the allocation stub to | 2447 // In the non-factory case, we rely on the allocation stub to |
| 2440 // instantiate the type arguments. | 2448 // instantiate the type arguments. |
| 2441 __ PushObject(node->type_arguments()); | 2449 __ PushObject(node->type_arguments()); |
| 2442 __ pushl(EAX); // Instantiator type arguments. | 2450 __ pushl(EAX); // Instantiator type arguments. |
| 2443 Label type_arguments_pushed; | 2451 Label type_arguments_pushed; |
| 2444 __ jmp(&type_arguments_pushed, Assembler::kNearJump); | 2452 __ jmp(&type_arguments_pushed, Assembler::kNearJump); |
| 2445 | 2453 |
| 2446 __ Bind(&type_arguments_instantiated); | 2454 __ Bind(&type_arguments_instantiated); |
| 2447 __ pushl(EAX); // Instantiated type arguments. | 2455 __ pushl(EAX); // Instantiated type arguments. |
| 2448 __ pushl(raw_null); // Null instantiator. | 2456 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2449 __ Bind(&type_arguments_pushed); | 2457 __ Bind(&type_arguments_pushed); |
| 2450 } | 2458 } |
| 2451 } | 2459 } |
| 2452 } | 2460 } |
| 2453 | 2461 |
| 2454 | 2462 |
| 2455 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { | 2463 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { |
| 2456 if (node->constructor().IsFactory()) { | 2464 if (node->constructor().IsFactory()) { |
| 2457 const bool requires_type_arguments = true; // Always first arg to factory. | 2465 const bool requires_type_arguments = true; // Always first arg to factory. |
| 2458 GenerateTypeArguments(node, requires_type_arguments); | 2466 GenerateTypeArguments(node, requires_type_arguments); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2490 } | 2498 } |
| 2491 | 2499 |
| 2492 if (IsResultNeeded(node)) { | 2500 if (IsResultNeeded(node)) { |
| 2493 __ pushl(EAX); // Set up return value from allocate. | 2501 __ pushl(EAX); // Set up return value from allocate. |
| 2494 } | 2502 } |
| 2495 | 2503 |
| 2496 // First argument(this) for constructor call which follows. | 2504 // First argument(this) for constructor call which follows. |
| 2497 __ pushl(EAX); | 2505 __ pushl(EAX); |
| 2498 // Second argument is the implicit construction phase parameter. | 2506 // Second argument is the implicit construction phase parameter. |
| 2499 // Run both the constructor initializer list and the constructor body. | 2507 // Run both the constructor initializer list and the constructor body. |
| 2500 __ PushObject(Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 2508 __ pushl(Immediate(Smi::RawValue(Function::kCtorPhaseAll))); |
| 2501 | |
| 2502 | 2509 |
| 2503 // Now setup rest of the arguments for the constructor call. | 2510 // Now setup rest of the arguments for the constructor call. |
| 2504 node->arguments()->Visit(this); | 2511 node->arguments()->Visit(this); |
| 2505 | 2512 |
| 2506 // Call the constructor. | 2513 // Call the constructor. |
| 2507 // +2 to include implicit receiver and phase arguments. | 2514 // +2 to include implicit receiver and phase arguments. |
| 2508 int num_args = node->arguments()->length() + 2; | 2515 int num_args = node->arguments()->length() + 2; |
| 2509 __ LoadObject(ECX, node->constructor()); | 2516 __ LoadObject(ECX, node->constructor()); |
| 2510 __ LoadObject(EDX, ArgumentsDescriptor(num_args, node->arguments()->names())); | 2517 __ LoadObject(EDX, ArgumentsDescriptor(num_args, node->arguments()->names())); |
| 2511 GenerateCall(node->token_index(), | 2518 GenerateCall(node->token_index(), |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2832 const Error& error = Error::Handle( | 2839 const Error& error = Error::Handle( |
| 2833 Parser::FormatError(script, token_index, "Error", format, args)); | 2840 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2834 va_end(args); | 2841 va_end(args); |
| 2835 Isolate::Current()->long_jump_base()->Jump(1, error); | 2842 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2836 UNREACHABLE(); | 2843 UNREACHABLE(); |
| 2837 } | 2844 } |
| 2838 | 2845 |
| 2839 } // namespace dart | 2846 } // namespace dart |
| 2840 | 2847 |
| 2841 #endif // defined TARGET_ARCH_IA32 | 2848 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |