| 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" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/assembler_macros.h" | 9 #include "vm/assembler_macros.h" |
| 10 #include "vm/code_generator.h" | 10 #include "vm/code_generator.h" |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 // Total number of args is the first Smi in args descriptor array (R10). | 287 // Total number of args is the first Smi in args descriptor array (R10). |
| 288 __ movq(RAX, FieldAddress(R10, Array::data_offset())); | 288 __ movq(RAX, FieldAddress(R10, Array::data_offset())); |
| 289 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // Get receiver. RAX is a Smi. | 289 __ movq(RAX, Address(RSP, RAX, TIMES_4, 0)); // Get receiver. RAX is a Smi. |
| 290 // TODO(srdjan): Remove the special casing below for null receiver, once | 290 // TODO(srdjan): Remove the special casing below for null receiver, once |
| 291 // NullClass is implemented. | 291 // NullClass is implemented. |
| 292 __ cmpq(RAX, raw_null); | 292 __ cmpq(RAX, raw_null); |
| 293 // Use Object class if receiver is null. | 293 // Use Object class if receiver is null. |
| 294 __ j(EQUAL, &null_receiver, Assembler::kNearJump); | 294 __ j(EQUAL, &null_receiver, Assembler::kNearJump); |
| 295 __ testq(RAX, Immediate(kSmiTagMask)); | 295 __ testq(RAX, Immediate(kSmiTagMask)); |
| 296 __ j(ZERO, &smi_receiver, Assembler::kNearJump); | 296 __ j(ZERO, &smi_receiver, Assembler::kNearJump); |
| 297 __ movq(RAX, FieldAddress(RAX, Object::class_offset())); | 297 __ GetClassOf(RAX, RAX); |
| 298 __ jmp(&class_in_rax, Assembler::kNearJump); | 298 __ jmp(&class_in_rax, Assembler::kNearJump); |
| 299 __ Bind(&smi_receiver); | 299 __ Bind(&smi_receiver); |
| 300 // For Smis we need to get the class from the isolate. | 300 // For Smis we need to get the class from the isolate. |
| 301 // Load current Isolate pointer from Context structure into RAX. | 301 // Load current Isolate pointer from Context structure into RAX. |
| 302 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | 302 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); |
| 303 __ movq(RAX, Address(RAX, Isolate::object_store_offset())); | 303 __ movq(RAX, Address(RAX, Isolate::object_store_offset())); |
| 304 __ movq(RAX, Address(RAX, ObjectStore::smi_class_offset())); | 304 __ movq(RAX, Address(RAX, ObjectStore::smi_class_offset())); |
| 305 __ jmp(&class_in_rax, Assembler::kNearJump); | 305 __ jmp(&class_in_rax, Assembler::kNearJump); |
| 306 __ Bind(&null_receiver); | 306 __ Bind(&null_receiver); |
| 307 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); | 307 __ movq(RAX, FieldAddress(CTX, Context::isolate_offset())); |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 // R10: Array length as Smi. | 658 // R10: Array length as Smi. |
| 659 | 659 |
| 660 // Store the type argument field. | 660 // Store the type argument field. |
| 661 __ StoreIntoObject(RAX, | 661 __ StoreIntoObject(RAX, |
| 662 FieldAddress(RAX, Array::type_arguments_offset()), | 662 FieldAddress(RAX, Array::type_arguments_offset()), |
| 663 RBX); | 663 RBX); |
| 664 | 664 |
| 665 // Set the length field. | 665 // Set the length field. |
| 666 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::length_offset()), R10); | 666 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::length_offset()), R10); |
| 667 | 667 |
| 668 // Store class value for array. | |
| 669 __ movq(RBX, FieldAddress(CTX, Context::isolate_offset())); | |
| 670 __ movq(RBX, Address(RBX, Isolate::object_store_offset())); | |
| 671 __ movq(RBX, Address(RBX, ObjectStore::array_class_offset())); | |
| 672 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::class_offset()), RBX); | |
| 673 // Calculate the size tag. | 668 // Calculate the size tag. |
| 674 // RAX: new object start as a tagged pointer. | 669 // RAX: new object start as a tagged pointer. |
| 675 // R12: new object end address. | 670 // R12: new object end address. |
| 676 // R10: Array length as Smi. | 671 // R10: Array length as Smi. |
| 677 { | 672 { |
| 678 Label size_tag_overflow, done; | 673 Label size_tag_overflow, done; |
| 679 __ leaq(RBX, Address(R10, TIMES_4, fixed_size)); // R10 is Smi. | 674 __ leaq(RBX, Address(R10, TIMES_4, fixed_size)); // R10 is Smi. |
| 680 ASSERT(kSmiTagShift == 1); | 675 ASSERT(kSmiTagShift == 1); |
| 681 __ andq(RBX, Immediate(-kObjectAlignment)); | 676 __ andq(RBX, Immediate(-kObjectAlignment)); |
| 682 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 677 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 | 743 |
| 749 // Verify that R13 is a closure by checking its class. | 744 // Verify that R13 is a closure by checking its class. |
| 750 Label not_closure; | 745 Label not_closure; |
| 751 __ cmpq(R13, raw_null); | 746 __ cmpq(R13, raw_null); |
| 752 // Not a closure, but null object. | 747 // Not a closure, but null object. |
| 753 __ j(EQUAL, ¬_closure, Assembler::kNearJump); | 748 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| 754 __ testq(R13, Immediate(kSmiTagMask)); | 749 __ testq(R13, Immediate(kSmiTagMask)); |
| 755 __ j(ZERO, ¬_closure, Assembler::kNearJump); // Not a closure, but a smi. | 750 __ j(ZERO, ¬_closure, Assembler::kNearJump); // Not a closure, but a smi. |
| 756 // Verify that the class of the object is a closure class by checking that | 751 // Verify that the class of the object is a closure class by checking that |
| 757 // class.signature_function() is not null. | 752 // class.signature_function() is not null. |
| 758 __ movq(RAX, FieldAddress(R13, Object::class_offset())); | 753 __ GetClassOf(RAX, R13); |
| 759 __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset())); | 754 __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset())); |
| 760 __ cmpq(RAX, raw_null); | 755 __ cmpq(RAX, raw_null); |
| 761 // Actual class is not a closure class. | 756 // Actual class is not a closure class. |
| 762 __ j(EQUAL, ¬_closure, Assembler::kNearJump); | 757 __ j(EQUAL, ¬_closure, Assembler::kNearJump); |
| 763 | 758 |
| 764 // RAX is just the signature function. Load the actual closure function. | 759 // RAX is just the signature function. Load the actual closure function. |
| 765 __ movq(RBX, FieldAddress(R13, Closure::function_offset())); | 760 __ movq(RBX, FieldAddress(R13, Closure::function_offset())); |
| 766 | 761 |
| 767 // Load closure context in CTX; note that CTX has already been preserved. | 762 // Load closure context in CTX; note that CTX has already been preserved. |
| 768 __ movq(CTX, FieldAddress(R13, Closure::context_offset())); | 763 __ movq(CTX, FieldAddress(R13, Closure::context_offset())); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 983 | 978 |
| 984 // Successfully allocated the object, now update top to point to | 979 // Successfully allocated the object, now update top to point to |
| 985 // next object start and initialize the object. | 980 // next object start and initialize the object. |
| 986 // RAX: new object. | 981 // RAX: new object. |
| 987 // R13: next object start. | 982 // R13: next object start. |
| 988 // R10: number of context variables. | 983 // R10: number of context variables. |
| 989 __ movq(RDI, Immediate(heap->TopAddress())); | 984 __ movq(RDI, Immediate(heap->TopAddress())); |
| 990 __ movq(Address(RDI, 0), R13); | 985 __ movq(Address(RDI, 0), R13); |
| 991 __ addq(RAX, Immediate(kHeapObjectTag)); | 986 __ addq(RAX, Immediate(kHeapObjectTag)); |
| 992 | 987 |
| 993 // Initialize the class field in the context object. | |
| 994 // RAX: new object. | |
| 995 // R10: number of context variables. | |
| 996 __ LoadObject(R13, context_class); // Load up class field of context. | |
| 997 __ StoreIntoObject(RAX, | |
| 998 FieldAddress(RAX, Context::class_offset()), | |
| 999 R13); | |
| 1000 // Calculate the size tag. | 988 // Calculate the size tag. |
| 1001 // RAX: new object. | 989 // RAX: new object. |
| 1002 // R10: number of context variables. | 990 // R10: number of context variables. |
| 1003 { | 991 { |
| 1004 Label size_tag_overflow, done; | 992 Label size_tag_overflow, done; |
| 1005 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); | 993 __ leaq(R13, Address(R10, TIMES_8, fixed_size)); |
| 1006 __ andq(R13, Immediate(-kObjectAlignment)); | 994 __ andq(R13, Immediate(-kObjectAlignment)); |
| 1007 __ cmpq(R13, Immediate(RawObject::SizeTag::kMaxSizeTag)); | 995 __ cmpq(R13, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
| 1008 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | 996 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
| 1009 __ shlq(R13, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); | 997 __ shlq(R13, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1149 // Initialize InstantiatedTypeArguments object at RCX. | 1137 // Initialize InstantiatedTypeArguments object at RCX. |
| 1150 __ movq(Address(RCX, | 1138 __ movq(Address(RCX, |
| 1151 InstantiatedTypeArguments::uninstantiated_type_arguments_offset()), | 1139 InstantiatedTypeArguments::uninstantiated_type_arguments_offset()), |
| 1152 RDI); | 1140 RDI); |
| 1153 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); | 1141 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); |
| 1154 __ movq(Address(RCX, | 1142 __ movq(Address(RCX, |
| 1155 InstantiatedTypeArguments::instantiator_type_arguments_offset()), | 1143 InstantiatedTypeArguments::instantiator_type_arguments_offset()), |
| 1156 RDX); | 1144 RDX); |
| 1157 const Class& ita_cls = | 1145 const Class& ita_cls = |
| 1158 Class::ZoneHandle(Object::instantiated_type_arguments_class()); | 1146 Class::ZoneHandle(Object::instantiated_type_arguments_class()); |
| 1159 __ LoadObject(RDX, ita_cls); | |
| 1160 __ movq(Address(RCX, Instance::class_offset()), RDX); // Set its class. | |
| 1161 // Set the tags. | 1147 // Set the tags. |
| 1162 uword tags = 0; | 1148 uword tags = 0; |
| 1163 tags = RawObject::SizeTag::update(type_args_size, tags); | 1149 tags = RawObject::SizeTag::update(type_args_size, tags); |
| 1164 tags = RawObject::ClassTag::update(ita_cls.index(), tags); | 1150 tags = RawObject::ClassTag::update(ita_cls.index(), tags); |
| 1165 __ movq(Address(RCX, Instance::tags_offset()), Immediate(tags)); | 1151 __ movq(Address(RCX, Instance::tags_offset()), Immediate(tags)); |
| 1166 // Set the new InstantiatedTypeArguments object (RCX) as the type | 1152 // Set the new InstantiatedTypeArguments object (RCX) as the type |
| 1167 // arguments (RDI) of the new object (RAX). | 1153 // arguments (RDI) of the new object (RAX). |
| 1168 __ movq(RDI, RCX); | 1154 __ movq(RDI, RCX); |
| 1169 __ addq(RDI, Immediate(kHeapObjectTag)); | 1155 __ addq(RDI, Immediate(kHeapObjectTag)); |
| 1170 // Set RBX to new object end. | 1156 // Set RBX to new object end. |
| 1171 __ movq(RBX, RCX); | 1157 __ movq(RBX, RCX); |
| 1172 __ Bind(&type_arguments_ready); | 1158 __ Bind(&type_arguments_ready); |
| 1173 // RAX: new object. | 1159 // RAX: new object. |
| 1174 // RDI: new object type arguments. | 1160 // RDI: new object type arguments. |
| 1175 } | 1161 } |
| 1176 | 1162 |
| 1177 // Initialize the class field in the object. | |
| 1178 // RAX: new object start. | 1163 // RAX: new object start. |
| 1179 // RBX: next object start. | 1164 // RBX: next object start. |
| 1180 // RDI: new object type arguments (if is_cls_parameterized). | 1165 // RDI: new object type arguments (if is_cls_parameterized). |
| 1181 __ LoadObject(RDX, cls); // Load class of object to be allocated. | 1166 __ LoadObject(RDX, cls); // Load class of object to be allocated. |
| 1182 __ movq(Address(RAX, Instance::class_offset()), RDX); | |
| 1183 // Set the tags. | 1167 // Set the tags. |
| 1184 uword tags = 0; | 1168 uword tags = 0; |
| 1185 tags = RawObject::SizeTag::update(instance_size, tags); | 1169 tags = RawObject::SizeTag::update(instance_size, tags); |
| 1186 ASSERT(cls.index() != kIllegalObjectKind); | 1170 ASSERT(cls.index() != kIllegalObjectKind); |
| 1187 tags = RawObject::ClassTag::update(cls.index(), tags); | 1171 tags = RawObject::ClassTag::update(cls.index(), tags); |
| 1188 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); | 1172 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); |
| 1189 | 1173 |
| 1190 // Initialize the remaining words of the object. | 1174 // Initialize the remaining words of the object. |
| 1191 const Immediate raw_null = | 1175 const Immediate raw_null = |
| 1192 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1176 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1323 __ jmp(&slow_case); | 1307 __ jmp(&slow_case); |
| 1324 } else { | 1308 } else { |
| 1325 __ j(ABOVE_EQUAL, &slow_case); | 1309 __ j(ABOVE_EQUAL, &slow_case); |
| 1326 } | 1310 } |
| 1327 | 1311 |
| 1328 // Successfully allocated the object, now update top to point to | 1312 // Successfully allocated the object, now update top to point to |
| 1329 // next object start and initialize the object. | 1313 // next object start and initialize the object. |
| 1330 __ movq(RDI, Immediate(heap->TopAddress())); | 1314 __ movq(RDI, Immediate(heap->TopAddress())); |
| 1331 __ movq(Address(RDI, 0), R13); | 1315 __ movq(Address(RDI, 0), R13); |
| 1332 | 1316 |
| 1333 // Initialize the class field in the object. | |
| 1334 // RAX: new closure object. | 1317 // RAX: new closure object. |
| 1335 // RBX: new context object (only if is_implicit_closure). | 1318 // RBX: new context object (only if is_implicit_closure). |
| 1336 __ LoadObject(R10, cls); // Load signature class of closure. | |
| 1337 __ movq(Address(RAX, Closure::class_offset()), R10); | |
| 1338 // Set the tags. | 1319 // Set the tags. |
| 1339 uword tags = 0; | 1320 uword tags = 0; |
| 1340 tags = RawObject::SizeTag::update(closure_size, tags); | 1321 tags = RawObject::SizeTag::update(closure_size, tags); |
| 1341 tags = RawObject::ClassTag::update(cls.index(), tags); | 1322 tags = RawObject::ClassTag::update(cls.index(), tags); |
| 1342 __ movq(Address(RAX, Closure::tags_offset()), Immediate(tags)); | 1323 __ movq(Address(RAX, Closure::tags_offset()), Immediate(tags)); |
| 1343 | 1324 |
| 1344 // Initialize the function field in the object. | 1325 // Initialize the function field in the object. |
| 1345 // RAX: new closure object. | 1326 // RAX: new closure object. |
| 1346 // RBX: new context object (only if is_implicit_closure). | 1327 // RBX: new context object (only if is_implicit_closure). |
| 1347 // R13: next object start. | 1328 // R13: next object start. |
| 1348 __ LoadObject(R10, func); // Load function of closure to be allocated. | 1329 __ LoadObject(R10, func); // Load function of closure to be allocated. |
| 1349 __ movq(Address(RAX, Closure::function_offset()), R10); | 1330 __ movq(Address(RAX, Closure::function_offset()), R10); |
| 1350 | 1331 |
| 1351 // Setup the context for this closure. | 1332 // Setup the context for this closure. |
| 1352 if (is_implicit_static_closure) { | 1333 if (is_implicit_static_closure) { |
| 1353 ObjectStore* object_store = Isolate::Current()->object_store(); | 1334 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 1354 ASSERT(object_store != NULL); | 1335 ASSERT(object_store != NULL); |
| 1355 const Context& empty_context = | 1336 const Context& empty_context = |
| 1356 Context::ZoneHandle(object_store->empty_context()); | 1337 Context::ZoneHandle(object_store->empty_context()); |
| 1357 __ LoadObject(R10, empty_context); | 1338 __ LoadObject(R10, empty_context); |
| 1358 __ movq(Address(RAX, Closure::context_offset()), R10); | 1339 __ movq(Address(RAX, Closure::context_offset()), R10); |
| 1359 } else if (is_implicit_instance_closure) { | 1340 } else if (is_implicit_instance_closure) { |
| 1360 // Initialize the new context capturing the receiver. | 1341 // Initialize the new context capturing the receiver. |
| 1361 | 1342 |
| 1362 // Set the class field to the Context class. | |
| 1363 const Class& context_class = Class::ZoneHandle(Object::context_class()); | 1343 const Class& context_class = Class::ZoneHandle(Object::context_class()); |
| 1364 __ LoadObject(R13, context_class); | |
| 1365 __ movq(Address(RBX, Context::class_offset()), R13); | |
| 1366 // Set the tags. | 1344 // Set the tags. |
| 1367 uword tags = 0; | 1345 uword tags = 0; |
| 1368 tags = RawObject::SizeTag::update(context_size, tags); | 1346 tags = RawObject::SizeTag::update(context_size, tags); |
| 1369 tags = RawObject::ClassTag::update(context_class.index(), tags); | 1347 tags = RawObject::ClassTag::update(context_class.index(), tags); |
| 1370 __ movq(Address(RBX, Context::tags_offset()), Immediate(tags)); | 1348 __ movq(Address(RBX, Context::tags_offset()), Immediate(tags)); |
| 1371 | 1349 |
| 1372 // Set number of variables field to 1 (for captured receiver). | 1350 // Set number of variables field to 1 (for captured receiver). |
| 1373 __ movq(Address(RBX, Context::num_variables_offset()), Immediate(1)); | 1351 __ movq(Address(RBX, Context::num_variables_offset()), Immediate(1)); |
| 1374 | 1352 |
| 1375 // Set isolate field to isolate of current context. | 1353 // Set isolate field to isolate of current context. |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1663 Label not_smi; | 1641 Label not_smi; |
| 1664 // Test if Smi -> load Smi class for comparison. | 1642 // Test if Smi -> load Smi class for comparison. |
| 1665 __ testq(RAX, Immediate(kSmiTagMask)); | 1643 __ testq(RAX, Immediate(kSmiTagMask)); |
| 1666 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); | 1644 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); |
| 1667 const Class& smi_class = | 1645 const Class& smi_class = |
| 1668 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); | 1646 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); |
| 1669 __ LoadObject(RAX, smi_class); | 1647 __ LoadObject(RAX, smi_class); |
| 1670 __ ret(); | 1648 __ ret(); |
| 1671 | 1649 |
| 1672 __ Bind(¬_smi); | 1650 __ Bind(¬_smi); |
| 1673 __ movq(RAX, FieldAddress(RAX, Object::class_offset())); | 1651 __ GetClassOf(RAX, RAX); |
| 1674 __ ret(); | 1652 __ ret(); |
| 1675 } | 1653 } |
| 1676 | 1654 |
| 1677 | 1655 |
| 1678 // Use inline cache data array to invoke the target or continue in inline | 1656 // Use inline cache data array to invoke the target or continue in inline |
| 1679 // cache miss handler. Stub for 1-argument check (receiver class). | 1657 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1680 // RCX: Inline cache data array | 1658 // RCX: Inline cache data array |
| 1681 // RDX: Arguments array | 1659 // RDX: Arguments array |
| 1682 // TOS(0): return address | 1660 // TOS(0): return address |
| 1683 // Inline cache data array structure: | 1661 // Inline cache data array structure: |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1761 // TOS + 3: SubtypeTestCache. | 1739 // TOS + 3: SubtypeTestCache. |
| 1762 // Result in RCX: null -> not found, otherwise result (true or false). | 1740 // Result in RCX: null -> not found, otherwise result (true or false). |
| 1763 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { | 1741 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { |
| 1764 ASSERT((1 <= n) && (n <= 3)); | 1742 ASSERT((1 <= n) && (n <= 3)); |
| 1765 const Immediate raw_null = | 1743 const Immediate raw_null = |
| 1766 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1744 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1767 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; | 1745 const intptr_t kInstantiatorTypeArgumentsInBytes = 1 * kWordSize; |
| 1768 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; | 1746 const intptr_t kInstanceOffsetInBytes = 2 * kWordSize; |
| 1769 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; | 1747 const intptr_t kCacheOffsetInBytes = 3 * kWordSize; |
| 1770 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); | 1748 __ movq(RAX, Address(RSP, kInstanceOffsetInBytes)); |
| 1771 __ movq(R10, FieldAddress(RAX, Object::class_offset())); | 1749 __ GetClassOf(R10, RAX); |
| 1772 // RAX: instance, R10: instance class. | 1750 // RAX: instance, R10: instance class. |
| 1773 if (n > 1) { | 1751 if (n > 1) { |
| 1774 // Compute instance type arguments into R13. | 1752 // Compute instance type arguments into R13. |
| 1775 Label has_no_type_arguments; | 1753 Label has_no_type_arguments; |
| 1776 __ movq(R13, raw_null); | 1754 __ movq(R13, raw_null); |
| 1777 __ movq(RDI, FieldAddress(R10, | 1755 __ movq(RDI, FieldAddress(R10, |
| 1778 Class::type_arguments_instance_field_offset_offset())); | 1756 Class::type_arguments_instance_field_offset_offset())); |
| 1779 __ cmpq(RDI, Immediate(Class::kNoTypeArguments)); | 1757 __ cmpq(RDI, Immediate(Class::kNoTypeArguments)); |
| 1780 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); | 1758 __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump); |
| 1781 __ movq(R13, FieldAddress(RAX, RDI, TIMES_1, 0)); | 1759 __ movq(R13, FieldAddress(RAX, RDI, TIMES_1, 0)); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1856 // TOS + 2: instance. | 1834 // TOS + 2: instance. |
| 1857 // TOS + 3: cache array. | 1835 // TOS + 3: cache array. |
| 1858 // Result in RCX: null -> not found, otherwise result (true or false). | 1836 // Result in RCX: null -> not found, otherwise result (true or false). |
| 1859 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { | 1837 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { |
| 1860 GenerateSubtypeNTestCacheStub(assembler, 3); | 1838 GenerateSubtypeNTestCacheStub(assembler, 3); |
| 1861 } | 1839 } |
| 1862 | 1840 |
| 1863 } // namespace dart | 1841 } // namespace dart |
| 1864 | 1842 |
| 1865 #endif // defined TARGET_ARCH_X64 | 1843 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |