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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1039 __ movq(R13, Immediate(heap->EndAddress(space))); | 1047 __ movq(R13, Immediate(heap->EndAddress(space))); |
1040 __ cmpq(RBX, Address(R13, 0)); | 1048 __ cmpq(RBX, Address(R13, 0)); |
1041 if (FLAG_use_slow_path) { | 1049 if (FLAG_use_slow_path) { |
1042 __ jmp(&slow_case); | 1050 __ jmp(&slow_case); |
1043 } else { | 1051 } else { |
1044 __ j(ABOVE_EQUAL, &slow_case); | 1052 __ j(ABOVE_EQUAL, &slow_case); |
1045 } | 1053 } |
1046 __ movq(Address(RCX, 0), RBX); | 1054 __ movq(Address(RCX, 0), RBX); |
1047 __ UpdateAllocationStats(cls.id(), space); | 1055 __ UpdateAllocationStats(cls.id(), space); |
1048 | 1056 |
1049 // RAX: new object start. | 1057 // RAX: new object start (untagged). |
1050 // RBX: next object start. | 1058 // RBX: next object start. |
1051 // RDX: new object type arguments (if is_cls_parameterized). | 1059 // RDX: new object type arguments (if is_cls_parameterized). |
1052 // Set the tags. | 1060 // Set the tags. |
1053 uword tags = 0; | 1061 uword tags = 0; |
1054 tags = RawObject::SizeTag::update(instance_size, tags); | 1062 tags = RawObject::SizeTag::update(instance_size, tags); |
1055 ASSERT(cls.id() != kIllegalCid); | 1063 ASSERT(cls.id() != kIllegalCid); |
1056 tags = RawObject::ClassIdTag::update(cls.id(), tags); | 1064 tags = RawObject::ClassIdTag::update(cls.id(), tags); |
1057 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); | 1065 __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags)); |
| 1066 __ addq(RAX, Immediate(kHeapObjectTag)); |
1058 | 1067 |
1059 // Initialize the remaining words of the object. | 1068 // Initialize the remaining words of the object. |
1060 // RAX: new object start. | 1069 // RAX: new object (tagged). |
1061 // RBX: next object start. | 1070 // RBX: next object start. |
1062 // RDX: new object type arguments (if is_cls_parameterized). | 1071 // RDX: new object type arguments (if is_cls_parameterized). |
1063 // R12: raw null. | 1072 // R12: raw null. |
1064 // First try inlining the initialization without a loop. | 1073 // First try inlining the initialization without a loop. |
1065 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1074 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
1066 // Check if the object contains any non-header fields. | 1075 // Check if the object contains any non-header fields. |
1067 // Small objects are initialized using a consecutive set of writes. | 1076 // Small objects are initialized using a consecutive set of writes. |
1068 for (intptr_t current_offset = Instance::NextFieldOffset(); | 1077 for (intptr_t current_offset = Instance::NextFieldOffset(); |
1069 current_offset < instance_size; | 1078 current_offset < instance_size; |
1070 current_offset += kWordSize) { | 1079 current_offset += kWordSize) { |
1071 __ movq(Address(RAX, current_offset), R12); | 1080 __ StoreIntoObjectNoBarrier(RAX, |
| 1081 FieldAddress(RAX, current_offset), |
| 1082 R12); |
1072 } | 1083 } |
1073 } else { | 1084 } else { |
1074 __ leaq(RCX, Address(RAX, Instance::NextFieldOffset())); | 1085 __ leaq(RCX, FieldAddress(RAX, Instance::NextFieldOffset())); |
1075 // Loop until the whole object is initialized. | 1086 // Loop until the whole object is initialized. |
1076 // RAX: new object. | 1087 // RAX: new object (tagged). |
1077 // RBX: next object start. | 1088 // RBX: next object start. |
1078 // RCX: next word to be initialized. | 1089 // RCX: next word to be initialized. |
1079 // RDX: new object type arguments (if is_cls_parameterized). | 1090 // RDX: new object type arguments (if is_cls_parameterized). |
1080 Label init_loop; | 1091 Label init_loop; |
1081 Label done; | 1092 Label done; |
1082 __ Bind(&init_loop); | 1093 __ Bind(&init_loop); |
1083 __ cmpq(RCX, RBX); | 1094 __ cmpq(RCX, RBX); |
1084 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 1095 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
1085 __ movq(Address(RCX, 0), R12); | 1096 __ StoreIntoObjectNoBarrier(RAX, Address(RCX, 0), R12); |
1086 __ addq(RCX, Immediate(kWordSize)); | 1097 __ addq(RCX, Immediate(kWordSize)); |
1087 __ jmp(&init_loop, Assembler::kNearJump); | 1098 __ jmp(&init_loop, Assembler::kNearJump); |
1088 __ Bind(&done); | 1099 __ Bind(&done); |
1089 } | 1100 } |
1090 if (is_cls_parameterized) { | 1101 if (is_cls_parameterized) { |
1091 // RDX: new object type arguments. | 1102 // RDX: new object type arguments. |
1092 // Set the type arguments in the new object. | 1103 // Set the type arguments in the new object. |
1093 __ movq(Address(RAX, cls.type_arguments_field_offset()), RDX); | 1104 intptr_t offset = cls.type_arguments_field_offset(); |
| 1105 __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, offset), RDX); |
1094 } | 1106 } |
1095 // Done allocating and initializing the instance. | 1107 // Done allocating and initializing the instance. |
1096 // RAX: new object. | 1108 // RAX: new object (tagged). |
1097 __ addq(RAX, Immediate(kHeapObjectTag)); | |
1098 __ ret(); | 1109 __ ret(); |
1099 | 1110 |
1100 __ Bind(&slow_case); | 1111 __ Bind(&slow_case); |
1101 } | 1112 } |
1102 // If is_cls_parameterized: | 1113 // If is_cls_parameterized: |
1103 // RDX: new object type arguments. | 1114 // RDX: new object type arguments. |
1104 // Create a stub frame. | 1115 // Create a stub frame. |
1105 __ EnterStubFrame(true); // Uses PP to access class object. | 1116 __ EnterStubFrame(true); // Uses PP to access class object. |
1106 __ pushq(R12); // Setup space on stack for return value. | 1117 __ pushq(R12); // Setup space on stack for return value. |
1107 __ PushObject(cls, PP); // Push class of object to be allocated. | 1118 __ PushObject(cls, PP); // Push class of object to be allocated. |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1197 if (FLAG_throw_on_javascript_int_overflow) { | 1208 if (FLAG_throw_on_javascript_int_overflow) { |
1198 // The overflow check is more complex than implemented below. | 1209 // The overflow check is more complex than implemented below. |
1199 return; | 1210 return; |
1200 } | 1211 } |
1201 ASSERT(num_args == 2); | 1212 ASSERT(num_args == 2); |
1202 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Right | 1213 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Right |
1203 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left. | 1214 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left. |
1204 __ movq(R12, RCX); | 1215 __ movq(R12, RCX); |
1205 __ orq(R12, RAX); | 1216 __ orq(R12, RAX); |
1206 __ testq(R12, Immediate(kSmiTagMask)); | 1217 __ testq(R12, Immediate(kSmiTagMask)); |
1207 __ j(NOT_ZERO, not_smi_or_overflow, Assembler::kNearJump); | 1218 #if defined(DEBUG) |
| 1219 const bool jump_length = Assembler::kFarJump; |
| 1220 #else |
| 1221 const bool jump_length = Assembler::kNearJump; |
| 1222 #endif |
| 1223 __ j(NOT_ZERO, not_smi_or_overflow, jump_length); |
1208 switch (kind) { | 1224 switch (kind) { |
1209 case Token::kADD: { | 1225 case Token::kADD: { |
1210 __ addq(RAX, RCX); | 1226 __ addq(RAX, RCX); |
1211 __ j(OVERFLOW, not_smi_or_overflow, Assembler::kNearJump); | 1227 __ j(OVERFLOW, not_smi_or_overflow, jump_length); |
1212 break; | 1228 break; |
1213 } | 1229 } |
1214 case Token::kSUB: { | 1230 case Token::kSUB: { |
1215 __ subq(RAX, RCX); | 1231 __ subq(RAX, RCX); |
1216 __ j(OVERFLOW, not_smi_or_overflow, Assembler::kNearJump); | 1232 __ j(OVERFLOW, not_smi_or_overflow, jump_length); |
1217 break; | 1233 break; |
1218 } | 1234 } |
1219 case Token::kEQ: { | 1235 case Token::kEQ: { |
1220 Label done, is_true; | 1236 Label done, is_true; |
1221 __ cmpq(RAX, RCX); | 1237 __ cmpq(RAX, RCX); |
1222 __ j(EQUAL, &is_true, Assembler::kNearJump); | 1238 __ j(EQUAL, &is_true, Assembler::kNearJump); |
1223 __ LoadObject(RAX, Bool::False(), PP); | 1239 __ LoadObject(RAX, Bool::False(), PP); |
1224 __ jmp(&done, Assembler::kNearJump); | 1240 __ jmp(&done, Assembler::kNearJump); |
1225 __ Bind(&is_true); | 1241 __ Bind(&is_true); |
1226 __ LoadObject(RAX, Bool::True(), PP); | 1242 __ LoadObject(RAX, Bool::True(), PP); |
(...skipping 21 matching lines...) Expand all Loading... |
1248 __ Stop("Incorrect IC data"); | 1264 __ Stop("Incorrect IC data"); |
1249 __ Bind(&ok); | 1265 __ Bind(&ok); |
1250 #endif | 1266 #endif |
1251 | 1267 |
1252 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1268 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
1253 // Update counter. | 1269 // Update counter. |
1254 __ movq(R8, Address(R12, count_offset)); | 1270 __ movq(R8, Address(R12, count_offset)); |
1255 __ addq(R8, Immediate(Smi::RawValue(1))); | 1271 __ addq(R8, Immediate(Smi::RawValue(1))); |
1256 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1272 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); |
1257 __ cmovnoq(R9, R8); | 1273 __ cmovnoq(R9, R8); |
1258 __ movq(Address(R12, count_offset), R9); | 1274 __ StoreIntoSmiField(Address(R12, count_offset), R9); |
1259 | 1275 |
1260 __ ret(); | 1276 __ ret(); |
1261 } | 1277 } |
1262 | 1278 |
1263 | 1279 |
1264 // Generate inline cache check for 'num_args'. | 1280 // Generate inline cache check for 'num_args'. |
1265 // RBX: Inline cache data object. | 1281 // RBX: Inline cache data object. |
1266 // TOS(0): return address | 1282 // TOS(0): return address |
1267 // Control flow: | 1283 // Control flow: |
1268 // - If receiver is null -> jump to IC miss. | 1284 // - If receiver is null -> jump to IC miss. |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1390 // R12: Pointer to an IC data check group. | 1406 // R12: Pointer to an IC data check group. |
1391 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1407 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
1392 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1408 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
1393 __ movq(RAX, Address(R12, target_offset)); | 1409 __ movq(RAX, Address(R12, target_offset)); |
1394 | 1410 |
1395 // Update counter. | 1411 // Update counter. |
1396 __ movq(R8, Address(R12, count_offset)); | 1412 __ movq(R8, Address(R12, count_offset)); |
1397 __ addq(R8, Immediate(Smi::RawValue(1))); | 1413 __ addq(R8, Immediate(Smi::RawValue(1))); |
1398 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1414 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); |
1399 __ cmovnoq(R9, R8); | 1415 __ cmovnoq(R9, R8); |
1400 __ movq(Address(R12, count_offset), R9); | 1416 __ StoreIntoSmiField(Address(R12, count_offset), R9); |
1401 | 1417 |
1402 __ Bind(&call_target_function); | 1418 __ Bind(&call_target_function); |
1403 // RAX: Target function. | 1419 // RAX: Target function. |
1404 Label is_compiled; | 1420 Label is_compiled; |
1405 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); | 1421 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); |
1406 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1422 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
1407 __ jmp(RCX); | 1423 __ jmp(RCX); |
1408 | 1424 |
1409 __ Bind(&stepping); | 1425 __ Bind(&stepping); |
1410 __ EnterStubFrame(); | 1426 __ EnterStubFrame(); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1536 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1552 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
1537 // R12: points directly to the first ic data array element. | 1553 // R12: points directly to the first ic data array element. |
1538 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1554 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1539 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1555 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1540 | 1556 |
1541 // Increment count for this call. | 1557 // Increment count for this call. |
1542 __ movq(R8, Address(R12, count_offset)); | 1558 __ movq(R8, Address(R12, count_offset)); |
1543 __ addq(R8, Immediate(Smi::RawValue(1))); | 1559 __ addq(R8, Immediate(Smi::RawValue(1))); |
1544 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1560 __ movq(R9, Immediate(Smi::RawValue(Smi::kMaxValue))); |
1545 __ cmovnoq(R9, R8); | 1561 __ cmovnoq(R9, R8); |
1546 __ movq(Address(R12, count_offset), R9); | 1562 __ StoreIntoSmiField(Address(R12, count_offset), R9); |
1547 | 1563 |
1548 // Load arguments descriptor into R10. | 1564 // Load arguments descriptor into R10. |
1549 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); | 1565 __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset())); |
1550 | 1566 |
1551 // Get function and call it, if possible. | 1567 // Get function and call it, if possible. |
1552 __ movq(RAX, Address(R12, target_offset)); | 1568 __ movq(RAX, Address(R12, target_offset)); |
1553 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); | 1569 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); |
1554 // RCX: Target instructions. | 1570 // RCX: Target instructions. |
1555 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1571 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
1556 __ jmp(RCX); | 1572 __ jmp(RCX); |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1959 | 1975 |
1960 __ movq(left, Address(RSP, 2 * kWordSize)); | 1976 __ movq(left, Address(RSP, 2 * kWordSize)); |
1961 __ movq(right, Address(RSP, 1 * kWordSize)); | 1977 __ movq(right, Address(RSP, 1 * kWordSize)); |
1962 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 1978 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
1963 __ ret(); | 1979 __ ret(); |
1964 } | 1980 } |
1965 | 1981 |
1966 } // namespace dart | 1982 } // namespace dart |
1967 | 1983 |
1968 #endif // defined TARGET_ARCH_X64 | 1984 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |