| 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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 // A Smi object cannot be the instance of a parameterized class. | 117 // A Smi object cannot be the instance of a parameterized class. |
| 118 __ testq(RAX, Immediate(kSmiTagMask)); | 118 __ testq(RAX, Immediate(kSmiTagMask)); |
| 119 __ j(ZERO, is_not_instance_lbl); | 119 __ j(ZERO, is_not_instance_lbl); |
| 120 const AbstractTypeArguments& type_arguments = | 120 const AbstractTypeArguments& type_arguments = |
| 121 AbstractTypeArguments::ZoneHandle(type.arguments()); | 121 AbstractTypeArguments::ZoneHandle(type.arguments()); |
| 122 const bool is_raw_type = type_arguments.IsNull() || | 122 const bool is_raw_type = type_arguments.IsNull() || |
| 123 type_arguments.IsRaw(type_arguments.Length()); | 123 type_arguments.IsRaw(type_arguments.Length()); |
| 124 if (is_raw_type) { | 124 if (is_raw_type) { |
| 125 // Dynamic type argument, check only classes. | 125 // Dynamic type argument, check only classes. |
| 126 // List is a very common case. | 126 // List is a very common case. |
| 127 __ movq(R10, FieldAddress(RAX, Object::class_offset())); | 127 __ GetClassOf(R10, RAX); |
| 128 if (!type_class.is_interface()) { | 128 if (!type_class.is_interface()) { |
| 129 __ CompareObject(R10, type_class); | 129 __ CompareObject(R10, type_class); |
| 130 __ j(EQUAL, is_instance_lbl); | 130 __ j(EQUAL, is_instance_lbl); |
| 131 } | 131 } |
| 132 if (type.IsListInterface()) { | 132 if (type.IsListInterface()) { |
| 133 Label unknown; | 133 Label unknown; |
| 134 GrowableArray<const Class*> args; | 134 GrowableArray<const Class*> args; |
| 135 args.Add(CoreClass("ObjectArray")); | 135 args.Add(CoreClass("ObjectArray")); |
| 136 args.Add(CoreClass("GrowableObjectArray")); | 136 args.Add(CoreClass("GrowableObjectArray")); |
| 137 args.Add(CoreClass("ImmutableArray")); | 137 args.Add(CoreClass("ImmutableArray")); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 TypeArguments::Handle(), | 225 TypeArguments::Handle(), |
| 226 &malformed_error)) { | 226 &malformed_error)) { |
| 227 __ jmp(is_instance_lbl); | 227 __ jmp(is_instance_lbl); |
| 228 } else { | 228 } else { |
| 229 __ jmp(is_not_instance_lbl); | 229 __ jmp(is_not_instance_lbl); |
| 230 } | 230 } |
| 231 | 231 |
| 232 ObjectStore* object_store = Isolate::Current()->object_store(); | 232 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 233 // Compare if the classes are equal. Instance is not Smi. | 233 // Compare if the classes are equal. Instance is not Smi. |
| 234 __ Bind(&compare_classes); | 234 __ Bind(&compare_classes); |
| 235 __ movq(R10, FieldAddress(RAX, Object::class_offset())); | 235 __ GetClassOf(R10, RAX); |
| 236 // If type is an interface, we can skip the class equality check. | 236 // If type is an interface, we can skip the class equality check. |
| 237 if (!type_class.is_interface()) { | 237 if (!type_class.is_interface()) { |
| 238 __ CompareObject(R10, type_class); | 238 __ CompareObject(R10, type_class); |
| 239 __ j(EQUAL, is_instance_lbl); | 239 __ j(EQUAL, is_instance_lbl); |
| 240 } | 240 } |
| 241 // Check for interfaces that cannot be implemented by user. | 241 // Check for interfaces that cannot be implemented by user. |
| 242 // (see ClassFinalizer::ResolveInterfaces for list of restricted interfaces). | 242 // (see ClassFinalizer::ResolveInterfaces for list of restricted interfaces). |
| 243 // Bool interface can be implemented only by core class Bool. | 243 // Bool interface can be implemented only by core class Bool. |
| 244 if (type.IsBoolInterface()) { | 244 if (type.IsBoolInterface()) { |
| 245 const Class& bool_class = Class::ZoneHandle(object_store->bool_class()); | 245 const Class& bool_class = Class::ZoneHandle(object_store->bool_class()); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 intptr_t cid, | 313 intptr_t cid, |
| 314 intptr_t token_index, | 314 intptr_t token_index, |
| 315 const Class& type_class, | 315 const Class& type_class, |
| 316 Label* is_instance_lbl, | 316 Label* is_instance_lbl, |
| 317 Label* is_not_instance_lbl) { | 317 Label* is_not_instance_lbl) { |
| 318 const SubtypeTestCache& type_test_cache = | 318 const SubtypeTestCache& type_test_cache = |
| 319 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); | 319 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
| 320 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 320 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
| 321 const Immediate raw_null = | 321 const Immediate raw_null = |
| 322 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 322 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 323 __ movq(R10, FieldAddress(RAX, Object::class_offset())); | 323 __ GetClassOf(R10, RAX); |
| 324 // Check immediate superclass equality. | 324 // Check immediate superclass equality. |
| 325 __ movq(R13, FieldAddress(R10, Class::super_type_offset())); | 325 __ movq(R13, FieldAddress(R10, Class::super_type_offset())); |
| 326 __ movq(R13, FieldAddress(R13, Type::type_class_offset())); | 326 __ movq(R13, FieldAddress(R13, Type::type_class_offset())); |
| 327 __ CompareObject(R13, type_class); | 327 __ CompareObject(R13, type_class); |
| 328 __ j(EQUAL, is_instance_lbl); | 328 __ j(EQUAL, is_instance_lbl); |
| 329 | 329 |
| 330 __ LoadObject(R10, type_test_cache); | 330 __ LoadObject(R10, type_test_cache); |
| 331 __ pushq(R10); // Cache array. | 331 __ pushq(R10); // Cache array. |
| 332 __ pushq(RAX); // Instance. | 332 __ pushq(RAX); // Instance. |
| 333 __ pushq(raw_null); // Unused | 333 __ pushq(raw_null); // Unused |
| (...skipping 28 matching lines...) Expand all Loading... |
| 362 if (type.IsTypeParameter()) { | 362 if (type.IsTypeParameter()) { |
| 363 // Load instantiator (or null) and instantiator type arguments on stack. | 363 // Load instantiator (or null) and instantiator type arguments on stack. |
| 364 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. | 364 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. |
| 365 // RDX: instantiator type arguments. | 365 // RDX: instantiator type arguments. |
| 366 // Check if type argument is Dynamic. | 366 // Check if type argument is Dynamic. |
| 367 __ cmpq(RDX, raw_null); | 367 __ cmpq(RDX, raw_null); |
| 368 __ j(EQUAL, is_instance_lbl); | 368 __ j(EQUAL, is_instance_lbl); |
| 369 // Can handle only type arguments that are instances of TypeArguments. | 369 // Can handle only type arguments that are instances of TypeArguments. |
| 370 // (runtime checks canonicalize type arguments). | 370 // (runtime checks canonicalize type arguments). |
| 371 Label fall_through; | 371 Label fall_through; |
| 372 __ movq(R10, FieldAddress(RDX, Object::class_offset())); | 372 __ GetClassOf(R10, RDX); |
| 373 __ CompareObject(R10, Object::ZoneHandle(Object::type_arguments_class())); | 373 __ CompareObject(R10, Object::ZoneHandle(Object::type_arguments_class())); |
| 374 __ j(NOT_EQUAL, &fall_through); | 374 __ j(NOT_EQUAL, &fall_through); |
| 375 __ movq(RDI, | 375 __ movq(RDI, |
| 376 FieldAddress(RDX, TypeArguments::type_at_offset(type.Index()))); | 376 FieldAddress(RDX, TypeArguments::type_at_offset(type.Index()))); |
| 377 // RDI: Concrete type. | 377 // RDI: Concrete type. |
| 378 // Check if it is Dynamic, | 378 // Check if it is Dynamic, |
| 379 __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType())); | 379 __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType())); |
| 380 __ j(EQUAL, is_instance_lbl); | 380 __ j(EQUAL, is_instance_lbl); |
| 381 __ cmpq(RDI, raw_null); | 381 __ cmpq(RDI, raw_null); |
| 382 __ j(EQUAL, is_instance_lbl); | 382 __ j(EQUAL, is_instance_lbl); |
| (...skipping 755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1138 __ cmpq(RAX, raw_null); | 1138 __ cmpq(RAX, raw_null); |
| 1139 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1139 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1140 } | 1140 } |
| 1141 // Instantiate non-null type arguments. | 1141 // Instantiate non-null type arguments. |
| 1142 if (comp->type_arguments().IsUninstantiatedIdentity()) { | 1142 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 1143 Label type_arguments_uninstantiated; | 1143 Label type_arguments_uninstantiated; |
| 1144 // Check if the instantiator type argument vector is a TypeArguments of a | 1144 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1145 // matching length and, if so, use it as the instantiated type_arguments. | 1145 // matching length and, if so, use it as the instantiated type_arguments. |
| 1146 // No need to check the instantiator (RAX) for null here, because a null | 1146 // No need to check the instantiator (RAX) for null here, because a null |
| 1147 // instantiator will have the wrong class (Null instead of TypeArguments). | 1147 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 1148 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 1148 __ GetClassOf(R10, RAX); |
| 1149 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 1149 __ CompareObject(R10, Class::ZoneHandle(Object::type_arguments_class())); |
| 1150 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1150 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 1151 Immediate arguments_length = | 1151 Immediate arguments_length = |
| 1152 Immediate(Smi::RawValue(comp->type_arguments().Length())); | 1152 Immediate(Smi::RawValue(comp->type_arguments().Length())); |
| 1153 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 1153 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 1154 arguments_length); | 1154 arguments_length); |
| 1155 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1155 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1156 __ Bind(&type_arguments_uninstantiated); | 1156 __ Bind(&type_arguments_uninstantiated); |
| 1157 } | 1157 } |
| 1158 // A runtime call to instantiate the type arguments is required. | 1158 // A runtime call to instantiate the type arguments is required. |
| 1159 __ PushObject(Object::ZoneHandle()); // Make room for the result. | 1159 __ PushObject(Object::ZoneHandle()); // Make room for the result. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1187 __ cmpq(RAX, raw_null); | 1187 __ cmpq(RAX, raw_null); |
| 1188 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1188 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1189 } | 1189 } |
| 1190 // Instantiate non-null type arguments. | 1190 // Instantiate non-null type arguments. |
| 1191 if (comp->type_arguments().IsUninstantiatedIdentity()) { | 1191 if (comp->type_arguments().IsUninstantiatedIdentity()) { |
| 1192 // Check if the instantiator type argument vector is a TypeArguments of a | 1192 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1193 // matching length and, if so, use it as the instantiated type_arguments. | 1193 // matching length and, if so, use it as the instantiated type_arguments. |
| 1194 // No need to check the instantiator (RAX) for null here, because a null | 1194 // No need to check the instantiator (RAX) for null here, because a null |
| 1195 // instantiator will have the wrong class (Null instead of TypeArguments). | 1195 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 1196 Label type_arguments_uninstantiated; | 1196 Label type_arguments_uninstantiated; |
| 1197 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 1197 __ GetClassOf(R10, RAX); |
| 1198 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 1198 __ CompareObject(R10, Class::ZoneHandle(Object::type_arguments_class())); |
| 1199 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); | 1199 __ j(NOT_EQUAL, &type_arguments_uninstantiated, Assembler::kNearJump); |
| 1200 Immediate arguments_length = | 1200 Immediate arguments_length = |
| 1201 Immediate(Smi::RawValue(comp->type_arguments().Length())); | 1201 Immediate(Smi::RawValue(comp->type_arguments().Length())); |
| 1202 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 1202 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 1203 arguments_length); | 1203 arguments_length); |
| 1204 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 1204 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 1205 __ Bind(&type_arguments_uninstantiated); | 1205 __ Bind(&type_arguments_uninstantiated); |
| 1206 } | 1206 } |
| 1207 // In the non-factory case, we rely on the allocation stub to | 1207 // In the non-factory case, we rely on the allocation stub to |
| 1208 // instantiate the type arguments. | 1208 // instantiate the type arguments. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1241 // TODO(regis): The following emitted code is duplicated in | 1241 // TODO(regis): The following emitted code is duplicated in |
| 1242 // VisitExtractConstructorTypeArguments above. The reason is that the code | 1242 // VisitExtractConstructorTypeArguments above. The reason is that the code |
| 1243 // is split between two computations, so that each one produces a | 1243 // is split between two computations, so that each one produces a |
| 1244 // single value, rather than producing a pair of values. | 1244 // single value, rather than producing a pair of values. |
| 1245 // If this becomes an issue, we should expose these tests at the IL level. | 1245 // If this becomes an issue, we should expose these tests at the IL level. |
| 1246 | 1246 |
| 1247 // Check if the instantiator type argument vector is a TypeArguments of a | 1247 // Check if the instantiator type argument vector is a TypeArguments of a |
| 1248 // matching length and, if so, use it as the instantiated type_arguments. | 1248 // matching length and, if so, use it as the instantiated type_arguments. |
| 1249 // No need to check the instantiator (RAX) for null here, because a null | 1249 // No need to check the instantiator (RAX) for null here, because a null |
| 1250 // instantiator will have the wrong class (Null instead of TypeArguments). | 1250 // instantiator will have the wrong class (Null instead of TypeArguments). |
| 1251 __ LoadObject(RCX, Class::ZoneHandle(Object::type_arguments_class())); | 1251 __ GetClassOf(R10, RAX); |
| 1252 __ cmpq(RCX, FieldAddress(RAX, Object::class_offset())); | 1252 __ CompareObject(R10, Class::ZoneHandle(Object::type_arguments_class())); |
| 1253 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1253 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 1254 Immediate arguments_length = | 1254 Immediate arguments_length = |
| 1255 Immediate(Smi::RawValue(comp->type_arguments().Length())); | 1255 Immediate(Smi::RawValue(comp->type_arguments().Length())); |
| 1256 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), | 1256 __ cmpq(FieldAddress(RAX, TypeArguments::length_offset()), |
| 1257 arguments_length); | 1257 arguments_length); |
| 1258 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1258 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 1259 // The instantiator was used in VisitExtractConstructorTypeArguments as the | 1259 // The instantiator was used in VisitExtractConstructorTypeArguments as the |
| 1260 // instantiated type arguments, no proper instantiator needed. | 1260 // instantiated type arguments, no proper instantiator needed. |
| 1261 __ movq(RAX, Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 1261 __ movq(RAX, Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 1262 } | 1262 } |
| (...skipping 668 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1931 | 1931 |
| 1932 | 1932 |
| 1933 void FlowGraphCompiler::FinalizeComments(const Code& code) { | 1933 void FlowGraphCompiler::FinalizeComments(const Code& code) { |
| 1934 code.set_comments(assembler_->GetCodeComments()); | 1934 code.set_comments(assembler_->GetCodeComments()); |
| 1935 } | 1935 } |
| 1936 | 1936 |
| 1937 | 1937 |
| 1938 } // namespace dart | 1938 } // namespace dart |
| 1939 | 1939 |
| 1940 #endif // defined TARGET_ARCH_X64 | 1940 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |