| 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 // Testing against an instantiated type with no arguments, without | 186 // Testing against an instantiated type with no arguments, without |
| 186 // SubtypeTestCache. | 187 // SubtypeTestCache. |
| 187 // RAX: instance to test against (preserved). | 188 // RAX: instance to test against (preserved). |
| 188 // Clobbers R10, R13. | 189 // Clobbers R10, R13. |
| 189 // Returns true if there is a fallthrough. | 190 // Returns true if there is a fallthrough. |
| 190 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( | 191 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( |
| 191 intptr_t token_pos, | 192 intptr_t token_pos, |
| 192 const AbstractType& type, | 193 const AbstractType& type, |
| 193 Label* is_instance_lbl, | 194 Label* is_instance_lbl, |
| 194 Label* is_not_instance_lbl) { | 195 Label* is_not_instance_lbl) { |
| 196 __ Comment("InstantiatedTypeNoArgumentsTest"); |
| 195 ASSERT(type.IsInstantiated()); | 197 ASSERT(type.IsInstantiated()); |
| 196 const Class& type_class = Class::Handle(type.type_class()); | 198 const Class& type_class = Class::Handle(type.type_class()); |
| 197 ASSERT(!type_class.HasTypeArguments()); | 199 ASSERT(!type_class.HasTypeArguments()); |
| 198 | 200 |
| 199 const Register kInstanceReg = RAX; | 201 const Register kInstanceReg = RAX; |
| 200 Label compare_classes; | 202 Label compare_classes; |
| 201 __ testq(kInstanceReg, Immediate(kSmiTagMask)); | 203 __ testq(kInstanceReg, Immediate(kSmiTagMask)); |
| 202 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); | 204 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); |
| 203 // Instance is Smi, check directly. | 205 // Instance is Smi, check directly. |
| 204 const Class& smi_class = Class::Handle(Smi::Class()); | 206 const Class& smi_class = Class::Handle(Smi::Class()); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 // Clobbers R10, R13. | 258 // Clobbers R10, R13. |
| 257 // Immediate class test already done. | 259 // Immediate class test already done. |
| 258 // TODO(srdjan): Implement a quicker subtype check, as type test | 260 // TODO(srdjan): Implement a quicker subtype check, as type test |
| 259 // arrays can grow too high, but they may be useful when optimizing | 261 // arrays can grow too high, but they may be useful when optimizing |
| 260 // code (type-feedback). | 262 // code (type-feedback). |
| 261 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( | 263 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( |
| 262 intptr_t token_pos, | 264 intptr_t token_pos, |
| 263 const Class& type_class, | 265 const Class& type_class, |
| 264 Label* is_instance_lbl, | 266 Label* is_instance_lbl, |
| 265 Label* is_not_instance_lbl) { | 267 Label* is_not_instance_lbl) { |
| 268 __ Comment("Subtype1TestCacheLookup"); |
| 266 const Register kInstanceReg = RAX; | 269 const Register kInstanceReg = RAX; |
| 267 __ LoadClass(R10, kInstanceReg); | 270 __ LoadClass(R10, kInstanceReg); |
| 268 // R10: instance class. | 271 // R10: instance class. |
| 269 // Check immediate superclass equality. | 272 // Check immediate superclass equality. |
| 270 __ movq(R13, FieldAddress(R10, Class::super_type_offset())); | 273 __ movq(R13, FieldAddress(R10, Class::super_type_offset())); |
| 271 __ movq(R13, FieldAddress(R13, Type::type_class_offset())); | 274 __ movq(R13, FieldAddress(R13, Type::type_class_offset())); |
| 272 __ CompareObject(R13, type_class); | 275 __ CompareObject(R13, type_class); |
| 273 __ j(EQUAL, is_instance_lbl); | 276 __ j(EQUAL, is_instance_lbl); |
| 274 | 277 |
| 275 const Register kTypeArgumentsReg = kNoRegister; | 278 const Register kTypeArgumentsReg = kNoRegister; |
| 276 const Register kTempReg = R10; | 279 const Register kTempReg = R10; |
| 277 return GenerateCallSubtypeTestStub(kTestTypeOneArg, | 280 return GenerateCallSubtypeTestStub(kTestTypeOneArg, |
| 278 kInstanceReg, | 281 kInstanceReg, |
| 279 kTypeArgumentsReg, | 282 kTypeArgumentsReg, |
| 280 kTempReg, | 283 kTempReg, |
| 281 is_instance_lbl, | 284 is_instance_lbl, |
| 282 is_not_instance_lbl); | 285 is_not_instance_lbl); |
| 283 } | 286 } |
| 284 | 287 |
| 285 | 288 |
| 286 // Generates inlined check if 'type' is a type parameter or type itsef | 289 // Generates inlined check if 'type' is a type parameter or type itsef |
| 287 // RAX: instance (preserved). | 290 // RAX: instance (preserved). |
| 288 // Clobbers RDI, RDX, R10. | 291 // Clobbers RDI, RDX, R10. |
| 289 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( | 292 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
| 290 intptr_t token_pos, | 293 intptr_t token_pos, |
| 291 const AbstractType& type, | 294 const AbstractType& type, |
| 292 Label* is_instance_lbl, | 295 Label* is_instance_lbl, |
| 293 Label* is_not_instance_lbl) { | 296 Label* is_not_instance_lbl) { |
| 297 __ Comment("UninstantiatedTypeTest"); |
| 294 ASSERT(!type.IsInstantiated()); | 298 ASSERT(!type.IsInstantiated()); |
| 295 // Skip check if destination is a dynamic type. | 299 // Skip check if destination is a dynamic type. |
| 296 const Immediate raw_null = | 300 const Immediate raw_null = |
| 297 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 301 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 298 if (type.IsTypeParameter()) { | 302 if (type.IsTypeParameter()) { |
| 299 const TypeParameter& type_param = TypeParameter::Cast(type); | 303 const TypeParameter& type_param = TypeParameter::Cast(type); |
| 300 // Load instantiator (or null) and instantiator type arguments on stack. | 304 // Load instantiator (or null) and instantiator type arguments on stack. |
| 301 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. | 305 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. |
| 302 // RDX: instantiator type arguments. | 306 // RDX: instantiator type arguments. |
| 303 // Check if type argument is dynamic. | 307 // Check if type argument is dynamic. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 // Returns: | 379 // Returns: |
| 376 // - preserved instance in RAX and optional instantiator type arguments in RDX. | 380 // - preserved instance in RAX and optional instantiator type arguments in RDX. |
| 377 // Note that this inlined code must be followed by the runtime_call code, as it | 381 // Note that this inlined code must be followed by the runtime_call code, as it |
| 378 // may fall through to it. Otherwise, this inline code will jump to the label | 382 // may fall through to it. Otherwise, this inline code will jump to the label |
| 379 // is_instance or to the label is_not_instance. | 383 // is_instance or to the label is_not_instance. |
| 380 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( | 384 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( |
| 381 intptr_t token_pos, | 385 intptr_t token_pos, |
| 382 const AbstractType& type, | 386 const AbstractType& type, |
| 383 Label* is_instance_lbl, | 387 Label* is_instance_lbl, |
| 384 Label* is_not_instance_lbl) { | 388 Label* is_not_instance_lbl) { |
| 389 __ Comment("InlineInstanceof"); |
| 385 if (type.IsVoidType()) { | 390 if (type.IsVoidType()) { |
| 386 // A non-null value is returned from a void function, which will result in a | 391 // A non-null value is returned from a void function, which will result in a |
| 387 // type error. A null value is handled prior to executing this inline code. | 392 // type error. A null value is handled prior to executing this inline code. |
| 388 return SubtypeTestCache::null(); | 393 return SubtypeTestCache::null(); |
| 389 } | 394 } |
| 390 if (TypeCheckAsClassEquality(type)) { | 395 if (TypeCheckAsClassEquality(type)) { |
| 391 const intptr_t type_cid = Class::Handle(type.type_class()).id(); | 396 const intptr_t type_cid = Class::Handle(type.type_class()).id(); |
| 392 const Register kInstanceReg = RAX; | 397 const Register kInstanceReg = RAX; |
| 393 __ testq(kInstanceReg, Immediate(kSmiTagMask)); | 398 __ testq(kInstanceReg, Immediate(kSmiTagMask)); |
| 394 if (type_cid == kSmiCid) { | 399 if (type_cid == kSmiCid) { |
| (...skipping 1009 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1404 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1409 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
| 1405 __ Exchange(mem1, mem2); | 1410 __ Exchange(mem1, mem2); |
| 1406 } | 1411 } |
| 1407 | 1412 |
| 1408 | 1413 |
| 1409 #undef __ | 1414 #undef __ |
| 1410 | 1415 |
| 1411 } // namespace dart | 1416 } // namespace dart |
| 1412 | 1417 |
| 1413 #endif // defined TARGET_ARCH_X64 | 1418 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |