OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1086 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); | 1086 __ GetBuiltinEntry(rdx, Builtins::CALL_FUNCTION_PROXY); |
1087 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1087 __ call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1088 RelocInfo::CODE_TARGET); | 1088 RelocInfo::CODE_TARGET); |
1089 | 1089 |
1090 // Leave internal frame. | 1090 // Leave internal frame. |
1091 } | 1091 } |
1092 __ ret(3 * kPointerSize); // remove this, receiver, and arguments | 1092 __ ret(3 * kPointerSize); // remove this, receiver, and arguments |
1093 } | 1093 } |
1094 | 1094 |
1095 | 1095 |
1096 // Allocate an empty JSArray. The allocated array is put into the result | |
1097 // register. If the parameter initial_capacity is larger than zero an elements | |
1098 // backing store is allocated with this size and filled with the hole values. | |
1099 // Otherwise the elements backing store is set to the empty FixedArray. | |
1100 static void AllocateEmptyJSArray(MacroAssembler* masm, | |
1101 Register array_function, | |
1102 Register result, | |
1103 Register scratch1, | |
1104 Register scratch2, | |
1105 Register scratch3, | |
1106 Label* gc_required) { | |
1107 const int initial_capacity = JSArray::kPreallocatedArrayElements; | |
1108 STATIC_ASSERT(initial_capacity >= 0); | |
1109 | |
1110 __ LoadInitialArrayMap(array_function, scratch2, scratch1, false); | |
1111 | |
1112 // Allocate the JSArray object together with space for a fixed array with the | |
1113 // requested elements. | |
1114 int size = JSArray::kSize; | |
1115 if (initial_capacity > 0) { | |
1116 size += FixedArray::SizeFor(initial_capacity); | |
1117 } | |
1118 __ Allocate(size, result, scratch2, scratch3, gc_required, TAG_OBJECT); | |
1119 | |
1120 // Allocated the JSArray. Now initialize the fields except for the elements | |
1121 // array. | |
1122 // result: JSObject | |
1123 // scratch1: initial map | |
1124 // scratch2: start of next object | |
1125 Factory* factory = masm->isolate()->factory(); | |
1126 __ movq(FieldOperand(result, JSObject::kMapOffset), scratch1); | |
1127 __ Move(FieldOperand(result, JSArray::kPropertiesOffset), | |
1128 factory->empty_fixed_array()); | |
1129 // Field JSArray::kElementsOffset is initialized later. | |
1130 __ Move(FieldOperand(result, JSArray::kLengthOffset), Smi::FromInt(0)); | |
1131 | |
1132 // If no storage is requested for the elements array just set the empty | |
1133 // fixed array. | |
1134 if (initial_capacity == 0) { | |
1135 __ Move(FieldOperand(result, JSArray::kElementsOffset), | |
1136 factory->empty_fixed_array()); | |
1137 return; | |
1138 } | |
1139 | |
1140 // Calculate the location of the elements array and set elements array member | |
1141 // of the JSArray. | |
1142 // result: JSObject | |
1143 // scratch2: start of next object | |
1144 __ lea(scratch1, Operand(result, JSArray::kSize)); | |
1145 __ movq(FieldOperand(result, JSArray::kElementsOffset), scratch1); | |
1146 | |
1147 // Initialize the FixedArray and fill it with holes. FixedArray length is | |
1148 // stored as a smi. | |
1149 // result: JSObject | |
1150 // scratch1: elements array | |
1151 // scratch2: start of next object | |
1152 __ Move(FieldOperand(scratch1, HeapObject::kMapOffset), | |
1153 factory->fixed_array_map()); | |
1154 __ Move(FieldOperand(scratch1, FixedArray::kLengthOffset), | |
1155 Smi::FromInt(initial_capacity)); | |
1156 | |
1157 // Fill the FixedArray with the hole value. Inline the code if short. | |
1158 // Reconsider loop unfolding if kPreallocatedArrayElements gets changed. | |
1159 static const int kLoopUnfoldLimit = 4; | |
1160 __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); | |
1161 if (initial_capacity <= kLoopUnfoldLimit) { | |
1162 // Use a scratch register here to have only one reloc info when unfolding | |
1163 // the loop. | |
1164 for (int i = 0; i < initial_capacity; i++) { | |
1165 __ movq(FieldOperand(scratch1, | |
1166 FixedArray::kHeaderSize + i * kPointerSize), | |
1167 scratch3); | |
1168 } | |
1169 } else { | |
1170 Label loop, entry; | |
1171 __ movq(scratch2, Immediate(initial_capacity)); | |
1172 __ jmp(&entry); | |
1173 __ bind(&loop); | |
1174 __ movq(FieldOperand(scratch1, | |
1175 scratch2, | |
1176 times_pointer_size, | |
1177 FixedArray::kHeaderSize), | |
1178 scratch3); | |
1179 __ bind(&entry); | |
1180 __ decq(scratch2); | |
1181 __ j(not_sign, &loop); | |
1182 } | |
1183 } | |
1184 | |
1185 | |
1186 // Allocate a JSArray with the number of elements stored in a register. The | |
1187 // register array_function holds the built-in Array function and the register | |
1188 // array_size holds the size of the array as a smi. The allocated array is put | |
1189 // into the result register and beginning and end of the FixedArray elements | |
1190 // storage is put into registers elements_array and elements_array_end (see | |
1191 // below for when that is not the case). If the parameter fill_with_holes is | |
1192 // true the allocated elements backing store is filled with the hole values | |
1193 // otherwise it is left uninitialized. When the backing store is filled the | |
1194 // register elements_array is scratched. | |
1195 static void AllocateJSArray(MacroAssembler* masm, | |
1196 Register array_function, // Array function. | |
1197 Register array_size, // As a smi, cannot be 0. | |
1198 Register result, | |
1199 Register elements_array, | |
1200 Register elements_array_end, | |
1201 Register scratch, | |
1202 bool fill_with_hole, | |
1203 Label* gc_required) { | |
1204 __ LoadInitialArrayMap(array_function, scratch, | |
1205 elements_array, fill_with_hole); | |
1206 | |
1207 if (FLAG_debug_code) { // Assert that array size is not zero. | |
1208 __ testq(array_size, array_size); | |
1209 __ Assert(not_zero, "array size is unexpectedly 0"); | |
1210 } | |
1211 | |
1212 // Allocate the JSArray object together with space for a FixedArray with the | |
1213 // requested elements. | |
1214 SmiIndex index = | |
1215 masm->SmiToIndex(kScratchRegister, array_size, kPointerSizeLog2); | |
1216 __ Allocate(JSArray::kSize + FixedArray::kHeaderSize, | |
1217 index.scale, | |
1218 index.reg, | |
1219 result, | |
1220 elements_array_end, | |
1221 scratch, | |
1222 gc_required, | |
1223 TAG_OBJECT); | |
1224 | |
1225 // Allocated the JSArray. Now initialize the fields except for the elements | |
1226 // array. | |
1227 // result: JSObject | |
1228 // elements_array: initial map | |
1229 // elements_array_end: start of next object | |
1230 // array_size: size of array (smi) | |
1231 Factory* factory = masm->isolate()->factory(); | |
1232 __ movq(FieldOperand(result, JSObject::kMapOffset), elements_array); | |
1233 __ Move(elements_array, factory->empty_fixed_array()); | |
1234 __ movq(FieldOperand(result, JSArray::kPropertiesOffset), elements_array); | |
1235 // Field JSArray::kElementsOffset is initialized later. | |
1236 __ movq(FieldOperand(result, JSArray::kLengthOffset), array_size); | |
1237 | |
1238 // Calculate the location of the elements array and set elements array member | |
1239 // of the JSArray. | |
1240 // result: JSObject | |
1241 // elements_array_end: start of next object | |
1242 // array_size: size of array (smi) | |
1243 __ lea(elements_array, Operand(result, JSArray::kSize)); | |
1244 __ movq(FieldOperand(result, JSArray::kElementsOffset), elements_array); | |
1245 | |
1246 // Initialize the fixed array. FixedArray length is stored as a smi. | |
1247 // result: JSObject | |
1248 // elements_array: elements array | |
1249 // elements_array_end: start of next object | |
1250 // array_size: size of array (smi) | |
1251 __ Move(FieldOperand(elements_array, JSObject::kMapOffset), | |
1252 factory->fixed_array_map()); | |
1253 // For non-empty JSArrays the length of the FixedArray and the JSArray is the | |
1254 // same. | |
1255 __ movq(FieldOperand(elements_array, FixedArray::kLengthOffset), array_size); | |
1256 | |
1257 // Fill the allocated FixedArray with the hole value if requested. | |
1258 // result: JSObject | |
1259 // elements_array: elements array | |
1260 // elements_array_end: start of next object | |
1261 if (fill_with_hole) { | |
1262 Label loop, entry; | |
1263 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | |
1264 __ lea(elements_array, Operand(elements_array, | |
1265 FixedArray::kHeaderSize - kHeapObjectTag)); | |
1266 __ jmp(&entry); | |
1267 __ bind(&loop); | |
1268 __ movq(Operand(elements_array, 0), scratch); | |
1269 __ addq(elements_array, Immediate(kPointerSize)); | |
1270 __ bind(&entry); | |
1271 __ cmpq(elements_array, elements_array_end); | |
1272 __ j(below, &loop); | |
1273 } | |
1274 } | |
1275 | |
1276 | |
1277 // Create a new array for the built-in Array function. This function allocates | |
1278 // the JSArray object and the FixedArray elements array and initializes these. | |
1279 // If the Array cannot be constructed in native code the runtime is called. This | |
1280 // function assumes the following state: | |
1281 // rdi: constructor (built-in Array function) | |
1282 // rax: argc | |
1283 // rsp[0]: return address | |
1284 // rsp[8]: last argument | |
1285 // This function is used for both construct and normal calls of Array. The only | |
1286 // difference between handling a construct call and a normal call is that for a | |
1287 // construct call the constructor function in rdi needs to be preserved for | |
1288 // entering the generic code. In both cases argc in rax needs to be preserved. | |
1289 // Both registers are preserved by this code so no need to differentiate between | |
1290 // a construct call and a normal call. | |
1291 void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code) { | |
1292 Label argc_one_or_more, argc_two_or_more, empty_array, not_empty_array, | |
1293 has_non_smi_element, finish, cant_transition_map, not_double; | |
1294 | |
1295 // Check for array construction with zero arguments. | |
1296 __ testq(rax, rax); | |
1297 __ j(not_zero, &argc_one_or_more); | |
1298 | |
1299 __ bind(&empty_array); | |
1300 // Handle construction of an empty array. | |
1301 AllocateEmptyJSArray(masm, | |
1302 rdi, | |
1303 rbx, | |
1304 rcx, | |
1305 rdx, | |
1306 r8, | |
1307 call_generic_code); | |
1308 Counters* counters = masm->isolate()->counters(); | |
1309 __ IncrementCounter(counters->array_function_native(), 1); | |
1310 __ movq(rax, rbx); | |
1311 __ ret(kPointerSize); | |
1312 | |
1313 // Check for one argument. Bail out if argument is not smi or if it is | |
1314 // negative. | |
1315 __ bind(&argc_one_or_more); | |
1316 __ cmpq(rax, Immediate(1)); | |
1317 __ j(not_equal, &argc_two_or_more); | |
1318 __ movq(rdx, Operand(rsp, kPointerSize)); // Get the argument from the stack. | |
1319 | |
1320 __ SmiTest(rdx); | |
1321 __ j(not_zero, ¬_empty_array); | |
1322 __ pop(r8); // Adjust stack. | |
1323 __ Drop(1); | |
1324 __ push(r8); | |
1325 __ movq(rax, Immediate(0)); // Treat this as a call with argc of zero. | |
1326 __ jmp(&empty_array); | |
1327 | |
1328 __ bind(¬_empty_array); | |
1329 __ JumpUnlessNonNegativeSmi(rdx, call_generic_code); | |
1330 | |
1331 // Handle construction of an empty array of a certain size. Bail out if size | |
1332 // is to large to actually allocate an elements array. | |
1333 __ SmiCompare(rdx, Smi::FromInt(JSObject::kInitialMaxFastElementArray)); | |
1334 __ j(greater_equal, call_generic_code); | |
1335 | |
1336 // rax: argc | |
1337 // rdx: array_size (smi) | |
1338 // rdi: constructor | |
1339 // esp[0]: return address | |
1340 // esp[8]: argument | |
1341 AllocateJSArray(masm, | |
1342 rdi, | |
1343 rdx, | |
1344 rbx, | |
1345 rcx, | |
1346 r8, | |
1347 r9, | |
1348 true, | |
1349 call_generic_code); | |
1350 __ IncrementCounter(counters->array_function_native(), 1); | |
1351 __ movq(rax, rbx); | |
1352 __ ret(2 * kPointerSize); | |
1353 | |
1354 // Handle construction of an array from a list of arguments. | |
1355 __ bind(&argc_two_or_more); | |
1356 __ movq(rdx, rax); | |
1357 __ Integer32ToSmi(rdx, rdx); // Convet argc to a smi. | |
1358 // rax: argc | |
1359 // rdx: array_size (smi) | |
1360 // rdi: constructor | |
1361 // esp[0] : return address | |
1362 // esp[8] : last argument | |
1363 AllocateJSArray(masm, | |
1364 rdi, | |
1365 rdx, | |
1366 rbx, | |
1367 rcx, | |
1368 r8, | |
1369 r9, | |
1370 false, | |
1371 call_generic_code); | |
1372 __ IncrementCounter(counters->array_function_native(), 1); | |
1373 | |
1374 // rax: argc | |
1375 // rbx: JSArray | |
1376 // rcx: elements_array | |
1377 // r8: elements_array_end (untagged) | |
1378 // esp[0]: return address | |
1379 // esp[8]: last argument | |
1380 | |
1381 // Location of the last argument | |
1382 __ lea(r9, Operand(rsp, kPointerSize)); | |
1383 | |
1384 // Location of the first array element (Parameter fill_with_holes to | |
1385 // AllocateJSArrayis false, so the FixedArray is returned in rcx). | |
1386 __ lea(rdx, Operand(rcx, FixedArray::kHeaderSize - kHeapObjectTag)); | |
1387 | |
1388 // rax: argc | |
1389 // rbx: JSArray | |
1390 // rdx: location of the first array element | |
1391 // r9: location of the last argument | |
1392 // esp[0]: return address | |
1393 // esp[8]: last argument | |
1394 Label loop, entry; | |
1395 __ movq(rcx, rax); | |
1396 __ jmp(&entry); | |
1397 __ bind(&loop); | |
1398 __ movq(r8, Operand(r9, rcx, times_pointer_size, 0)); | |
1399 if (FLAG_smi_only_arrays) { | |
1400 __ JumpIfNotSmi(r8, &has_non_smi_element); | |
1401 } | |
1402 __ movq(Operand(rdx, 0), r8); | |
1403 __ addq(rdx, Immediate(kPointerSize)); | |
1404 __ bind(&entry); | |
1405 __ decq(rcx); | |
1406 __ j(greater_equal, &loop); | |
1407 | |
1408 // Remove caller arguments from the stack and return. | |
1409 // rax: argc | |
1410 // rbx: JSArray | |
1411 // esp[0]: return address | |
1412 // esp[8]: last argument | |
1413 __ bind(&finish); | |
1414 __ pop(rcx); | |
1415 __ lea(rsp, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize)); | |
1416 __ push(rcx); | |
1417 __ movq(rax, rbx); | |
1418 __ ret(0); | |
1419 | |
1420 __ bind(&has_non_smi_element); | |
1421 // Double values are handled by the runtime. | |
1422 __ CheckMap(r8, | |
1423 masm->isolate()->factory()->heap_number_map(), | |
1424 ¬_double, | |
1425 DONT_DO_SMI_CHECK); | |
1426 __ bind(&cant_transition_map); | |
1427 __ UndoAllocationInNewSpace(rbx); | |
1428 __ jmp(call_generic_code); | |
1429 | |
1430 __ bind(¬_double); | |
1431 // Transition FAST_SMI_ELEMENTS to FAST_ELEMENTS. | |
1432 // rbx: JSArray | |
1433 __ movq(r11, FieldOperand(rbx, HeapObject::kMapOffset)); | |
1434 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | |
1435 FAST_ELEMENTS, | |
1436 r11, | |
1437 kScratchRegister, | |
1438 &cant_transition_map); | |
1439 | |
1440 __ movq(FieldOperand(rbx, HeapObject::kMapOffset), r11); | |
1441 __ RecordWriteField(rbx, HeapObject::kMapOffset, r11, r8, | |
1442 kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK); | |
1443 | |
1444 // Finish the array initialization loop. | |
1445 Label loop2; | |
1446 __ bind(&loop2); | |
1447 __ movq(r8, Operand(r9, rcx, times_pointer_size, 0)); | |
1448 __ movq(Operand(rdx, 0), r8); | |
1449 __ addq(rdx, Immediate(kPointerSize)); | |
1450 __ decq(rcx); | |
1451 __ j(greater_equal, &loop2); | |
1452 __ jmp(&finish); | |
1453 } | |
1454 | |
1455 | |
1456 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { | 1096 void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) { |
1457 // ----------- S t a t e ------------- | 1097 // ----------- S t a t e ------------- |
1458 // -- rax : argc | 1098 // -- rax : argc |
1459 // -- rsp[0] : return address | 1099 // -- rsp[0] : return address |
1460 // -- rsp[8] : last argument | 1100 // -- rsp[8] : last argument |
1461 // ----------------------------------- | 1101 // ----------------------------------- |
1462 Label generic_array_code; | 1102 Label generic_array_code; |
1463 | 1103 |
1464 // Get the InternalArray function. | 1104 // Get the InternalArray function. |
1465 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi); | 1105 __ LoadGlobalFunction(Context::INTERNAL_ARRAY_FUNCTION_INDEX, rdi); |
1466 | 1106 |
1467 if (FLAG_debug_code) { | 1107 if (FLAG_debug_code) { |
1468 // Initial map for the builtin InternalArray functions should be maps. | 1108 // Initial map for the builtin InternalArray functions should be maps. |
1469 __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); | 1109 __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); |
1470 // Will both indicate a NULL and a Smi. | 1110 // Will both indicate a NULL and a Smi. |
1471 STATIC_ASSERT(kSmiTag == 0); | 1111 STATIC_ASSERT(kSmiTag == 0); |
1472 Condition not_smi = NegateCondition(masm->CheckSmi(rbx)); | 1112 Condition not_smi = NegateCondition(masm->CheckSmi(rbx)); |
1473 __ Check(not_smi, "Unexpected initial map for InternalArray function"); | 1113 __ Check(not_smi, "Unexpected initial map for InternalArray function"); |
1474 __ CmpObjectType(rbx, MAP_TYPE, rcx); | 1114 __ CmpObjectType(rbx, MAP_TYPE, rcx); |
1475 __ Check(equal, "Unexpected initial map for InternalArray function"); | 1115 __ Check(equal, "Unexpected initial map for InternalArray function"); |
1476 } | 1116 } |
1477 | 1117 |
1478 // Run the native code for the InternalArray function called as a normal | 1118 // Run the native code for the InternalArray function called as a normal |
1479 // function. | 1119 // function. |
1480 if (FLAG_optimize_constructed_arrays) { | 1120 // tail call a stub |
1481 // tail call a stub | 1121 InternalArrayConstructorStub stub(masm->isolate()); |
1482 InternalArrayConstructorStub stub(masm->isolate()); | 1122 __ TailCallStub(&stub); |
1483 __ TailCallStub(&stub); | |
1484 } else { | |
1485 ArrayNativeCode(masm, &generic_array_code); | |
1486 | |
1487 // Jump to the generic array code in case the specialized code cannot handle | |
1488 // the construction. | |
1489 __ bind(&generic_array_code); | |
1490 Handle<Code> array_code = | |
1491 masm->isolate()->builtins()->InternalArrayCodeGeneric(); | |
1492 __ Jump(array_code, RelocInfo::CODE_TARGET); | |
1493 } | |
1494 } | 1123 } |
1495 | 1124 |
1496 | 1125 |
1497 void Builtins::Generate_ArrayCode(MacroAssembler* masm) { | 1126 void Builtins::Generate_ArrayCode(MacroAssembler* masm) { |
1498 // ----------- S t a t e ------------- | 1127 // ----------- S t a t e ------------- |
1499 // -- rax : argc | 1128 // -- rax : argc |
1500 // -- rsp[0] : return address | 1129 // -- rsp[0] : return address |
1501 // -- rsp[8] : last argument | 1130 // -- rsp[8] : last argument |
1502 // ----------------------------------- | 1131 // ----------------------------------- |
1503 Label generic_array_code; | 1132 Label generic_array_code; |
1504 | 1133 |
1505 // Get the Array function. | 1134 // Get the Array function. |
1506 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rdi); | 1135 __ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, rdi); |
1507 | 1136 |
1508 if (FLAG_debug_code) { | 1137 if (FLAG_debug_code) { |
1509 // Initial map for the builtin Array functions should be maps. | 1138 // Initial map for the builtin Array functions should be maps. |
1510 __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); | 1139 __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); |
1511 // Will both indicate a NULL and a Smi. | 1140 // Will both indicate a NULL and a Smi. |
1512 STATIC_ASSERT(kSmiTag == 0); | 1141 STATIC_ASSERT(kSmiTag == 0); |
1513 Condition not_smi = NegateCondition(masm->CheckSmi(rbx)); | 1142 Condition not_smi = NegateCondition(masm->CheckSmi(rbx)); |
1514 __ Check(not_smi, "Unexpected initial map for Array function"); | 1143 __ Check(not_smi, "Unexpected initial map for Array function"); |
1515 __ CmpObjectType(rbx, MAP_TYPE, rcx); | 1144 __ CmpObjectType(rbx, MAP_TYPE, rcx); |
1516 __ Check(equal, "Unexpected initial map for Array function"); | 1145 __ Check(equal, "Unexpected initial map for Array function"); |
1517 } | 1146 } |
1518 | 1147 |
1519 // Run the native code for the Array function called as a normal function. | 1148 // Run the native code for the Array function called as a normal function. |
1520 if (FLAG_optimize_constructed_arrays) { | 1149 // tail call a stub |
1521 // tail call a stub | 1150 Handle<Object> undefined_sentinel( |
1522 Handle<Object> undefined_sentinel( | 1151 masm->isolate()->heap()->undefined_value(), |
1523 masm->isolate()->heap()->undefined_value(), | 1152 masm->isolate()); |
1524 masm->isolate()); | 1153 __ Move(rbx, undefined_sentinel); |
1525 __ Move(rbx, undefined_sentinel); | 1154 ArrayConstructorStub stub(masm->isolate()); |
1526 ArrayConstructorStub stub(masm->isolate()); | 1155 __ TailCallStub(&stub); |
1527 __ TailCallStub(&stub); | |
1528 } else { | |
1529 ArrayNativeCode(masm, &generic_array_code); | |
1530 | |
1531 // Jump to the generic array code in case the specialized code cannot handle | |
1532 // the construction. | |
1533 __ bind(&generic_array_code); | |
1534 Handle<Code> array_code = | |
1535 masm->isolate()->builtins()->ArrayCodeGeneric(); | |
1536 __ Jump(array_code, RelocInfo::CODE_TARGET); | |
1537 } | |
1538 } | 1156 } |
1539 | 1157 |
1540 | 1158 |
1541 void Builtins::Generate_CommonArrayConstructCode(MacroAssembler* masm) { | |
1542 // ----------- S t a t e ------------- | |
1543 // -- rax : argc | |
1544 // -- rdi : constructor | |
1545 // -- rsp[0] : return address | |
1546 // -- rsp[8] : last argument | |
1547 // ----------------------------------- | |
1548 if (FLAG_debug_code) { | |
1549 // The array construct code is only set for the builtin and internal | |
1550 // Array functions which always have a map. | |
1551 | |
1552 // Initial map for the builtin Array function should be a map. | |
1553 __ movq(rcx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); | |
1554 // Will both indicate a NULL and a Smi. | |
1555 STATIC_ASSERT(kSmiTag == 0); | |
1556 Condition not_smi = NegateCondition(masm->CheckSmi(rcx)); | |
1557 __ Check(not_smi, "Unexpected initial map for Array function"); | |
1558 __ CmpObjectType(rcx, MAP_TYPE, rcx); | |
1559 __ Check(equal, "Unexpected initial map for Array function"); | |
1560 } | |
1561 | |
1562 Label generic_constructor; | |
1563 // Run the native code for the Array function called as constructor. | |
1564 ArrayNativeCode(masm, &generic_constructor); | |
1565 // Jump to the generic construct code in case the specialized code cannot | |
1566 // handle the construction. | |
1567 __ bind(&generic_constructor); | |
1568 Handle<Code> generic_construct_stub = | |
1569 masm->isolate()->builtins()->JSConstructStubGeneric(); | |
1570 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | |
1571 } | |
1572 | |
1573 | |
1574 | |
1575 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { | 1159 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { |
1576 // ----------- S t a t e ------------- | 1160 // ----------- S t a t e ------------- |
1577 // -- rax : number of arguments | 1161 // -- rax : number of arguments |
1578 // -- rdi : constructor function | 1162 // -- rdi : constructor function |
1579 // -- rsp[0] : return address | 1163 // -- rsp[0] : return address |
1580 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1164 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
1581 // -- rsp[(argc + 1) * 8] : receiver | 1165 // -- rsp[(argc + 1) * 8] : receiver |
1582 // ----------------------------------- | 1166 // ----------------------------------- |
1583 Counters* counters = masm->isolate()->counters(); | 1167 Counters* counters = masm->isolate()->counters(); |
1584 __ IncrementCounter(counters->string_ctor_calls(), 1); | 1168 __ IncrementCounter(counters->string_ctor_calls(), 1); |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1848 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); | 1432 Deoptimizer::EntryGenerator generator(masm, Deoptimizer::OSR); |
1849 generator.Generate(); | 1433 generator.Generate(); |
1850 } | 1434 } |
1851 | 1435 |
1852 | 1436 |
1853 #undef __ | 1437 #undef __ |
1854 | 1438 |
1855 } } // namespace v8::internal | 1439 } } // namespace v8::internal |
1856 | 1440 |
1857 #endif // V8_TARGET_ARCH_X64 | 1441 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |