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/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 const Register kInstanceReg = EAX; | 126 const Register kInstanceReg = EAX; |
127 // A Smi object cannot be the instance of a parameterized class. | 127 // A Smi object cannot be the instance of a parameterized class. |
128 __ testl(kInstanceReg, Immediate(kSmiTagMask)); | 128 __ testl(kInstanceReg, Immediate(kSmiTagMask)); |
129 __ j(ZERO, is_not_instance_lbl); | 129 __ j(ZERO, is_not_instance_lbl); |
130 const AbstractTypeArguments& type_arguments = | 130 const AbstractTypeArguments& type_arguments = |
131 AbstractTypeArguments::ZoneHandle(type.arguments()); | 131 AbstractTypeArguments::ZoneHandle(type.arguments()); |
132 const bool is_raw_type = type_arguments.IsNull() || | 132 const bool is_raw_type = type_arguments.IsNull() || |
133 type_arguments.IsRaw(type_arguments.Length()); | 133 type_arguments.IsRaw(type_arguments.Length()); |
134 if (is_raw_type) { | 134 if (is_raw_type) { |
135 const Register kClassIdReg = ECX; | 135 const Register kClassIdReg = ECX; |
136 // Dynamic type argument, check only classes. | 136 // dynamic type argument, check only classes. |
137 // List is a very common case. | 137 // List is a very common case. |
138 __ LoadClassId(kClassIdReg, kInstanceReg); | 138 __ LoadClassId(kClassIdReg, kInstanceReg); |
139 if (!type_class.is_interface()) { | 139 if (!type_class.is_interface()) { |
140 __ cmpl(kClassIdReg, Immediate(type_class.id())); | 140 __ cmpl(kClassIdReg, Immediate(type_class.id())); |
141 __ j(EQUAL, is_instance_lbl); | 141 __ j(EQUAL, is_instance_lbl); |
142 } | 142 } |
143 if (type.IsListInterface()) { | 143 if (type.IsListInterface()) { |
144 GenerateListTypeCheck(kClassIdReg, is_instance_lbl); | 144 GenerateListTypeCheck(kClassIdReg, is_instance_lbl); |
145 } | 145 } |
146 return GenerateSubtype1TestCacheLookup( | 146 return GenerateSubtype1TestCacheLookup( |
147 token_pos, type_class, is_instance_lbl, is_not_instance_lbl); | 147 token_pos, type_class, is_instance_lbl, is_not_instance_lbl); |
148 } | 148 } |
149 // If one type argument only, check if type argument is Object or Dynamic. | 149 // If one type argument only, check if type argument is Object or dynamic. |
150 if (type_arguments.Length() == 1) { | 150 if (type_arguments.Length() == 1) { |
151 const AbstractType& tp_argument = AbstractType::ZoneHandle( | 151 const AbstractType& tp_argument = AbstractType::ZoneHandle( |
152 type_arguments.TypeAt(0)); | 152 type_arguments.TypeAt(0)); |
153 ASSERT(!tp_argument.IsMalformed()); | 153 ASSERT(!tp_argument.IsMalformed()); |
154 if (tp_argument.IsType()) { | 154 if (tp_argument.IsType()) { |
155 ASSERT(tp_argument.HasResolvedTypeClass()); | 155 ASSERT(tp_argument.HasResolvedTypeClass()); |
156 // Check if type argument is dynamic or Object. | 156 // Check if type argument is dynamic or Object. |
157 const Type& object_type = Type::Handle(Type::ObjectType()); | 157 const Type& object_type = Type::Handle(Type::ObjectType()); |
158 if (object_type.IsSubtypeOf(tp_argument, NULL)) { | 158 if (object_type.IsSubtypeOf(tp_argument, NULL)) { |
159 // Instance class test only necessary. | 159 // Instance class test only necessary. |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 Label* is_not_instance_lbl) { | 300 Label* is_not_instance_lbl) { |
301 ASSERT(!type.IsInstantiated()); | 301 ASSERT(!type.IsInstantiated()); |
302 // Skip check if destination is a dynamic type. | 302 // Skip check if destination is a dynamic type. |
303 const Immediate raw_null = | 303 const Immediate raw_null = |
304 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 304 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
305 if (type.IsTypeParameter()) { | 305 if (type.IsTypeParameter()) { |
306 const TypeParameter& type_param = TypeParameter::Cast(type); | 306 const TypeParameter& type_param = TypeParameter::Cast(type); |
307 // Load instantiator (or null) and instantiator type arguments on stack. | 307 // Load instantiator (or null) and instantiator type arguments on stack. |
308 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. | 308 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. |
309 // EDX: instantiator type arguments. | 309 // EDX: instantiator type arguments. |
310 // Check if type argument is Dynamic. | 310 // Check if type argument is dynamic. |
311 __ cmpl(EDX, raw_null); | 311 __ cmpl(EDX, raw_null); |
312 __ j(EQUAL, is_instance_lbl); | 312 __ j(EQUAL, is_instance_lbl); |
313 // Can handle only type arguments that are instances of TypeArguments. | 313 // Can handle only type arguments that are instances of TypeArguments. |
314 // (runtime checks canonicalize type arguments). | 314 // (runtime checks canonicalize type arguments). |
315 Label fall_through; | 315 Label fall_through; |
316 __ CompareClassId(EDX, kTypeArgumentsCid, EDI); | 316 __ CompareClassId(EDX, kTypeArgumentsCid, EDI); |
317 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); | 317 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); |
318 __ movl(EDI, | 318 __ movl(EDI, |
319 FieldAddress(EDX, TypeArguments::type_at_offset(type_param.index()))); | 319 FieldAddress(EDX, TypeArguments::type_at_offset(type_param.index()))); |
320 // EDI: concrete type of type. | 320 // EDI: concrete type of type. |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 ASSERT(type.IsFinalized() && !type.IsMalformed()); | 446 ASSERT(type.IsFinalized() && !type.IsMalformed()); |
447 | 447 |
448 const Immediate raw_null = | 448 const Immediate raw_null = |
449 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 449 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
450 Label is_instance, is_not_instance; | 450 Label is_instance, is_not_instance; |
451 __ pushl(ECX); // Store instantiator on stack. | 451 __ pushl(ECX); // Store instantiator on stack. |
452 __ pushl(EDX); // Store instantiator type arguments. | 452 __ pushl(EDX); // Store instantiator type arguments. |
453 // If type is instantiated and non-parameterized, we can inline code | 453 // If type is instantiated and non-parameterized, we can inline code |
454 // checking whether the tested instance is a Smi. | 454 // checking whether the tested instance is a Smi. |
455 if (type.IsInstantiated()) { | 455 if (type.IsInstantiated()) { |
456 // A null object is only an instance of Object and Dynamic, which has | 456 // A null object is only an instance of Object and dynamic, which has |
457 // already been checked above (if the type is instantiated). So we can | 457 // already been checked above (if the type is instantiated). So we can |
458 // return false here if the instance is null (and if the type is | 458 // return false here if the instance is null (and if the type is |
459 // instantiated). | 459 // instantiated). |
460 // We can only inline this null check if the type is instantiated at compile | 460 // We can only inline this null check if the type is instantiated at compile |
461 // time, since an uninstantiated type at compile time could be Object or | 461 // time, since an uninstantiated type at compile time could be Object or |
462 // Dynamic at run time. | 462 // dynamic at run time. |
463 __ cmpl(EAX, raw_null); | 463 __ cmpl(EAX, raw_null); |
464 __ j(EQUAL, &is_not_instance); | 464 __ j(EQUAL, &is_not_instance); |
465 } | 465 } |
466 | 466 |
467 // Generate inline instanceof test. | 467 // Generate inline instanceof test. |
468 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); | 468 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); |
469 test_cache = GenerateInlineInstanceof(token_pos, type, | 469 test_cache = GenerateInlineInstanceof(token_pos, type, |
470 &is_instance, &is_not_instance); | 470 &is_instance, &is_not_instance); |
471 | 471 |
472 // test_cache is null if there is no fall-through. | 472 // test_cache is null if there is no fall-through. |
(...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1359 __ popl(ECX); | 1359 __ popl(ECX); |
1360 __ popl(EAX); | 1360 __ popl(EAX); |
1361 } | 1361 } |
1362 | 1362 |
1363 | 1363 |
1364 #undef __ | 1364 #undef __ |
1365 | 1365 |
1366 } // namespace dart | 1366 } // namespace dart |
1367 | 1367 |
1368 #endif // defined TARGET_ARCH_IA32 | 1368 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |