| 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 1397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1408 __ PushObject(negate_result ? bool_true : bool_false); | 1408 __ PushObject(negate_result ? bool_true : bool_false); |
| 1409 __ jmp(&done, Assembler::kNearJump); | 1409 __ jmp(&done, Assembler::kNearJump); |
| 1410 | 1410 |
| 1411 __ Bind(&non_null); | 1411 __ Bind(&non_null); |
| 1412 // If type is instantiated and non-parameterized, we can inline code | 1412 // If type is instantiated and non-parameterized, we can inline code |
| 1413 // checking whether the tested instance is a Smi. | 1413 // checking whether the tested instance is a Smi. |
| 1414 if (type.IsInstantiated()) { | 1414 if (type.IsInstantiated()) { |
| 1415 const Class& type_class = Class::ZoneHandle(type.type_class()); | 1415 const Class& type_class = Class::ZoneHandle(type.type_class()); |
| 1416 const bool requires_type_arguments = type_class.HasTypeArguments(); | 1416 const bool requires_type_arguments = type_class.HasTypeArguments(); |
| 1417 // A Smi object cannot be the instance of a parameterized class. | 1417 // A Smi object cannot be the instance of a parameterized class. |
| 1418 // A class equality check is only applicable to a non-parameterized class. | 1418 // A class equality check is only applicable with a dst type of a |
| 1419 // TODO(regis): Should we still inline a Smi type check when checking for a | 1419 // non-parameterized class or with a raw dst type of a parameterized class. |
| 1420 // parameterized type and return false for a Smi's without calling the | 1420 if (requires_type_arguments) { |
| 1421 // runtime? | 1421 const TypeArguments& type_arguments = |
| 1422 if (!requires_type_arguments) { | 1422 TypeArguments::Handle(type.arguments()); |
| 1423 const bool is_raw_type = type_arguments.IsNull() || |
| 1424 type_arguments.IsDynamicTypes(type_arguments.Length()); |
| 1425 Label runtime_call; |
| 1426 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1427 __ j(ZERO, &runtime_call, Assembler::kNearJump); |
| 1428 // Object not Smi. |
| 1429 if (is_raw_type) { |
| 1430 if (!type_class.is_interface()) { |
| 1431 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1432 __ CompareObject(ECX, type_class); |
| 1433 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); |
| 1434 __ PushObject(negate_result ? bool_false : bool_true); |
| 1435 __ jmp(&done, Assembler::kNearJump); |
| 1436 } |
| 1437 } |
| 1438 __ Bind(&runtime_call); |
| 1439 // Fall through to runtime call. |
| 1440 } else { |
| 1423 Label compare_classes; | 1441 Label compare_classes; |
| 1424 __ testl(EAX, Immediate(kSmiTagMask)); | 1442 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1425 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); | 1443 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); |
| 1426 // Object is Smi. | 1444 // Object is Smi. |
| 1427 const Class& smi_class = Class::Handle(Smi::Class()); | 1445 const Class& smi_class = Class::Handle(Smi::Class()); |
| 1428 // TODO(regis): We should introduce a SmiType. | 1446 // TODO(regis): We should introduce a SmiType. |
| 1429 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), | 1447 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), |
| 1430 type_class, | 1448 type_class, |
| 1431 TypeArguments::Handle())) { | 1449 TypeArguments::Handle())) { |
| 1432 __ PushObject(negate_result ? bool_false : bool_true); | 1450 __ PushObject(negate_result ? bool_false : bool_true); |
| 1433 } else { | 1451 } else { |
| 1434 __ PushObject(negate_result ? bool_true : bool_false); | 1452 __ PushObject(negate_result ? bool_true : bool_false); |
| 1435 } | 1453 } |
| 1436 __ jmp(&done, Assembler::kNearJump); | 1454 __ jmp(&done, Assembler::kNearJump); |
| 1437 | 1455 |
| 1438 // Compare if the classes are equal. | 1456 // Compare if the classes are equal. |
| 1439 __ Bind(&compare_classes); | 1457 __ Bind(&compare_classes); |
| 1440 // If type is an interface, we can skip the class equality check, | 1458 if (type_class.is_interface()) { |
| 1441 // because instances cannot be of an interface type. | 1459 if (type.IsStringInterface()) { |
| 1442 if (!type_class.is_interface()) { | 1460 Label runtime_call; |
| 1461 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1462 const Class& one_byte_string_class = Class::ZoneHandle( |
| 1463 Isolate::Current()->object_store()->one_byte_string_class()); |
| 1464 __ CompareObject(ECX, one_byte_string_class); |
| 1465 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); |
| 1466 __ PushObject(negate_result ? bool_false : bool_true); |
| 1467 __ jmp(&done, Assembler::kNearJump); |
| 1468 __ Bind(&runtime_call); |
| 1469 } |
| 1470 } else { // type_class is not an interface. |
| 1443 Label runtime_call; | 1471 Label runtime_call; |
| 1444 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1472 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1445 __ CompareObject(ECX, type_class); | 1473 __ CompareObject(ECX, type_class); |
| 1446 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); | 1474 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); |
| 1447 __ PushObject(negate_result ? bool_false : bool_true); | 1475 __ PushObject(negate_result ? bool_false : bool_true); |
| 1448 __ jmp(&done, Assembler::kNearJump); | 1476 __ jmp(&done, Assembler::kNearJump); |
| 1449 __ Bind(&runtime_call); | 1477 __ Bind(&runtime_call); |
| 1450 } | 1478 } |
| 1451 } | 1479 } |
| 1452 } | 1480 } |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1558 TestClassAndJump(*CoreClass("ObjectArray"), &done); | 1586 TestClassAndJump(*CoreClass("ObjectArray"), &done); |
| 1559 TestClassAndJump(*CoreClass("GrowableObjectArray"), &done); | 1587 TestClassAndJump(*CoreClass("GrowableObjectArray"), &done); |
| 1560 } else if (!dst_type_class.is_interface()) { | 1588 } else if (!dst_type_class.is_interface()) { |
| 1561 __ testl(EAX, Immediate(kSmiTagMask)); | 1589 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1562 __ j(ZERO, &runtime_call, Assembler::kNearJump); | 1590 __ j(ZERO, &runtime_call, Assembler::kNearJump); |
| 1563 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); | 1591 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); |
| 1564 TestClassAndJump(dst_type_class, &done); | 1592 TestClassAndJump(dst_type_class, &done); |
| 1565 } | 1593 } |
| 1566 // Fall through to runtime class. | 1594 // Fall through to runtime class. |
| 1567 } | 1595 } |
| 1568 } else { | 1596 } else { // dst_type has NO type arguments. |
| 1569 Label compare_classes; | 1597 Label compare_classes; |
| 1570 __ testl(EAX, Immediate(kSmiTagMask)); | 1598 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1571 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); | 1599 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); |
| 1572 // Object is Smi. | 1600 // Object is Smi. |
| 1573 const Class& smi_class = Class::Handle(Smi::Class()); | 1601 const Class& smi_class = Class::Handle(Smi::Class()); |
| 1574 // TODO(regis): We should introduce a SmiType. | 1602 // TODO(regis): We should introduce a SmiType. |
| 1575 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), | 1603 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), |
| 1576 dst_type_class, | 1604 dst_type_class, |
| 1577 TypeArguments::Handle())) { | 1605 TypeArguments::Handle())) { |
| 1578 // Successful assignable type check: return object in EAX. | 1606 // Successful assignable type check: return object in EAX. |
| (...skipping 1129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2708 const Class& cls = Class::Handle(parsed_function_.function().owner()); | 2736 const Class& cls = Class::Handle(parsed_function_.function().owner()); |
| 2709 const Script& script = Script::Handle(cls.script()); | 2737 const Script& script = Script::Handle(cls.script()); |
| 2710 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); | 2738 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); |
| 2711 Isolate::Current()->long_jump_base()->Jump(1, error_msg); | 2739 Isolate::Current()->long_jump_base()->Jump(1, error_msg); |
| 2712 UNREACHABLE(); | 2740 UNREACHABLE(); |
| 2713 } | 2741 } |
| 2714 | 2742 |
| 2715 } // namespace dart | 2743 } // namespace dart |
| 2716 | 2744 |
| 2717 #endif // defined TARGET_ARCH_IA32 | 2745 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |