Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(629)

Side by Side Diff: runtime/vm/code_generator_ia32.cc

Issue 9873014: Factor out super-class and interface array subtype checks into a stub. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/vm/object.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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::IsRawSubTypeLabel());
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
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::IsRawSubTypeLabel());
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, &not_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(&not_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::IsRawSubTypeLabel());
1653 __ movl(EDI, EAX);
1654 __ popl(EAX);
1655 __ cmpl(EDI, Immediate(1));
1656 __ j(EQUAL, &done, Assembler::kNearJump);
1652 __ Bind(&fall_through); 1657 __ Bind(&fall_through);
1653 } 1658 }
1654 } 1659 }
1655 __ Bind(&runtime_call); 1660 __ Bind(&runtime_call);
1656 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1661 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1657 const Immediate location = 1662 const Immediate location =
1658 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); 1663 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index)));
1659 __ pushl(location); // Push the source location. 1664 __ pushl(location); // Push the source location.
1660 __ pushl(EAX); // Push the source object. 1665 __ pushl(EAX); // Push the source object.
1661 __ PushObject(dst_type); // Push the type of the destination. 1666 __ PushObject(dst_type); // Push the type of the destination.
(...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after
2765 const Error& error = Error::Handle( 2770 const Error& error = Error::Handle(
2766 Parser::FormatError(script, token_index, "Error", format, args)); 2771 Parser::FormatError(script, token_index, "Error", format, args));
2767 va_end(args); 2772 va_end(args);
2768 Isolate::Current()->long_jump_base()->Jump(1, error); 2773 Isolate::Current()->long_jump_base()->Jump(1, error);
2769 UNREACHABLE(); 2774 UNREACHABLE();
2770 } 2775 }
2771 2776
2772 } // namespace dart 2777 } // namespace dart
2773 2778
2774 #endif // defined TARGET_ARCH_IA32 2779 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698