Chromium Code Reviews| 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 1462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1473 __ Bind(&negate_done); | 1473 __ Bind(&negate_done); |
| 1474 __ pushl(EAX); | 1474 __ pushl(EAX); |
| 1475 } | 1475 } |
| 1476 __ Bind(&done); | 1476 __ Bind(&done); |
| 1477 } | 1477 } |
| 1478 | 1478 |
| 1479 | 1479 |
| 1480 // Jumps to label if ECX equals the given class. | 1480 // Jumps to label if ECX equals the given class. |
| 1481 // Inputs: | 1481 // Inputs: |
| 1482 // - ECX: tested class. | 1482 // - ECX: tested class. |
| 1483 // Destroys EDX. | 1483 void CodeGenerator::TestClassAndJump(const Class& cls, Label *label) { |
| 1484 static void TestClassAndJump(Assembler* assembler, | 1484 __ CompareObject(ECX, cls); |
| 1485 const Class& cls, | 1485 __ j(EQUAL, label, Assembler::kNearJump); |
| 1486 Label *label) { | 1486 } |
| 1487 assembler->LoadObject(EDX, cls); | 1487 |
| 1488 assembler->cmpl(EDX, ECX); | 1488 |
| 1489 assembler->j(EQUAL, label, Assembler::kNearJump); | 1489 static const Class* CoreClass(const char* c_name) { |
| 1490 const String& class_name = String::Handle(String::NewSymbol(c_name)); | |
| 1491 const Class& cls = Class::ZoneHandle(Library::Handle( | |
| 1492 Library::CoreImplLibrary()).LookupClass(class_name)); | |
| 1493 ASSERT(!cls.IsNull()); | |
| 1494 return &cls; | |
| 1490 } | 1495 } |
| 1491 | 1496 |
| 1492 | 1497 |
| 1493 // Optimize assignable type check by adding inlined tests for: | 1498 // Optimize assignable type check by adding inlined tests for: |
| 1494 // - NULL -> return NULL. | 1499 // - NULL -> return NULL. |
| 1495 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 1500 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
| 1496 // - Class equality (only if class is not parameterized). | 1501 // - Class equality (only if class is not parameterized). |
| 1497 // Inputs: | 1502 // Inputs: |
| 1498 // - EAX: object. | 1503 // - EAX: object. |
| 1499 // Destroys ECX and EDX. | 1504 // Destroys ECX and EDX. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1529 Label done, runtime_call; | 1534 Label done, runtime_call; |
| 1530 __ cmpl(EAX, raw_null); | 1535 __ cmpl(EAX, raw_null); |
| 1531 __ j(EQUAL, &done, Assembler::kNearJump); | 1536 __ j(EQUAL, &done, Assembler::kNearJump); |
| 1532 | 1537 |
| 1533 // If dst_type is instantiated and non-parameterized, we can inline code | 1538 // If dst_type is instantiated and non-parameterized, we can inline code |
| 1534 // checking whether the assigned instance is a Smi. | 1539 // checking whether the assigned instance is a Smi. |
| 1535 if (dst_type.IsInstantiated()) { | 1540 if (dst_type.IsInstantiated()) { |
| 1536 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); | 1541 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); |
| 1537 const bool dst_has_type_arguments = dst_type_class.HasTypeArguments(); | 1542 const bool dst_has_type_arguments = dst_type_class.HasTypeArguments(); |
| 1538 // A Smi object cannot be the instance of a parameterized class. | 1543 // A Smi object cannot be the instance of a parameterized class. |
| 1539 // A class equality check is only applicable to a non-parameterized class. | 1544 // A class equality check is only applicable to a non-parameterized class. |
|
regis
2011/11/09 01:47:53
// A class equality check is only applicable with
srdjan
2011/11/09 19:36:30
Done.
| |
| 1540 if (!dst_has_type_arguments) { | 1545 if (dst_has_type_arguments) { |
|
regis
2011/11/09 01:47:53
dst_class_has_type_arguments
srdjan
2011/11/09 19:36:30
Done.
| |
| 1546 const TypeArguments& arguments = | |
|
regis
2011/11/09 01:47:53
arguments -> dst_type_arguments.
srdjan
2011/11/09 19:36:30
Done.
| |
| 1547 TypeArguments::Handle(dst_type.arguments()); | |
| 1548 bool no_type_arguments = arguments.IsNull() || | |
|
regis
2011/11/09 01:47:53
Why the local? Make it const if you want to keep i
srdjan
2011/11/09 19:36:30
Made it a const. Giving it a name makes clear what
| |
| 1549 arguments.IsDynamicTypes(arguments.Length()); | |
| 1550 if (no_type_arguments) { | |
| 1551 // Dynamic type argument, check only classes. | |
| 1552 if (dst_type.IsListInterface()) { | |
| 1553 // TODO(srdjan) also accept List<Object>. | |
| 1554 __ testl(EAX, Immediate(kSmiTagMask)); | |
| 1555 __ j(ZERO, &runtime_call, Assembler::kNearJump); | |
| 1556 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | |
| 1557 TestClassAndJump(*CoreClass("ObjectArray"), &done); | |
| 1558 TestClassAndJump(*CoreClass("GrowableObjectArray"), &done); | |
| 1559 } else if (!dst_type_class.is_interface()) { | |
| 1560 __ testl(EAX, Immediate(kSmiTagMask)); | |
| 1561 __ j(ZERO, &runtime_call, Assembler::kNearJump); | |
| 1562 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | |
| 1563 TestClassAndJump(dst_type_class, &done); | |
| 1564 } | |
| 1565 // Fall through to runtime class. | |
| 1566 } | |
| 1567 } else { | |
| 1541 Label compare_classes; | 1568 Label compare_classes; |
| 1542 __ testl(EAX, Immediate(kSmiTagMask)); | 1569 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1543 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); | 1570 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); |
| 1544 // Object is Smi. | 1571 // Object is Smi. |
| 1545 const Class& smi_class = Class::Handle(Smi::Class()); | 1572 const Class& smi_class = Class::Handle(Smi::Class()); |
| 1546 // TODO(regis): We should introduce a SmiType. | 1573 // TODO(regis): We should introduce a SmiType. |
| 1547 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), | 1574 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), |
| 1548 dst_type_class, | 1575 dst_type_class, |
| 1549 TypeArguments::Handle())) { | 1576 TypeArguments::Handle())) { |
| 1550 // Successful assignable type check: return object in EAX. | 1577 // Successful assignable type check: return object in EAX. |
| 1551 __ jmp(&done, Assembler::kNearJump); | 1578 __ jmp(&done, Assembler::kNearJump); |
| 1552 } else { | 1579 } else { |
| 1553 // Failed assignable type check: call runtime to throw TypeError. | 1580 // Failed assignable type check: call runtime to throw TypeError. |
| 1554 __ jmp(&runtime_call, Assembler::kNearJump); | 1581 __ jmp(&runtime_call, Assembler::kNearJump); |
| 1555 } | 1582 } |
| 1556 // Compare if the classes are equal. | 1583 // Compare if the classes are equal. |
| 1557 __ Bind(&compare_classes); | 1584 __ Bind(&compare_classes); |
| 1558 // If dst_type is an interface, we can skip the class equality check, | 1585 // If dst_type is an interface, we can skip the class equality check, |
| 1559 // because instances cannot be of an interface type. | 1586 // because instances cannot be of an interface type. |
| 1560 if (!dst_type_class.is_interface()) { | 1587 if (!dst_type_class.is_interface()) { |
| 1561 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1588 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1562 TestClassAndJump(assembler_, dst_type_class, &done); | 1589 TestClassAndJump(dst_type_class, &done); |
| 1563 } else { | 1590 } else { |
| 1564 // However, for specific core library interfaces, we can check for | 1591 // However, for specific core library interfaces, we can check for |
| 1565 // specific core library classes. | 1592 // specific core library classes. |
| 1566 if (dst_type.IsBoolInterface()) { | 1593 if (dst_type.IsBoolInterface()) { |
| 1567 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1594 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1568 const Class& bool_class = Class::ZoneHandle( | 1595 const Class& bool_class = Class::ZoneHandle( |
| 1569 Isolate::Current()->object_store()->bool_class()); | 1596 Isolate::Current()->object_store()->bool_class()); |
| 1570 TestClassAndJump(assembler_, bool_class, &done); | 1597 TestClassAndJump(bool_class, &done); |
| 1571 } else if (dst_type.IsSubtypeOf( | 1598 } else if (dst_type.IsSubtypeOf( |
| 1572 Type::Handle(Type::NumberInterface()))) { | 1599 Type::Handle(Type::NumberInterface()))) { |
| 1573 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1600 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1574 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) { | 1601 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) { |
| 1575 // We already checked for Smi above. | 1602 // We already checked for Smi above. |
| 1576 const Class& mint_class = Class::ZoneHandle( | 1603 const Class& mint_class = Class::ZoneHandle( |
| 1577 Isolate::Current()->object_store()->mint_class()); | 1604 Isolate::Current()->object_store()->mint_class()); |
| 1578 TestClassAndJump(assembler_, mint_class, &done); | 1605 TestClassAndJump(mint_class, &done); |
| 1579 const Class& bigint_class = Class::ZoneHandle( | 1606 const Class& bigint_class = Class::ZoneHandle( |
| 1580 Isolate::Current()->object_store()->bigint_class()); | 1607 Isolate::Current()->object_store()->bigint_class()); |
| 1581 TestClassAndJump(assembler_, bigint_class, &done); | 1608 TestClassAndJump(bigint_class, &done); |
| 1582 } | 1609 } |
| 1583 if (dst_type.IsDoubleInterface() || dst_type.IsNumberInterface()) { | 1610 if (dst_type.IsDoubleInterface() || dst_type.IsNumberInterface()) { |
| 1584 const Class& double_class = Class::ZoneHandle( | 1611 const Class& double_class = Class::ZoneHandle( |
| 1585 Isolate::Current()->object_store()->double_class()); | 1612 Isolate::Current()->object_store()->double_class()); |
| 1586 TestClassAndJump(assembler_, double_class, &done); | 1613 TestClassAndJump(double_class, &done); |
| 1587 } | 1614 } |
| 1588 } else if (dst_type.IsStringInterface()) { | 1615 } else if (dst_type.IsStringInterface()) { |
| 1589 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1616 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1590 const Class& one_byte_string_class = Class::ZoneHandle( | 1617 const Class& one_byte_string_class = Class::ZoneHandle( |
| 1591 Isolate::Current()->object_store()->one_byte_string_class()); | 1618 Isolate::Current()->object_store()->one_byte_string_class()); |
| 1592 TestClassAndJump(assembler_, one_byte_string_class, &done); | 1619 TestClassAndJump(one_byte_string_class, &done); |
| 1593 const Class& two_byte_string_class = Class::ZoneHandle( | 1620 const Class& two_byte_string_class = Class::ZoneHandle( |
| 1594 Isolate::Current()->object_store()->two_byte_string_class()); | 1621 Isolate::Current()->object_store()->two_byte_string_class()); |
| 1595 TestClassAndJump(assembler_, two_byte_string_class, &done); | 1622 TestClassAndJump(two_byte_string_class, &done); |
| 1596 const Class& four_byte_string_class = Class::ZoneHandle( | 1623 const Class& four_byte_string_class = Class::ZoneHandle( |
| 1597 Isolate::Current()->object_store()->four_byte_string_class()); | 1624 Isolate::Current()->object_store()->four_byte_string_class()); |
| 1598 TestClassAndJump(assembler_, four_byte_string_class, &done); | 1625 TestClassAndJump(four_byte_string_class, &done); |
| 1599 } else if (dst_type.IsFunctionInterface()) { | 1626 } else if (dst_type.IsFunctionInterface()) { |
| 1600 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1627 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1601 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset())); | 1628 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset())); |
| 1602 __ cmpl(ECX, raw_null); | 1629 __ cmpl(ECX, raw_null); |
| 1603 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1630 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 1604 } | 1631 } |
| 1605 } | 1632 } |
| 1606 } | 1633 } |
| 1607 } | 1634 } |
| 1608 __ Bind(&runtime_call); | 1635 __ Bind(&runtime_call); |
| (...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2680 const Class& cls = Class::Handle(parsed_function_.function().owner()); | 2707 const Class& cls = Class::Handle(parsed_function_.function().owner()); |
| 2681 const Script& script = Script::Handle(cls.script()); | 2708 const Script& script = Script::Handle(cls.script()); |
| 2682 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); | 2709 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); |
| 2683 Isolate::Current()->long_jump_base()->Jump(1, error_msg); | 2710 Isolate::Current()->long_jump_base()->Jump(1, error_msg); |
| 2684 UNREACHABLE(); | 2711 UNREACHABLE(); |
| 2685 } | 2712 } |
| 2686 | 2713 |
| 2687 } // namespace dart | 2714 } // namespace dart |
| 2688 | 2715 |
| 2689 #endif // defined TARGET_ARCH_IA32 | 2716 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |