| 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_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 // type test is conclusive, otherwise fallthrough if a type test could not | 111 // type test is conclusive, otherwise fallthrough if a type test could not |
| 112 // be completed. | 112 // be completed. |
| 113 // RAX: instance (must survive). | 113 // RAX: instance (must survive). |
| 114 // Clobbers R10. | 114 // Clobbers R10. |
| 115 RawSubtypeTestCache* | 115 RawSubtypeTestCache* |
| 116 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( | 116 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( |
| 117 intptr_t token_pos, | 117 intptr_t token_pos, |
| 118 const AbstractType& type, | 118 const AbstractType& type, |
| 119 Label* is_instance_lbl, | 119 Label* is_instance_lbl, |
| 120 Label* is_not_instance_lbl) { | 120 Label* is_not_instance_lbl) { |
| 121 __ Comment("InstantiatedTypeWithArgumentsTest"); |
| 121 ASSERT(type.IsInstantiated()); | 122 ASSERT(type.IsInstantiated()); |
| 122 const Class& type_class = Class::ZoneHandle(type.type_class()); | 123 const Class& type_class = Class::ZoneHandle(type.type_class()); |
| 123 ASSERT(type_class.HasTypeArguments()); | 124 ASSERT(type_class.HasTypeArguments()); |
| 124 const Register kInstanceReg = RAX; | 125 const Register kInstanceReg = RAX; |
| 125 // A Smi object cannot be the instance of a parameterized class. | 126 // A Smi object cannot be the instance of a parameterized class. |
| 126 __ testq(kInstanceReg, Immediate(kSmiTagMask)); | 127 __ testq(kInstanceReg, Immediate(kSmiTagMask)); |
| 127 __ j(ZERO, is_not_instance_lbl); | 128 __ j(ZERO, is_not_instance_lbl); |
| 128 const AbstractTypeArguments& type_arguments = | 129 const AbstractTypeArguments& type_arguments = |
| 129 AbstractTypeArguments::ZoneHandle(type.arguments()); | 130 AbstractTypeArguments::ZoneHandle(type.arguments()); |
| 130 const bool is_raw_type = type_arguments.IsNull() || | 131 const bool is_raw_type = type_arguments.IsNull() || |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 // Testing against an instantiated type with no arguments, without | 188 // Testing against an instantiated type with no arguments, without |
| 188 // SubtypeTestCache. | 189 // SubtypeTestCache. |
| 189 // RAX: instance to test against (preserved). | 190 // RAX: instance to test against (preserved). |
| 190 // Clobbers R10, R13. | 191 // Clobbers R10, R13. |
| 191 // Returns true if there is a fallthrough. | 192 // Returns true if there is a fallthrough. |
| 192 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( | 193 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( |
| 193 intptr_t token_pos, | 194 intptr_t token_pos, |
| 194 const AbstractType& type, | 195 const AbstractType& type, |
| 195 Label* is_instance_lbl, | 196 Label* is_instance_lbl, |
| 196 Label* is_not_instance_lbl) { | 197 Label* is_not_instance_lbl) { |
| 198 __ Comment("InstantiatedTypeNoArgumentsTest"); |
| 197 ASSERT(type.IsInstantiated()); | 199 ASSERT(type.IsInstantiated()); |
| 198 const Class& type_class = Class::Handle(type.type_class()); | 200 const Class& type_class = Class::Handle(type.type_class()); |
| 199 ASSERT(!type_class.HasTypeArguments()); | 201 ASSERT(!type_class.HasTypeArguments()); |
| 200 | 202 |
| 201 const Register kInstanceReg = RAX; | 203 const Register kInstanceReg = RAX; |
| 202 Label compare_classes; | 204 Label compare_classes; |
| 203 __ testq(kInstanceReg, Immediate(kSmiTagMask)); | 205 __ testq(kInstanceReg, Immediate(kSmiTagMask)); |
| 204 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); | 206 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); |
| 205 // Instance is Smi, check directly. | 207 // Instance is Smi, check directly. |
| 206 const Class& smi_class = Class::Handle(Smi::Class()); | 208 const Class& smi_class = Class::Handle(Smi::Class()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 // Clobbers R10, R13. | 263 // Clobbers R10, R13. |
| 262 // Immediate class test already done. | 264 // Immediate class test already done. |
| 263 // TODO(srdjan): Implement a quicker subtype check, as type test | 265 // TODO(srdjan): Implement a quicker subtype check, as type test |
| 264 // arrays can grow too high, but they may be useful when optimizing | 266 // arrays can grow too high, but they may be useful when optimizing |
| 265 // code (type-feedback). | 267 // code (type-feedback). |
| 266 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( | 268 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( |
| 267 intptr_t token_pos, | 269 intptr_t token_pos, |
| 268 const Class& type_class, | 270 const Class& type_class, |
| 269 Label* is_instance_lbl, | 271 Label* is_instance_lbl, |
| 270 Label* is_not_instance_lbl) { | 272 Label* is_not_instance_lbl) { |
| 273 __ Comment("Subtype1TestCacheLookup"); |
| 271 const Register kInstanceReg = RAX; | 274 const Register kInstanceReg = RAX; |
| 272 __ LoadClass(R10, kInstanceReg); | 275 __ LoadClass(R10, kInstanceReg); |
| 273 // R10: instance class. | 276 // R10: instance class. |
| 274 // Check immediate superclass equality. | 277 // Check immediate superclass equality. |
| 275 __ movq(R13, FieldAddress(R10, Class::super_type_offset())); | 278 __ movq(R13, FieldAddress(R10, Class::super_type_offset())); |
| 276 __ movq(R13, FieldAddress(R13, Type::type_class_offset())); | 279 __ movq(R13, FieldAddress(R13, Type::type_class_offset())); |
| 277 __ CompareObject(R13, type_class); | 280 __ CompareObject(R13, type_class); |
| 278 __ j(EQUAL, is_instance_lbl); | 281 __ j(EQUAL, is_instance_lbl); |
| 279 | 282 |
| 280 const Register kTypeArgumentsReg = kNoRegister; | 283 const Register kTypeArgumentsReg = kNoRegister; |
| 281 const Register kTempReg = R10; | 284 const Register kTempReg = R10; |
| 282 return GenerateCallSubtypeTestStub(kTestTypeOneArg, | 285 return GenerateCallSubtypeTestStub(kTestTypeOneArg, |
| 283 kInstanceReg, | 286 kInstanceReg, |
| 284 kTypeArgumentsReg, | 287 kTypeArgumentsReg, |
| 285 kTempReg, | 288 kTempReg, |
| 286 is_instance_lbl, | 289 is_instance_lbl, |
| 287 is_not_instance_lbl); | 290 is_not_instance_lbl); |
| 288 } | 291 } |
| 289 | 292 |
| 290 | 293 |
| 291 // Generates inlined check if 'type' is a type parameter or type itsef | 294 // Generates inlined check if 'type' is a type parameter or type itsef |
| 292 // RAX: instance (preserved). | 295 // RAX: instance (preserved). |
| 293 // Clobbers RDI, RDX, R10. | 296 // Clobbers RDI, RDX, R10. |
| 294 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( | 297 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
| 295 intptr_t token_pos, | 298 intptr_t token_pos, |
| 296 const AbstractType& type, | 299 const AbstractType& type, |
| 297 Label* is_instance_lbl, | 300 Label* is_instance_lbl, |
| 298 Label* is_not_instance_lbl) { | 301 Label* is_not_instance_lbl) { |
| 302 __ Comment("UninstantiatedTypeTest"); |
| 299 ASSERT(!type.IsInstantiated()); | 303 ASSERT(!type.IsInstantiated()); |
| 300 // Skip check if destination is a dynamic type. | 304 // Skip check if destination is a dynamic type. |
| 301 const Immediate raw_null = | 305 const Immediate raw_null = |
| 302 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 306 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 303 if (type.IsTypeParameter()) { | 307 if (type.IsTypeParameter()) { |
| 304 const TypeParameter& type_param = TypeParameter::Cast(type); | 308 const TypeParameter& type_param = TypeParameter::Cast(type); |
| 305 // Load instantiator (or null) and instantiator type arguments on stack. | 309 // Load instantiator (or null) and instantiator type arguments on stack. |
| 306 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. | 310 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. |
| 307 // RDX: instantiator type arguments. | 311 // RDX: instantiator type arguments. |
| 308 // Check if type argument is dynamic. | 312 // Check if type argument is dynamic. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 // Returns: | 384 // Returns: |
| 381 // - preserved instance in RAX and optional instantiator type arguments in RDX. | 385 // - preserved instance in RAX and optional instantiator type arguments in RDX. |
| 382 // Note that this inlined code must be followed by the runtime_call code, as it | 386 // Note that this inlined code must be followed by the runtime_call code, as it |
| 383 // may fall through to it. Otherwise, this inline code will jump to the label | 387 // may fall through to it. Otherwise, this inline code will jump to the label |
| 384 // is_instance or to the label is_not_instance. | 388 // is_instance or to the label is_not_instance. |
| 385 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( | 389 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( |
| 386 intptr_t token_pos, | 390 intptr_t token_pos, |
| 387 const AbstractType& type, | 391 const AbstractType& type, |
| 388 Label* is_instance_lbl, | 392 Label* is_instance_lbl, |
| 389 Label* is_not_instance_lbl) { | 393 Label* is_not_instance_lbl) { |
| 394 __ Comment("InlineInstanceof"); |
| 390 if (type.IsVoidType()) { | 395 if (type.IsVoidType()) { |
| 391 // A non-null value is returned from a void function, which will result in a | 396 // A non-null value is returned from a void function, which will result in a |
| 392 // type error. A null value is handled prior to executing this inline code. | 397 // type error. A null value is handled prior to executing this inline code. |
| 393 return SubtypeTestCache::null(); | 398 return SubtypeTestCache::null(); |
| 394 } | 399 } |
| 395 if (type.IsInstantiated()) { | 400 if (type.IsInstantiated()) { |
| 396 const Class& type_class = Class::ZoneHandle(type.type_class()); | 401 const Class& type_class = Class::ZoneHandle(type.type_class()); |
| 397 // A Smi object cannot be the instance of a parameterized class. | 402 // A Smi object cannot be the instance of a parameterized class. |
| 398 // A class equality check is only applicable with a dst type of a | 403 // A class equality check is only applicable with a dst type of a |
| 399 // non-parameterized class or with a raw dst type of a parameterized class. | 404 // non-parameterized class or with a raw dst type of a parameterized class. |
| (...skipping 977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1377 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1382 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
| 1378 __ Exchange(mem1, mem2); | 1383 __ Exchange(mem1, mem2); |
| 1379 } | 1384 } |
| 1380 | 1385 |
| 1381 | 1386 |
| 1382 #undef __ | 1387 #undef __ |
| 1383 | 1388 |
| 1384 } // namespace dart | 1389 } // namespace dart |
| 1385 | 1390 |
| 1386 #endif // defined TARGET_ARCH_X64 | 1391 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |