| 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 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 cid, token_pos, type_class, is_instance_lbl, is_not_instance_lbl); | 140 cid, token_pos, type_class, is_instance_lbl, is_not_instance_lbl); |
| 141 } | 141 } |
| 142 // If one type argument only, check if type argument is Object or Dynamic. | 142 // If one type argument only, check if type argument is Object or Dynamic. |
| 143 if (type_arguments.Length() == 1) { | 143 if (type_arguments.Length() == 1) { |
| 144 const AbstractType& tp_argument = AbstractType::ZoneHandle( | 144 const AbstractType& tp_argument = AbstractType::ZoneHandle( |
| 145 type_arguments.TypeAt(0)); | 145 type_arguments.TypeAt(0)); |
| 146 ASSERT(!tp_argument.IsMalformed()); | 146 ASSERT(!tp_argument.IsMalformed()); |
| 147 if (tp_argument.IsType()) { | 147 if (tp_argument.IsType()) { |
| 148 ASSERT(tp_argument.HasResolvedTypeClass()); | 148 ASSERT(tp_argument.HasResolvedTypeClass()); |
| 149 // Check if type argument is dynamic or Object. | 149 // Check if type argument is dynamic or Object. |
| 150 const Type& object_type = | 150 const Type& object_type = Type::Handle(Type::ObjectType()); |
| 151 Type::Handle(Isolate::Current()->object_store()->object_type()); | |
| 152 Error& malformed_error = Error::Handle(); | 151 Error& malformed_error = Error::Handle(); |
| 153 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) { | 152 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) { |
| 154 // Instance class test only necessary. | 153 // Instance class test only necessary. |
| 155 return GenerateSubtype1TestCacheLookup( | 154 return GenerateSubtype1TestCacheLookup( |
| 156 cid, token_pos, type_class, is_instance_lbl, is_not_instance_lbl); | 155 cid, token_pos, type_class, is_instance_lbl, is_not_instance_lbl); |
| 157 } | 156 } |
| 158 } | 157 } |
| 159 } | 158 } |
| 160 | 159 |
| 161 // Regular subtype test cache involving instance's type arguments. | 160 // Regular subtype test cache involving instance's type arguments. |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 __ CompareClassId(RDX, kTypeArguments); | 308 __ CompareClassId(RDX, kTypeArguments); |
| 310 __ j(NOT_EQUAL, &fall_through); | 309 __ j(NOT_EQUAL, &fall_through); |
| 311 __ movq(RDI, | 310 __ movq(RDI, |
| 312 FieldAddress(RDX, TypeArguments::type_at_offset(type.Index()))); | 311 FieldAddress(RDX, TypeArguments::type_at_offset(type.Index()))); |
| 313 // RDI: Concrete type. | 312 // RDI: Concrete type. |
| 314 // Check if it is Dynamic, | 313 // Check if it is Dynamic, |
| 315 __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType())); | 314 __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType())); |
| 316 __ j(EQUAL, is_instance_lbl); | 315 __ j(EQUAL, is_instance_lbl); |
| 317 __ cmpq(RDI, raw_null); | 316 __ cmpq(RDI, raw_null); |
| 318 __ j(EQUAL, is_instance_lbl); | 317 __ j(EQUAL, is_instance_lbl); |
| 319 const Type& object_type = | 318 const Type& object_type = Type::ZoneHandle(Type::ObjectType()); |
| 320 Type::ZoneHandle(Isolate::Current()->object_store()->object_type()); | |
| 321 __ CompareObject(RDI, object_type); | 319 __ CompareObject(RDI, object_type); |
| 322 __ j(EQUAL, is_instance_lbl); | 320 __ j(EQUAL, is_instance_lbl); |
| 323 | 321 |
| 324 // For Smi check quickly against int and num interface types. | 322 // For Smi check quickly against int and num interface types. |
| 325 Label not_smi; | 323 Label not_smi; |
| 326 __ testq(RAX, Immediate(kSmiTagMask)); // Value is Smi? | 324 __ testq(RAX, Immediate(kSmiTagMask)); // Value is Smi? |
| 327 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); | 325 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); |
| 328 __ CompareObject(RDI, Type::ZoneHandle(Type::IntInterface())); | 326 __ CompareObject(RDI, Type::ZoneHandle(Type::IntInterface())); |
| 329 __ j(EQUAL, is_instance_lbl); | 327 __ j(EQUAL, is_instance_lbl); |
| 330 __ CompareObject(RDI, Type::ZoneHandle(Type::NumberInterface())); | 328 __ CompareObject(RDI, Type::ZoneHandle(Type::NumberInterface())); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 // - RCX: instantiator or raw_null. | 428 // - RCX: instantiator or raw_null. |
| 431 // Returns: | 429 // Returns: |
| 432 // - object in RAX for successful assignable check (or throws TypeError). | 430 // - object in RAX for successful assignable check (or throws TypeError). |
| 433 // Performance notes: positive checks must be quick, negative checks can be slow | 431 // Performance notes: positive checks must be quick, negative checks can be slow |
| 434 // as they throw an exception. | 432 // as they throw an exception. |
| 435 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t cid, | 433 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t cid, |
| 436 intptr_t token_pos, | 434 intptr_t token_pos, |
| 437 intptr_t try_index, | 435 intptr_t try_index, |
| 438 const AbstractType& dst_type, | 436 const AbstractType& dst_type, |
| 439 const String& dst_name) { | 437 const String& dst_name) { |
| 440 ASSERT(FLAG_enable_type_checks); | |
| 441 ASSERT(token_pos >= 0); | 438 ASSERT(token_pos >= 0); |
| 442 ASSERT(!dst_type.IsNull()); | 439 ASSERT(!dst_type.IsNull()); |
| 443 ASSERT(dst_type.IsFinalized()); | 440 ASSERT(dst_type.IsFinalized()); |
| 444 // Assignable check is skipped in FlowGraphBuilder, not here. | 441 // Assignable check is skipped in FlowGraphBuilder, not here. |
| 445 ASSERT(dst_type.IsMalformed() || | 442 ASSERT(dst_type.IsMalformed() || |
| 446 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); | 443 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); |
| 447 ASSERT(!dst_type.IsVoidType()); | 444 ASSERT(!dst_type.IsVoidType()); |
| 448 __ pushq(RCX); // Store instantiator. | 445 __ pushq(RCX); // Store instantiator. |
| 449 __ pushq(RDX); // Store instantiator type arguments. | 446 __ pushq(RDX); // Store instantiator type arguments. |
| 450 // A null object is always assignable and is returned as result. | 447 // A null object is always assignable and is returned as result. |
| (...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1068 __ cvtsi2sd(result, temp); | 1065 __ cvtsi2sd(result, temp); |
| 1069 __ Bind(&done); | 1066 __ Bind(&done); |
| 1070 } | 1067 } |
| 1071 | 1068 |
| 1072 | 1069 |
| 1073 #undef __ | 1070 #undef __ |
| 1074 | 1071 |
| 1075 } // namespace dart | 1072 } // namespace dart |
| 1076 | 1073 |
| 1077 #endif // defined TARGET_ARCH_X64 | 1074 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |