| 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 806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2389 bool requires_type_arguments) { | 2389 bool requires_type_arguments) { |
| 2390 const Immediate raw_null = | 2390 const Immediate raw_null = |
| 2391 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 2391 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 2392 // Instantiate the type arguments if necessary. | 2392 // Instantiate the type arguments if necessary. |
| 2393 if (node->type_arguments().IsNull() || | 2393 if (node->type_arguments().IsNull() || |
| 2394 node->type_arguments().IsInstantiated()) { | 2394 node->type_arguments().IsInstantiated()) { |
| 2395 if (requires_type_arguments) { | 2395 if (requires_type_arguments) { |
| 2396 // A factory requires the type arguments as first parameter. | 2396 // A factory requires the type arguments as first parameter. |
| 2397 __ PushObject(node->type_arguments()); | 2397 __ PushObject(node->type_arguments()); |
| 2398 if (!node->constructor().IsFactory()) { | 2398 if (!node->constructor().IsFactory()) { |
| 2399 // The allocator additionally requires the instantiator type arguments. | 2399 // The non-factory allocator additionally requires the instantiator |
| 2400 __ pushl(raw_null); // Null instantiator. | 2400 // type arguments which are not needed here, since the type arguments |
| 2401 // are instantiated. |
| 2402 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2401 } | 2403 } |
| 2402 } | 2404 } |
| 2403 } else { | 2405 } else { |
| 2404 // The type arguments are uninstantiated. | 2406 // The type arguments are uninstantiated. |
| 2405 ASSERT(requires_type_arguments); | 2407 ASSERT(requires_type_arguments); |
| 2406 GenerateInstantiatorTypeArguments(node->token_index()); | 2408 GenerateInstantiatorTypeArguments(node->token_index()); |
| 2407 __ popl(EAX); // Pop instantiator. | 2409 __ popl(EAX); // Pop instantiator. |
| 2408 // EAX is the instantiator AbstractTypeArguments object (or null). | 2410 // EAX is the instantiator AbstractTypeArguments object (or null). |
| 2409 // If EAX is null, no need to instantiate the type arguments, use null, and | 2411 // If the instantiator is null and if the type argument vector |
| 2410 // allocate an object of a raw type. | 2412 // instantiated from null becomes a vector of Dynamic, then use null as |
| 2411 Label type_arguments_instantiated, type_arguments_uninstantiated; | 2413 // the type arguments. |
| 2412 __ cmpl(EAX, raw_null); | 2414 Label type_arguments_instantiated; |
| 2413 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2415 const intptr_t len = node->type_arguments().Length(); |
| 2414 | 2416 if (node->type_arguments().IsRawInstantiatedRaw(len)) { |
| 2417 __ cmpl(EAX, raw_null); |
| 2418 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2419 } |
| 2415 // Instantiate non-null type arguments. | 2420 // Instantiate non-null type arguments. |
| 2416 if (node->type_arguments().IsUninstantiatedIdentity()) { | 2421 if (node->type_arguments().IsUninstantiatedIdentity()) { |
| 2417 // Check if the instantiator type argument vector is a TypeArguments of a | 2422 // Check if the instantiator type argument vector is a TypeArguments of a |
| 2418 // matching length and, if so, use it as the instantiated type_arguments. | 2423 // matching length and, if so, use it as the instantiated type_arguments. |
| 2424 // No need to check RAX for null (again), because a null instance will |
| 2425 // have the wrong class (Null instead of TypeArguments). |
| 2426 Label type_arguments_uninstantiated; |
| 2419 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class())); | 2427 __ LoadObject(ECX, Class::ZoneHandle(Object::type_arguments_class())); |
| 2420 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset())); | 2428 __ cmpl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 2421 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 2429 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 2422 Immediate arguments_length = Immediate(reinterpret_cast<int32_t>( | 2430 Immediate arguments_length = Immediate(reinterpret_cast<int32_t>( |
| 2423 Smi::New(node->type_arguments().Length()))); | 2431 Smi::New(node->type_arguments().Length()))); |
| 2424 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), | 2432 __ cmpl(FieldAddress(EAX, TypeArguments::length_offset()), |
| 2425 arguments_length); | 2433 arguments_length); |
| 2426 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2434 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2435 __ Bind(&type_arguments_uninstantiated); |
| 2427 } | 2436 } |
| 2428 __ Bind(&type_arguments_uninstantiated); | |
| 2429 if (node->constructor().IsFactory()) { | 2437 if (node->constructor().IsFactory()) { |
| 2430 // A runtime call to instantiate the type arguments is required before | 2438 // A runtime call to instantiate the type arguments is required before |
| 2431 // calling the factory. | 2439 // calling the factory. |
| 2432 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 2440 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 2433 __ PushObject(node->type_arguments()); | 2441 __ PushObject(node->type_arguments()); |
| 2434 __ pushl(EAX); // Push instantiator type arguments. | 2442 __ pushl(EAX); // Push instantiator type arguments. |
| 2435 GenerateCallRuntime(node->id(), | 2443 GenerateCallRuntime(node->id(), |
| 2436 node->token_index(), | 2444 node->token_index(), |
| 2437 kInstantiateTypeArgumentsRuntimeEntry); | 2445 kInstantiateTypeArgumentsRuntimeEntry); |
| 2438 __ popl(EAX); // Pop instantiator type arguments. | 2446 __ popl(EAX); // Pop instantiator type arguments. |
| 2439 __ popl(EAX); // Pop uninstantiated type arguments. | 2447 __ popl(EAX); // Pop uninstantiated type arguments. |
| 2440 __ popl(EAX); // Pop instantiated type arguments. | 2448 __ popl(EAX); // Pop instantiated type arguments. |
| 2441 __ Bind(&type_arguments_instantiated); | 2449 __ Bind(&type_arguments_instantiated); |
| 2442 __ pushl(EAX); // Instantiated type arguments. | 2450 __ pushl(EAX); // Instantiated type arguments. |
| 2443 } else { | 2451 } else { |
| 2444 // In the non-factory case, we rely on the allocation stub to | 2452 // In the non-factory case, we rely on the allocation stub to |
| 2445 // instantiate the type arguments. | 2453 // instantiate the type arguments. |
| 2446 __ PushObject(node->type_arguments()); | 2454 __ PushObject(node->type_arguments()); |
| 2447 __ pushl(EAX); // Instantiator type arguments. | 2455 __ pushl(EAX); // Instantiator type arguments. |
| 2448 Label type_arguments_pushed; | 2456 Label type_arguments_pushed; |
| 2449 __ jmp(&type_arguments_pushed, Assembler::kNearJump); | 2457 __ jmp(&type_arguments_pushed, Assembler::kNearJump); |
| 2450 | 2458 |
| 2451 __ Bind(&type_arguments_instantiated); | 2459 __ Bind(&type_arguments_instantiated); |
| 2452 __ pushl(EAX); // Instantiated type arguments. | 2460 __ pushl(EAX); // Instantiated type arguments. |
| 2453 __ pushl(raw_null); // Null instantiator. | 2461 __ pushl(Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2454 __ Bind(&type_arguments_pushed); | 2462 __ Bind(&type_arguments_pushed); |
| 2455 } | 2463 } |
| 2456 } | 2464 } |
| 2457 } | 2465 } |
| 2458 | 2466 |
| 2459 | 2467 |
| 2460 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { | 2468 void CodeGenerator::VisitConstructorCallNode(ConstructorCallNode* node) { |
| 2461 if (node->constructor().IsFactory()) { | 2469 if (node->constructor().IsFactory()) { |
| 2462 const bool requires_type_arguments = true; // Always first arg to factory. | 2470 const bool requires_type_arguments = true; // Always first arg to factory. |
| 2463 GenerateTypeArguments(node, requires_type_arguments); | 2471 GenerateTypeArguments(node, requires_type_arguments); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2495 } | 2503 } |
| 2496 | 2504 |
| 2497 if (IsResultNeeded(node)) { | 2505 if (IsResultNeeded(node)) { |
| 2498 __ pushl(EAX); // Set up return value from allocate. | 2506 __ pushl(EAX); // Set up return value from allocate. |
| 2499 } | 2507 } |
| 2500 | 2508 |
| 2501 // First argument(this) for constructor call which follows. | 2509 // First argument(this) for constructor call which follows. |
| 2502 __ pushl(EAX); | 2510 __ pushl(EAX); |
| 2503 // Second argument is the implicit construction phase parameter. | 2511 // Second argument is the implicit construction phase parameter. |
| 2504 // Run both the constructor initializer list and the constructor body. | 2512 // Run both the constructor initializer list and the constructor body. |
| 2505 __ PushObject(Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll))); | 2513 __ pushl(Immediate(Smi::RawValue(Function::kCtorPhaseAll))); |
| 2506 | |
| 2507 | 2514 |
| 2508 // Now setup rest of the arguments for the constructor call. | 2515 // Now setup rest of the arguments for the constructor call. |
| 2509 node->arguments()->Visit(this); | 2516 node->arguments()->Visit(this); |
| 2510 | 2517 |
| 2511 // Call the constructor. | 2518 // Call the constructor. |
| 2512 // +2 to include implicit receiver and phase arguments. | 2519 // +2 to include implicit receiver and phase arguments. |
| 2513 int num_args = node->arguments()->length() + 2; | 2520 int num_args = node->arguments()->length() + 2; |
| 2514 __ LoadObject(ECX, node->constructor()); | 2521 __ LoadObject(ECX, node->constructor()); |
| 2515 __ LoadObject(EDX, ArgumentsDescriptor(num_args, node->arguments()->names())); | 2522 __ LoadObject(EDX, ArgumentsDescriptor(num_args, node->arguments()->names())); |
| 2516 GenerateCall(node->token_index(), | 2523 GenerateCall(node->token_index(), |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2837 const Error& error = Error::Handle( | 2844 const Error& error = Error::Handle( |
| 2838 Parser::FormatError(script, token_index, "Error", format, args)); | 2845 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2839 va_end(args); | 2846 va_end(args); |
| 2840 Isolate::Current()->long_jump_base()->Jump(1, error); | 2847 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2841 UNREACHABLE(); | 2848 UNREACHABLE(); |
| 2842 } | 2849 } |
| 2843 | 2850 |
| 2844 } // namespace dart | 2851 } // namespace dart |
| 2845 | 2852 |
| 2846 #endif // defined TARGET_ARCH_IA32 | 2853 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |