| 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 |