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

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

Issue 10381045: Improve type checking, remove unused stub (removed also in x64 in preparation of porting the better… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 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
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 1427 matching lines...) Expand 10 before | Expand all | Expand 10 after
1438 // TODO(srdjan) also accept List<Object>. 1438 // TODO(srdjan) also accept List<Object>.
1439 __ CompareObject(ECX, *CoreClass("ObjectArray")); 1439 __ CompareObject(ECX, *CoreClass("ObjectArray"));
1440 __ j(EQUAL, is_instance_lbl); 1440 __ j(EQUAL, is_instance_lbl);
1441 __ CompareObject(ECX, *CoreClass("GrowableObjectArray")); 1441 __ CompareObject(ECX, *CoreClass("GrowableObjectArray"));
1442 __ j(EQUAL, is_instance_lbl); 1442 __ j(EQUAL, is_instance_lbl);
1443 } 1443 }
1444 return 1444 return
1445 GenerateSubtype1TestCacheLookup(node_id, token_index, type_class, 1445 GenerateSubtype1TestCacheLookup(node_id, token_index, type_class,
1446 is_instance_lbl, is_not_instance_lbl); 1446 is_instance_lbl, is_not_instance_lbl);
1447 } 1447 }
1448 // Note that the test below must be synced with the tests in 1448 // If one type argument only, quick check.
1449 // CodeGenerator::UpdateTestCache. 1449 if (type_arguments.Length() == 1) {
1450 // Inline checks for one type argument only. 1450 const AbstractType& tp_argument = AbstractType::ZoneHandle(
1451 if (type_arguments.Length() != 1) { 1451 type_arguments.TypeAt(0));
1452 return SubtypeTestCache::null(); 1452 // Malformed type has been caught in the caller chain of this function.
1453 } 1453 ASSERT(tp_argument.HasResolvedTypeClass());
1454 const AbstractType& tp_argument = 1454 // Check if type argument is dynamic or Object.
1455 AbstractType::ZoneHandle(type_arguments.TypeAt(0)); 1455 const Type& object_type =
1456 if (!tp_argument.IsType()) { 1456 Type::Handle(Isolate::Current()->object_store()->object_type());
1457 // E.g., it is a TypeParameter. 1457 Error& malformed_error = Error::Handle();
1458 return SubtypeTestCache::null(); 1458 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) {
1459 } 1459 // Instance class test only necessary.
1460 // Malformed type has been caught in the caller chain of this function. 1460 return GenerateSubtype1TestCacheLookup(
1461 ASSERT(tp_argument.HasResolvedTypeClass()); 1461 node_id,
1462 // Check if type argument is dynamic or Object. 1462 token_index,
1463 const Type& object_type = 1463 type_class,
1464 Type::Handle(Isolate::Current()->object_store()->object_type()); 1464 is_instance_lbl,
1465 Error& malformed_error = Error::Handle(); 1465 is_not_instance_lbl);
1466 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) { 1466 }
1467 // Instance class test only necessary.
1468 return GenerateSubtype1TestCacheLookup(
1469 node_id, token_index, type_class, is_instance_lbl, is_not_instance_lbl);
1470 } 1467 }
1471 const SubtypeTestCache& type_test_cache = 1468 const SubtypeTestCache& type_test_cache =
1472 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); 1469 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
1473 Label inlined_check, fall_through; 1470 Label inlined_check, fall_through;
1474 const Immediate raw_null = 1471 const Immediate raw_null =
1475 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1472 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1476 __ LoadObject(EDX, type_test_cache); 1473 __ LoadObject(EDX, type_test_cache);
1477 __ pushl(EDX); // Subtype test cache. 1474 __ pushl(EDX); // Subtype test cache.
1478 __ pushl(EAX); // Instance. 1475 __ pushl(EAX); // Instance.
1479 __ pushl(raw_null); // Unused. 1476 __ pushl(raw_null); // Unused.
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1606 // EAX must be preserved! 1603 // EAX must be preserved!
1607 Label fall_through; 1604 Label fall_through;
1608 const bool kPushInstantiator = false; 1605 const bool kPushInstantiator = false;
1609 GenerateInstantiatorTypeArguments(token_index, kPushInstantiator); 1606 GenerateInstantiatorTypeArguments(token_index, kPushInstantiator);
1610 // Type arguments are on stack. 1607 // Type arguments are on stack.
1611 __ popl(EBX); 1608 __ popl(EBX);
1612 // Check if type argument is dynamic. 1609 // Check if type argument is dynamic.
1613 __ cmpl(EBX, raw_null); 1610 __ cmpl(EBX, raw_null);
1614 __ j(EQUAL, is_instance_lbl); 1611 __ j(EQUAL, is_instance_lbl);
1615 1612
1613 // EBX: instantiator type arguments.
1616 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs. 1614 // For now handle only TypeArguments and bail out if InstantiatedTypeArgs.
1615 // We expect that frequently checked objects wull have their type arguments
1616 // converted into instance of TypeArguments.
1617 __ movl(EDX, FieldAddress(EBX, Object::class_offset())); 1617 __ movl(EDX, FieldAddress(EBX, Object::class_offset()));
1618 __ CompareObject(EDX, Object::ZoneHandle(Object::type_arguments_class())); 1618 __ CompareObject(EDX, Object::ZoneHandle(Object::type_arguments_class()));
1619 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); 1619 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
1620 1620
1621 // EBX: Instance of TypeArguments.
1622 __ movl(EDX, 1621 __ movl(EDX,
1623 FieldAddress(EBX, TypeArguments::type_at_offset(type.Index()))); 1622 FieldAddress(EBX, TypeArguments::type_at_offset(type.Index())));
1624 // EDX: concrete type of type. 1623 // EDX: concrete type of type.
1625 // Check if type argument is dynamic. 1624 // Check if type argument is dynamic.
1626 __ CompareObject(EDX, Type::ZoneHandle(Type::DynamicType())); 1625 __ CompareObject(EDX, Type::ZoneHandle(Type::DynamicType()));
1627 __ j(EQUAL, is_instance_lbl); 1626 __ j(EQUAL, is_instance_lbl);
1627 __ cmpl(EDX, raw_null);
1628 __ j(EQUAL, is_instance_lbl);
1628 1629
1629 // Check if the type has type parameters, if not do the class comparison. 1630 // For Smi check quickly against int and num interfaces.
1630 Label not_smi; 1631 Label not_smi;
1631 __ testl(EAX, Immediate(kSmiTagMask)); // Value is Smi? 1632 __ testl(EAX, Immediate(kSmiTagMask)); // Value is Smi?
1632 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump); 1633 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
1633 // For Smi check quickly against int and num interfaces.
1634 __ CompareObject(EDX, Type::ZoneHandle(Type::IntInterface())); 1634 __ CompareObject(EDX, Type::ZoneHandle(Type::IntInterface()));
1635 __ j(EQUAL, is_instance_lbl); 1635 __ j(EQUAL, is_instance_lbl);
1636 __ CompareObject(EDX, Type::ZoneHandle(Type::NumberInterface())); 1636 __ CompareObject(EDX, Type::ZoneHandle(Type::NumberInterface()));
1637 __ j(EQUAL, is_instance_lbl); 1637 __ j(EQUAL, is_instance_lbl);
1638 __ jmp(&fall_through); 1638 __ jmp(&fall_through);
1639 1639
1640 __ Bind(&not_smi); 1640 __ Bind(&not_smi);
1641 // EBX: instantiator type arguments.
1642 // EAX: instance
1641 // The instantiated type parameter may not be a Type, but could be an 1643 // The instantiated type parameter may not be a Type, but could be an
1642 // InstantiatedType. It is therefore necessary to check its class. 1644 // InstantiatedType. It is therefore necessary to check its class.
1643 __ movl(ECX, FieldAddress(EDX, Object::class_offset())); 1645 const SubtypeTestCache& type_test_cache =
1644 __ CompareObject(ECX, Object::ZoneHandle(Object::type_class())); 1646 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
1645 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); 1647 __ LoadObject(ECX, type_test_cache);
1646 1648 __ pushl(ECX); // Subtype test cache.
1647 __ movl(EDX, FieldAddress(EDX, Type::type_class_offset())); 1649 __ pushl(EAX); // Instance.
1648 __ movl(ECX, FieldAddress(EDX, Class::type_parameters_offset())); 1650 __ pushl(EBX); // Instantator type arguments.
1649 // Check that class of type has no type parameters. 1651 __ call(&StubCode::Subtype3TestCacheLabel());
1652 __ popl(EDX); // Discard type arguments.
1653 __ popl(EAX); // Restore receiver.
1654 __ popl(EDX); // Discard subtype test cache.
1655 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False.
1650 __ cmpl(ECX, raw_null); 1656 __ cmpl(ECX, raw_null);
1651 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); 1657 __ j(EQUAL, &fall_through, Assembler::kNearJump);
1652 // EAX has non-parameterized class. 1658 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1653 // Check class equality 1659 __ CompareObject(ECX, bool_true);
1654 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1655 __ movl(ECX, FieldAddress(ECX, Type::type_class_offset()));
1656 __ cmpl(ECX, EDX);
1657 __ j(EQUAL, is_instance_lbl); 1660 __ j(EQUAL, is_instance_lbl);
1658 1661 __ jmp(is_not_instance_lbl);
1659 // We have a non-parameterized class in EDX, compare with class of
1660 // value in EAX. EAX, EDX are preserved in stub.
1661 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1662 __ call(&StubCode::IsRawSubTypeLabel());
1663 // Result in EBX: 1 is raw subtype.
1664 __ cmpl(EBX, Immediate(1));
1665 __ j(EQUAL, is_instance_lbl);
1666
1667 // Test not conclusive.
1668 __ Bind(&fall_through); 1662 __ Bind(&fall_through);
1669 return SubtypeTestCache::null(); 1663 return type_test_cache.raw();
1670 } 1664 }
1671 if (type.IsType()) { 1665 if (type.IsType()) {
1672 Label fall_through; 1666 Label fall_through;
1673 __ testl(EAX, Immediate(kSmiTagMask)); // Is instance Smi? 1667 __ testl(EAX, Immediate(kSmiTagMask)); // Is instance Smi?
1674 __ j(ZERO, is_not_instance_lbl, Assembler::kNearJump); 1668 __ j(ZERO, is_not_instance_lbl, Assembler::kNearJump);
1675 // Uninstantiated type class is known at compile time, but the type 1669 // Uninstantiated type class is known at compile time, but the type
1676 // arguments are determined at runtime by the instantiator. 1670 // arguments are determined at runtime by the instantiator.
1677 const SubtypeTestCache& type_test_cache = 1671 const SubtypeTestCache& type_test_cache =
1678 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); 1672 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
1679 __ LoadObject(EDX, type_test_cache); 1673 __ LoadObject(EDX, type_test_cache);
(...skipping 1278 matching lines...) Expand 10 before | Expand all | Expand 10 after
2958 const Error& error = Error::Handle( 2952 const Error& error = Error::Handle(
2959 Parser::FormatError(script, token_index, "Error", format, args)); 2953 Parser::FormatError(script, token_index, "Error", format, args));
2960 va_end(args); 2954 va_end(args);
2961 Isolate::Current()->long_jump_base()->Jump(1, error); 2955 Isolate::Current()->long_jump_base()->Jump(1, error);
2962 UNREACHABLE(); 2956 UNREACHABLE();
2963 } 2957 }
2964 2958
2965 } // namespace dart 2959 } // namespace dart
2966 2960
2967 #endif // defined TARGET_ARCH_IA32 2961 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698