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