OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 // RAX: newly allocated array. | 359 // RAX: newly allocated array. |
360 // R10: length of the array (was preserved by the stub). | 360 // R10: length of the array (was preserved by the stub). |
361 __ pushq(RAX); // Array is in RAX and on top of stack. | 361 __ pushq(RAX); // Array is in RAX and on top of stack. |
362 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); | 362 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); |
363 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | 363 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); |
364 // R12: address of first argument on stack. | 364 // R12: address of first argument on stack. |
365 // RBX: address of first argument in array. | 365 // RBX: address of first argument in array. |
366 Label loop, loop_condition; | 366 Label loop, loop_condition; |
367 __ jmp(&loop_condition, Assembler::kNearJump); | 367 __ jmp(&loop_condition, Assembler::kNearJump); |
368 __ Bind(&loop); | 368 __ Bind(&loop); |
369 __ movq(RAX, Address(R12, 0)); | 369 __ movq(RDI, Address(R12, 0)); |
370 __ movq(Address(RBX, 0), RAX); | 370 // No generational barrier needed, since array is in new space. |
| 371 __ StoreIntoObjectNoBarrier(RAX, Address(RBX, 0), RDI); |
371 __ addq(RBX, Immediate(kWordSize)); | 372 __ addq(RBX, Immediate(kWordSize)); |
372 __ subq(R12, Immediate(kWordSize)); | 373 __ subq(R12, Immediate(kWordSize)); |
373 __ Bind(&loop_condition); | 374 __ Bind(&loop_condition); |
374 __ decq(R10); | 375 __ decq(R10); |
375 __ j(POSITIVE, &loop, Assembler::kNearJump); | 376 __ j(POSITIVE, &loop, Assembler::kNearJump); |
376 } | 377 } |
377 | 378 |
378 | 379 |
379 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 380 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
380 intptr_t deopt_reason, | 381 intptr_t deopt_reason, |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 // RCX: new object end address. | 646 // RCX: new object end address. |
646 // RDI: iterator which initially points to the start of the variable | 647 // RDI: iterator which initially points to the start of the variable |
647 // data area to be initialized. | 648 // data area to be initialized. |
648 __ LoadObject(R12, Object::null_object(), PP); | 649 __ LoadObject(R12, Object::null_object(), PP); |
649 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray))); | 650 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray))); |
650 Label done; | 651 Label done; |
651 Label init_loop; | 652 Label init_loop; |
652 __ Bind(&init_loop); | 653 __ Bind(&init_loop); |
653 __ cmpq(RDI, RCX); | 654 __ cmpq(RDI, RCX); |
654 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 655 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
655 __ movq(Address(RDI, 0), R12); | 656 // No generational barrier needed, since we are storing null. |
| 657 __ StoreIntoObjectNoBarrier(RAX, Address(RDI, 0), R12); |
656 __ addq(RDI, Immediate(kWordSize)); | 658 __ addq(RDI, Immediate(kWordSize)); |
657 __ jmp(&init_loop, Assembler::kNearJump); | 659 __ jmp(&init_loop, Assembler::kNearJump); |
658 __ Bind(&done); | 660 __ Bind(&done); |
659 __ ret(); // returns the newly allocated object in RAX. | 661 __ ret(); // returns the newly allocated object in RAX. |
660 | 662 |
661 // Unable to allocate the array using the fast inline code, just call | 663 // Unable to allocate the array using the fast inline code, just call |
662 // into the runtime. | 664 // into the runtime. |
663 __ Bind(&slow_case); | 665 __ Bind(&slow_case); |
664 // Create a stub frame as we are pushing some objects on the stack before | 666 // Create a stub frame as we are pushing some objects on the stack before |
665 // calling into the runtime. | 667 // calling into the runtime. |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
878 } | 880 } |
879 | 881 |
880 // Setup up number of context variables field. | 882 // Setup up number of context variables field. |
881 // RAX: new object. | 883 // RAX: new object. |
882 // R10: number of context variables as integer value (not object). | 884 // R10: number of context variables as integer value (not object). |
883 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); | 885 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); |
884 | 886 |
885 // Setup the parent field. | 887 // Setup the parent field. |
886 // RAX: new object. | 888 // RAX: new object. |
887 // R10: number of context variables. | 889 // R10: number of context variables. |
888 __ movq(FieldAddress(RAX, Context::parent_offset()), R12); | 890 // No generational barrier needed, since we are storing null. |
| 891 __ StoreIntoObjectNoBarrier(RAX, |
| 892 FieldAddress(RAX, Context::parent_offset()), |
| 893 R12); |
889 | 894 |
890 // Initialize the context variables. | 895 // Initialize the context variables. |
891 // RAX: new object. | 896 // RAX: new object. |
892 // R10: number of context variables. | 897 // R10: number of context variables. |
893 { | 898 { |
894 Label loop, entry; | 899 Label loop, entry; |
895 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0))); | 900 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0))); |
896 | 901 |
897 __ jmp(&entry, Assembler::kNearJump); | 902 __ jmp(&entry, Assembler::kNearJump); |
898 __ Bind(&loop); | 903 __ Bind(&loop); |
899 __ decq(R10); | 904 __ decq(R10); |
900 __ movq(Address(R13, R10, TIMES_8, 0), R12); | 905 // No generational barrier needed, since we are storing null. |
| 906 __ StoreIntoObjectNoBarrier(RAX, |
| 907 Address(R13, R10, TIMES_8, 0), |
| 908 R12); |
901 __ Bind(&entry); | 909 __ Bind(&entry); |
902 __ cmpq(R10, Immediate(0)); | 910 __ cmpq(R10, Immediate(0)); |
903 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 911 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
904 } | 912 } |
905 | 913 |
906 // Done allocating and initializing the context. | 914 // Done allocating and initializing the context. |
907 // RAX: new object. | 915 // RAX: new object. |
908 __ ret(); | 916 __ ret(); |
909 | 917 |
910 __ Bind(&slow_case); | 918 __ Bind(&slow_case); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1031 __ movq(R13, Immediate(heap->EndAddress(space))); | 1039 __ movq(R13, Immediate(heap->EndAddress(space))); |
1032 __ cmpq(RBX, Address(R13, 0)); | 1040 __ cmpq(RBX, Address(R13, 0)); |
1033 if (FLAG_use_slow_path) { | 1041 if (FLAG_use_slow_path) { |
1034 __ jmp(&slow_case); | 1042 __ jmp(&slow_case); |
1035 } else { | 1043 } else { |
1036 __ j(ABOVE_EQUAL, &slow_case); | 1044 __ j(ABOVE_EQUAL, &slow_case); |
1037 } | 1045 } |
1038 __ movq(Address(RCX, 0), RBX); | 1046 __ movq(Address(RCX, 0), RBX); |
1039 __ UpdateAllocationStats(cls.id(), space); | 1047 __ UpdateAllocationStats(cls.id(), space); |
1040 | 1048 |
1041 // RAX: new object start. | 1049 // RAX: new object start (untagged). |
1042 // RBX: next object start. | 1050 // RBX: next object start. |
1043 // RDX: new object type arguments (if is_cls_parameterized). | 1051 // RDX: new object type arguments (if is_cls_parameterized). |
1044 // Set the tags. | 1052 // Set the tags. |
1045 uword tags = 0; | 1053 uword tags = 0; |
1046 tags = RawObject::SizeTag::update(instance_size, tags); | 1054 tags = RawObject::SizeTag::update(instance_size, tags); |
1047 ASSERT(cls.id() != kIllegalCid); | 1055 ASSERT(cls.id() != kIllegalCid); |
1048 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1056 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
1049 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); | 1057 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); |
| 1058 __ addq(RAX, Immediate(kHeapObjectTag)); |
1050 | 1059 |
1051 // Initialize the remaining words of the object. | 1060 // Initialize the remaining words of the object. |
1052 // RAX: new object start. | 1061 // RAX: new object (tagged). |
1053 // RBX: next object start. | 1062 // RBX: next object start. |
1054 // RDX: new object type arguments (if is_cls_parameterized). | 1063 // RDX: new object type arguments (if is_cls_parameterized). |
1055 // R12: raw null. | 1064 // R12: raw null. |
1056 // First try inlining the initialization without a loop. | 1065 // First try inlining the initialization without a loop. |
1057 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1066 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
1058 // Check if the object contains any non-header fields. | 1067 // Check if the object contains any non-header fields. |
1059 // Small objects are initialized using a consecutive set of writes. | 1068 // Small objects are initialized using a consecutive set of writes. |
1060 for (intptr_t current_offset = Instance::NextFieldOffset(); | 1069 for (intptr_t current_offset = Instance::NextFieldOffset(); |
1061 current_offset < instance_size; | 1070 current_offset < instance_size; |
1062 current_offset += kWordSize) { | 1071 current_offset += kWordSize) { |
1063 __ movq(Address(RAX, current_offset), R12); | 1072 __ StoreIntoObjectNoBarrier(RAX, |
| 1073 FieldAddress(RAX, current_offset), |
| 1074 R12); |
1064 } | 1075 } |
1065 } else { | 1076 } else { |
1066 __ leaq(RCX, Address(RAX, Instance::NextFieldOffset())); | 1077 __ leaq(RCX, FieldAddress(RAX, Instance::NextFieldOffset())); |
1067 // Loop until the whole object is initialized. | 1078 // Loop until the whole object is initialized. |
1068 // RAX: new object. | 1079 // RAX: new object (tagged). |
1069 // RBX: next object start. | 1080 // RBX: next object start. |
1070 // RCX: next word to be initialized. | 1081 // RCX: next word to be initialized. |
1071 // RDX: new object type arguments (if is_cls_parameterized). | 1082 // RDX: new object type arguments (if is_cls_parameterized). |
1072 Label init_loop; | 1083 Label init_loop; |
1073 Label done; | 1084 Label done; |
1074 __ Bind(&init_loop); | 1085 __ Bind(&init_loop); |
1075 __ cmpq(RCX, RBX); | 1086 __ cmpq(RCX, RBX); |
1076 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 1087 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
1077 __ movq(Address(RCX, 0), R12); | 1088 __ StoreIntoObjectNoBarrier(RAX, Address(RCX, 0), R12); |
1078 __ addq(RCX, Immediate(kWordSize)); | 1089 __ addq(RCX, Immediate(kWordSize)); |
1079 __ jmp(&init_loop, Assembler::kNearJump); | 1090 __ jmp(&init_loop, Assembler::kNearJump); |
1080 __ Bind(&done); | 1091 __ Bind(&done); |
1081 } | 1092 } |
1082 if (is_cls_parameterized) { | 1093 if (is_cls_parameterized) { |
1083 // RDX: new object type arguments. | 1094 // RDX: new object type arguments. |
1084 // Set the type arguments in the new object. | 1095 // Set the type arguments in the new object. |
1085 __ movq(Address(RAX, cls.type_arguments_field_offset()), RDX); | 1096 intptr_t offset = cls.type_arguments_field_offset(); |
| 1097 __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, offset), RDX); |
1086 } | 1098 } |
1087 // Done allocating and initializing the instance. | 1099 // Done allocating and initializing the instance. |
1088 // RAX: new object. | 1100 // RAX: new object (tagged). |
1089 __ addq(RAX, Immediate(kHeapObjectTag)); | |
1090 __ ret(); | 1101 __ ret(); |
1091 | 1102 |
1092 __ Bind(&slow_case); | 1103 __ Bind(&slow_case); |
1093 } | 1104 } |
1094 // If is_cls_parameterized: | 1105 // If is_cls_parameterized: |
1095 // RDX: new object type arguments. | 1106 // RDX: new object type arguments. |
1096 // Create a stub frame. | 1107 // Create a stub frame. |
1097 __ EnterStubFrame(true); // Uses PP to access class object. | 1108 __ EnterStubFrame(true); // Uses PP to access class object. |
1098 __ pushq(R12); // Setup space on stack for return value. | 1109 __ pushq(R12); // Setup space on stack for return value. |
1099 __ PushObject(cls, PP); // Push class of object to be allocated. | 1110 __ PushObject(cls, PP); // Push class of object to be allocated. |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1189 if (FLAG_throw_on_javascript_int_overflow) { | 1200 if (FLAG_throw_on_javascript_int_overflow) { |
1190 // The overflow check is more complex than implemented below. | 1201 // The overflow check is more complex than implemented below. |
1191 return; | 1202 return; |
1192 } | 1203 } |
1193 ASSERT(num_args == 2); | 1204 ASSERT(num_args == 2); |
1194 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Right | 1205 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Right |
1195 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left. | 1206 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left. |
1196 __ movq(R12, RCX); | 1207 __ movq(R12, RCX); |
1197 __ orq(R12, RAX); | 1208 __ orq(R12, RAX); |
1198 __ testq(R12, Immediate(kSmiTagMask)); | 1209 __ testq(R12, Immediate(kSmiTagMask)); |
1199 __ j(NOT_ZERO, not_smi_or_overflow, Assembler::kNearJump); | 1210 #if defined(DEBUG) |
| 1211 const bool jump_length = Assembler::kFarJump; |
| 1212 #else |
| 1213 const bool jump_length = Assembler::kNearJump; |
| 1214 #endif |
| 1215 __ j(NOT_ZERO, not_smi_or_overflow, jump_length); |
1200 switch (kind) { | 1216 switch (kind) { |
1201 case Token::kADD: { | 1217 case Token::kADD: { |
1202 __ addq(RAX, RCX); | 1218 __ addq(RAX, RCX); |
1203 __ j(OVERFLOW, not_smi_or_overflow, Assembler::kNearJump); | 1219 __ j(OVERFLOW, not_smi_or_overflow, jump_length); |
1204 break; | 1220 break; |
1205 } | 1221 } |
1206 case Token::kSUB: { | 1222 case Token::kSUB: { |
1207 __ subq(RAX, RCX); | 1223 __ subq(RAX, RCX); |
1208 __ j(OVERFLOW, not_smi_or_overflow, Assembler::kNearJump); | 1224 __ j(OVERFLOW, not_smi_or_overflow, jump_length); |
1209 break; | 1225 break; |
1210 } | 1226 } |
1211 case Token::kEQ: { | 1227 case Token::kEQ: { |
1212 Label done, is_true; | 1228 Label done, is_true; |
1213 __ cmpq(RAX, RCX); | 1229 __ cmpq(RAX, RCX); |
1214 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1230 __ j(EQUAL, &is_true, Assembler::kNearJump); |
1215 __ LoadObject(RAX, Bool::False(), PP); | 1231 __ LoadObject(RAX, Bool::False(), PP); |
1216 __ jmp(&done, Assembler::kNearJump); | 1232 __ jmp(&done, Assembler::kNearJump); |
1217 __ Bind(&is_true); | 1233 __ Bind(&is_true); |
1218 __ LoadObject(RAX, Bool::True(), PP); | 1234 __ LoadObject(RAX, Bool::True(), PP); |
(...skipping 21 matching lines...) Expand all Loading... |
1240 __ Stop("Incorrect IC data"); | 1256 __ Stop("Incorrect IC data"); |
1241 __ Bind(&ok); | 1257 __ Bind(&ok); |
1242 #endif | 1258 #endif |
1243 | 1259 |
1244 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1260 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
1245 // Update counter. | 1261 // Update counter. |
1246 __ movq(R8, Address(R12, count_offset)); | 1262 __ movq(R8, Address(R12, count_offset)); |
1247 __ addq(R8, Immediate(Smi::RawValue(1))); | 1263 __ addq(R8, Immediate(Smi::RawValue(1))); |
1248 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1264 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); |
1249 __ cmovnoq(R9, R8); | 1265 __ cmovnoq(R9, R8); |
1250 __ movq(Address(R12, count_offset), R9); | 1266 __ StoreIntoSmiField(Address(R12, count_offset), R9); |
1251 | 1267 |
1252 __ ret(); | 1268 __ ret(); |
1253 } | 1269 } |
1254 | 1270 |
1255 | 1271 |
1256 // Generate inline cache check for 'num_args'. | 1272 // Generate inline cache check for 'num_args'. |
1257 // RBX: Inline cache data object. | 1273 // RBX: Inline cache data object. |
1258 // TOS(0): return address | 1274 // TOS(0): return address |
1259 // Control flow: | 1275 // Control flow: |
1260 // - If receiver is null -> jump to IC miss. | 1276 // - If receiver is null -> jump to IC miss. |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1382 // R12: Pointer to an IC data check group. | 1398 // R12: Pointer to an IC data check group. |
1383 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1399 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
1384 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1400 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
1385 __ movq(RAX, Address(R12, target_offset)); | 1401 __ movq(RAX, Address(R12, target_offset)); |
1386 | 1402 |
1387 // Update counter. | 1403 // Update counter. |
1388 __ movq(R8, Address(R12, count_offset)); | 1404 __ movq(R8, Address(R12, count_offset)); |
1389 __ addq(R8, Immediate(Smi::RawValue(1))); | 1405 __ addq(R8, Immediate(Smi::RawValue(1))); |
1390 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1406 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); |
1391 __ cmovnoq(R9, R8); | 1407 __ cmovnoq(R9, R8); |
1392 __ movq(Address(R12, count_offset), R9); | 1408 __ StoreIntoSmiField(Address(R12, count_offset), R9); |
1393 | 1409 |
1394 __ Bind(&call_target_function); | 1410 __ Bind(&call_target_function); |
1395 // RAX: Target function. | 1411 // RAX: Target function. |
1396 Label is_compiled; | 1412 Label is_compiled; |
1397 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); | 1413 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); |
1398 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1414 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
1399 __ jmp(RCX); | 1415 __ jmp(RCX); |
1400 | 1416 |
1401 __ Bind(&stepping); | 1417 __ Bind(&stepping); |
1402 __ EnterStubFrame(); | 1418 __ EnterStubFrame(); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1528 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1544 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
1529 // R12: points directly to the first ic data array element. | 1545 // R12: points directly to the first ic data array element. |
1530 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1546 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1531 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1547 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1532 | 1548 |
1533 // Increment count for this call. | 1549 // Increment count for this call. |
1534 __ movq(R8, Address(R12, count_offset)); | 1550 __ movq(R8, Address(R12, count_offset)); |
1535 __ addq(R8, Immediate(Smi::RawValue(1))); | 1551 __ addq(R8, Immediate(Smi::RawValue(1))); |
1536 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1552 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); |
1537 __ cmovnoq(R9, R8); | 1553 __ cmovnoq(R9, R8); |
1538 __ movq(Address(R12, count_offset), R9); | 1554 __ StoreIntoSmiField(Address(R12, count_offset), R9); |
1539 | 1555 |
1540 // Load arguments descriptor into R10. | 1556 // Load arguments descriptor into R10. |
1541 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); | 1557 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
1542 | 1558 |
1543 // Get function and call it, if possible. | 1559 // Get function and call it, if possible. |
1544 __ movq(RAX, Address(R12, target_offset)); | 1560 __ movq(RAX, Address(R12, target_offset)); |
1545 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); | 1561 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); |
1546 // RCX: Target instructions. | 1562 // RCX: Target instructions. |
1547 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1563 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
1548 __ jmp(RCX); | 1564 __ jmp(RCX); |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1951 | 1967 |
1952 __ movq(left, Address(RSP, 2 * kWordSize)); | 1968 __ movq(left, Address(RSP, 2 * kWordSize)); |
1953 __ movq(right, Address(RSP, 1 * kWordSize)); | 1969 __ movq(right, Address(RSP, 1 * kWordSize)); |
1954 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 1970 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
1955 __ ret(); | 1971 __ ret(); |
1956 } | 1972 } |
1957 | 1973 |
1958 } // namespace dart | 1974 } // namespace dart |
1959 | 1975 |
1960 #endif // defined TARGET_ARCH_X64 | 1976 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |