Chromium Code Reviews| 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 1450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1461 // function. | 1461 // function. |
| 1462 if (dst_type.IsVoidType()) { | 1462 if (dst_type.IsVoidType()) { |
| 1463 return; | 1463 return; |
| 1464 } | 1464 } |
| 1465 | 1465 |
| 1466 // A null object is always assignable and is returned as result. | 1466 // A null object is always assignable and is returned as result. |
| 1467 const Immediate raw_null = | 1467 const Immediate raw_null = |
| 1468 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1468 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1469 Label done, runtime_call; | 1469 Label done, runtime_call; |
| 1470 __ cmpl(EAX, raw_null); | 1470 __ cmpl(EAX, raw_null); |
| 1471 __ j(EQUAL, &done, Assembler::kNearJump); | 1471 __ j(EQUAL, &done); |
| 1472 | 1472 |
| 1473 // Generate throw new TypeError() if the type is malformed. | 1473 // Generate throw new TypeError() if the type is malformed. |
| 1474 if (dst_type.IsMalformed()) { | 1474 if (dst_type.IsMalformed()) { |
| 1475 const Error& error = Error::Handle(dst_type.malformed_error()); | 1475 const Error& error = Error::Handle(dst_type.malformed_error()); |
| 1476 const String& error_message = String::ZoneHandle( | 1476 const String& error_message = String::ZoneHandle( |
| 1477 String::NewSymbol(error.ToErrorCString())); | 1477 String::NewSymbol(error.ToErrorCString())); |
| 1478 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1478 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1479 const Immediate location = | 1479 const Immediate location = |
| 1480 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); | 1480 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); |
| 1481 __ pushl(location); // Push the source location. | 1481 __ pushl(location); // Push the source location. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1536 __ jmp(&done, Assembler::kNearJump); | 1536 __ jmp(&done, Assembler::kNearJump); |
| 1537 } else { | 1537 } else { |
| 1538 // Failed assignable type check: call runtime to throw TypeError. | 1538 // Failed assignable type check: call runtime to throw TypeError. |
| 1539 __ jmp(&runtime_call, Assembler::kNearJump); | 1539 __ jmp(&runtime_call, Assembler::kNearJump); |
| 1540 } | 1540 } |
| 1541 // Compare if the classes are equal. | 1541 // Compare if the classes are equal. |
| 1542 __ Bind(&compare_classes); | 1542 __ Bind(&compare_classes); |
| 1543 // If dst_type is an interface, we can skip the class equality check, | 1543 // If dst_type is an interface, we can skip the class equality check, |
| 1544 // because instances cannot be of an interface type. | 1544 // because instances cannot be of an interface type. |
| 1545 if (!dst_type_class.is_interface()) { | 1545 if (!dst_type_class.is_interface()) { |
| 1546 // Check if classes are equal. | 1546 __ LoadObject(EDX, dst_type_class); |
| 1547 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1547 __ cmpl(EDX, ECX); |
| 1548 TestClassAndJump(dst_type_class, &done); // Uses ECX. | 1548 __ j(EQUAL, &done, Assembler::kNearJump); |
| 1549 // Check superclasses using a loop (faster than runtime call). | 1549 __ pushl(EAX); |
| 1550 Label loop_done, loop; | 1550 __ call(&StubCode::IsSubTypeLabel()); |
| 1551 __ Bind(&loop); | 1551 __ movl(EDI, EAX); |
| 1552 // ECX: class. | 1552 __ popl(EAX); |
| 1553 __ movl(ECX, FieldAddress(ECX, Class::super_type_offset())); | 1553 __ cmpl(EDI, Immediate(1)); |
| 1554 // The supertype of Object is a null object. | 1554 __ j(EQUAL, &done, Assembler::kNearJump); |
| 1555 __ cmpl(ECX, raw_null); | 1555 // Otherwise fallthrough |
| 1556 __ j(EQUAL, &loop_done, Assembler::kNearJump); | |
| 1557 __ movl(ECX, FieldAddress(ECX, Type::type_class_offset())); | |
| 1558 TestClassAndJump(dst_type_class, &done); // Uses ECX. | |
| 1559 __ jmp(&loop); | |
| 1560 __ Bind(&loop_done); | |
| 1561 } else { | 1556 } else { |
| 1562 // However, for specific core library interfaces, we can check for | 1557 // However, for specific core library interfaces, we can check for |
| 1563 // specific core library classes. | 1558 // specific core library classes. |
| 1564 Error& malformed_error = Error::Handle(); | 1559 Error& malformed_error = Error::Handle(); |
| 1565 if (dst_type.IsBoolInterface()) { | 1560 if (dst_type.IsBoolInterface()) { |
| 1566 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1561 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1567 const Class& bool_class = Class::ZoneHandle( | 1562 const Class& bool_class = Class::ZoneHandle( |
| 1568 Isolate::Current()->object_store()->bool_class()); | 1563 Isolate::Current()->object_store()->bool_class()); |
| 1569 TestClassAndJump(bool_class, &done); | 1564 TestClassAndJump(bool_class, &done); |
| 1570 } else if (dst_type.IsSubtypeOf( | 1565 } else if (dst_type.IsSubtypeOf( |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1594 TestClassAndJump(two_byte_string_class, &done); | 1589 TestClassAndJump(two_byte_string_class, &done); |
| 1595 const Class& four_byte_string_class = Class::ZoneHandle( | 1590 const Class& four_byte_string_class = Class::ZoneHandle( |
| 1596 Isolate::Current()->object_store()->four_byte_string_class()); | 1591 Isolate::Current()->object_store()->four_byte_string_class()); |
| 1597 TestClassAndJump(four_byte_string_class, &done); | 1592 TestClassAndJump(four_byte_string_class, &done); |
| 1598 } else if (dst_type.IsFunctionInterface()) { | 1593 } else if (dst_type.IsFunctionInterface()) { |
| 1599 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1594 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1600 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset())); | 1595 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset())); |
| 1601 __ cmpl(ECX, raw_null); | 1596 __ cmpl(ECX, raw_null); |
| 1602 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1597 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 1603 } else { | 1598 } else { |
| 1604 // Check interfaces. | 1599 __ LoadObject(EDX, dst_type_class); |
| 1605 Label fall_through; | 1600 // EAX: Instance (preserve). |
| 1606 // Get interfaces array from class. | 1601 // EDX: test class |
| 1607 __ movl(EBX, FieldAddress(EAX, Object::class_offset())); | 1602 __ pushl(EAX); |
| 1608 __ movl(EBX, FieldAddress(EBX, Class::interfaces_offset())); | 1603 __ call(&StubCode::IsSubTypeLabel()); |
| 1609 __ cmpl(EBX, raw_null); | 1604 __ movl(EDI, EAX); |
| 1610 __ j(EQUAL, &fall_through, Assembler::kNearJump); | 1605 __ popl(EAX); |
| 1611 // Iterate over interfaces array and check if any of interfaces match. | 1606 __ cmpl(EDI, Immediate(1)); |
| 1612 __ movl(EDI, FieldAddress(EBX, Array::length_offset())); | 1607 __ j(EQUAL, &done, Assembler::kNearJump); |
| 1613 // EDI: array index | 1608 // Otherwise fallthrough |
| 1614 // EBX: array | |
| 1615 Label loop; | |
| 1616 __ Bind(&loop); | |
| 1617 __ subl(EDI, Immediate(Smi::RawValue(1))); | |
| 1618 __ cmpl(EDI, Immediate(0)); | |
| 1619 __ j(LESS, &runtime_call, Assembler::kNearJump); | |
| 1620 // EDI is Smi therefore TIMES_2 instead of TIMES_4. | |
| 1621 // Get type from array. | |
| 1622 __ movl(ECX, FieldAddress(EBX, EDI, TIMES_2, Array::data_offset())); | |
| 1623 __ movl(ECX, FieldAddress(ECX, Type::type_class_offset())); | |
| 1624 TestClassAndJump(dst_type_class, &done); // Uses ECX. | |
| 1625 __ jmp(&loop, Assembler::kNearJump); | |
| 1626 // Fall through to runtime code. | |
| 1627 __ Bind(&fall_through); | |
| 1628 } | 1609 } |
| 1629 } | 1610 } |
| 1630 } | 1611 } |
| 1631 } else { | 1612 } else { |
| 1632 ASSERT(!dst_type.IsInstantiated()); | 1613 ASSERT(!dst_type.IsInstantiated()); |
| 1633 // Skip check if destination is a dynamic type. | 1614 // Skip check if destination is a dynamic type. |
| 1634 if (dst_type.IsTypeParameter()) { | 1615 if (dst_type.IsTypeParameter()) { |
| 1635 // EAX must be preserved! | 1616 // EAX must be preserved! |
| 1636 Label fall_through; | 1617 Label fall_through; |
| 1637 GenerateInstantiatorTypeArguments(token_index); | 1618 GenerateInstantiatorTypeArguments(token_index); |
| 1638 // Type arguments are on stack | 1619 // Type arguments are on stack |
| 1639 __ popl(EBX); | 1620 __ popl(EBX); |
| 1640 // Check if dynamic. | 1621 // Check if dynamic. |
| 1641 __ cmpl(EBX, raw_null); | 1622 __ cmpl(EBX, raw_null); |
| 1642 __ j(EQUAL, &done, Assembler::kNearJump); | 1623 __ j(EQUAL, &done, Assembler::kNearJump); |
| 1643 | 1624 |
| 1644 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. | 1625 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. |
| 1645 __ movl(EDX, FieldAddress(EBX, Object::class_offset())); | 1626 __ movl(EDX, FieldAddress(EBX, Object::class_offset())); |
| 1646 __ CompareObject(EDX, Object::ZoneHandle(Object::type_arguments_class())); | 1627 __ CompareObject(EDX, Object::ZoneHandle(Object::type_arguments_class())); |
| 1647 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | 1628 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); |
| 1629 // EBX: Instance of TypeArguments. | |
| 1648 __ movl(EDX, | 1630 __ movl(EDX, |
| 1649 FieldAddress(EBX, TypeArguments::type_at_offset(dst_type.Index()))); | 1631 FieldAddress(EBX, TypeArguments::type_at_offset(dst_type.Index()))); |
| 1632 // EDX: concrete type of dst_type. | |
| 1650 __ CompareObject(EDX, Type::ZoneHandle(Type::DynamicType())); | 1633 __ CompareObject(EDX, Type::ZoneHandle(Type::DynamicType())); |
| 1651 __ j(EQUAL, &done, Assembler::kNearJump); | 1634 __ j(EQUAL, &done, Assembler::kNearJump); |
| 1635 // Check if the type has type parameters, if not do the class comparison. | |
| 1636 Label not_smi; | |
| 1637 __ testl(EAX, Immediate(kSmiTagMask)); // Value is Smi? | |
| 1638 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); | |
| 1639 __ CompareObject(EDX, Type::ZoneHandle(Type::IntInterface())); | |
| 1640 __ j(EQUAL, &done, Assembler::kNearJump); | |
| 1641 __ CompareObject(EDX, Type::ZoneHandle(Type::NumberInterface())); | |
| 1642 __ j(EQUAL, &done, Assembler::kNearJump); | |
| 1643 __ Bind(¬_smi); | |
| 1644 __ movl(EDX, FieldAddress(EDX, Type::type_class_offset())); | |
| 1645 __ movl(ECX, FieldAddress(EDX, Class::type_parameters_offset())); | |
| 1646 // Check that class of dst_type has no type parameters. | |
| 1647 __ cmpl(ECX, raw_null); | |
| 1648 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | |
| 1649 // We have a non-parameterized class in EDX, compare with class of | |
| 1650 // value in EAX. | |
| 1651 __ pushl(EAX); | |
| 1652 __ call(&StubCode::IsSubTypeLabel()); | |
| 1653 __ movl(EDI, EAX); | |
| 1654 __ popl(EAX); | |
| 1655 __ cmpl(EDI, Immediate(1)); | |
| 1656 __ j(EQUAL, &done, Assembler::kNearJump); | |
| 1657 // Check superclasses. | |
|
regis
2012/03/28 02:22:45
Is this comment left over?
srdjan
2012/03/28 15:42:15
Removed.
| |
| 1652 __ Bind(&fall_through); | 1658 __ Bind(&fall_through); |
| 1653 } | 1659 } |
| 1654 } | 1660 } |
| 1655 __ Bind(&runtime_call); | 1661 __ Bind(&runtime_call); |
| 1656 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1662 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| 1657 const Immediate location = | 1663 const Immediate location = |
| 1658 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); | 1664 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); |
| 1659 __ pushl(location); // Push the source location. | 1665 __ pushl(location); // Push the source location. |
| 1660 __ pushl(EAX); // Push the source object. | 1666 __ pushl(EAX); // Push the source object. |
| 1661 __ PushObject(dst_type); // Push the type of the destination. | 1667 __ PushObject(dst_type); // Push the type of the destination. |
| (...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2765 const Error& error = Error::Handle( | 2771 const Error& error = Error::Handle( |
| 2766 Parser::FormatError(script, token_index, "Error", format, args)); | 2772 Parser::FormatError(script, token_index, "Error", format, args)); |
| 2767 va_end(args); | 2773 va_end(args); |
| 2768 Isolate::Current()->long_jump_base()->Jump(1, error); | 2774 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2769 UNREACHABLE(); | 2775 UNREACHABLE(); |
| 2770 } | 2776 } |
| 2771 | 2777 |
| 2772 } // namespace dart | 2778 } // namespace dart |
| 2773 | 2779 |
| 2774 #endif // defined TARGET_ARCH_IA32 | 2780 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |