OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 Smi::FromInt(PropertyDetails::TypeField::mask())); | 371 Smi::FromInt(PropertyDetails::TypeField::mask())); |
372 __ j(not_zero, miss); | 372 __ j(not_zero, miss); |
373 | 373 |
374 // Get the value at the masked, scaled index. | 374 // Get the value at the masked, scaled index. |
375 const int kValueOffset = | 375 const int kValueOffset = |
376 NumberDictionary::kElementsStartOffset + kPointerSize; | 376 NumberDictionary::kElementsStartOffset + kPointerSize; |
377 __ movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | 377 __ movq(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); |
378 } | 378 } |
379 | 379 |
380 | 380 |
381 // One byte opcode for test rax,0xXXXXXXXX. | 381 // The offset from the inlined patch site to the start of the inlined |
382 static const byte kTestEaxByte = 0xA9; | 382 // load instruction. |
| 383 const int LoadIC::kOffsetToLoadInstruction = 20; |
383 | 384 |
384 | 385 |
385 static bool PatchInlinedMapCheck(Address address, Object* map) { | 386 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { |
386 if (V8::UseCrankshaft()) return false; | 387 // ----------- S t a t e ------------- |
| 388 // -- rax : receiver |
| 389 // -- rcx : name |
| 390 // -- rsp[0] : return address |
| 391 // ----------------------------------- |
| 392 Label miss; |
387 | 393 |
388 // Arguments are address of start of call sequence that called | 394 StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss); |
389 // the IC, | 395 __ bind(&miss); |
390 Address test_instruction_address = | 396 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
391 address + Assembler::kCallTargetAddressOffset; | |
392 // The keyed load has a fast inlined case if the IC call instruction | |
393 // is immediately followed by a test instruction. | |
394 if (*test_instruction_address != kTestEaxByte) return false; | |
395 | |
396 // Fetch the offset from the test instruction to the map compare | |
397 // instructions (starting with the 64-bit immediate mov of the map | |
398 // address). This offset is stored in the last 4 bytes of the 5 | |
399 // byte test instruction. | |
400 Address delta_address = test_instruction_address + 1; | |
401 int delta = *reinterpret_cast<int*>(delta_address); | |
402 // Compute the map address. The map address is in the last 8 bytes | |
403 // of the 10-byte immediate mov instruction (incl. REX prefix), so we add 2 | |
404 // to the offset to get the map address. | |
405 Address map_address = test_instruction_address + delta + 2; | |
406 // Patch the map check. | |
407 *(reinterpret_cast<Object**>(map_address)) = map; | |
408 return true; | |
409 } | 397 } |
410 | 398 |
411 | 399 |
412 bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { | 400 void LoadIC::GenerateStringLength(MacroAssembler* masm) { |
413 return PatchInlinedMapCheck(address, map); | 401 // ----------- S t a t e ------------- |
| 402 // -- rax : receiver |
| 403 // -- rcx : name |
| 404 // -- rsp[0] : return address |
| 405 // ----------------------------------- |
| 406 Label miss; |
| 407 |
| 408 StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss); |
| 409 __ bind(&miss); |
| 410 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
414 } | 411 } |
415 | 412 |
416 | 413 |
417 bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { | 414 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { |
418 return PatchInlinedMapCheck(address, map); | 415 // ----------- S t a t e ------------- |
| 416 // -- rax : receiver |
| 417 // -- rcx : name |
| 418 // -- rsp[0] : return address |
| 419 // ----------------------------------- |
| 420 Label miss; |
| 421 |
| 422 StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss); |
| 423 __ bind(&miss); |
| 424 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); |
419 } | 425 } |
420 | 426 |
421 | 427 |
422 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { | |
423 // ----------- S t a t e ------------- | |
424 // -- rax : key | |
425 // -- rdx : receiver | |
426 // -- rsp[0] : return address | |
427 // ----------------------------------- | |
428 | |
429 __ IncrementCounter(&Counters::keyed_load_miss, 1); | |
430 | |
431 __ pop(rbx); | |
432 __ push(rdx); // receiver | |
433 __ push(rax); // name | |
434 __ push(rbx); // return address | |
435 | |
436 // Perform tail call to the entry. | |
437 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); | |
438 __ TailCallExternalReference(ref, 2, 1); | |
439 } | |
440 | |
441 | |
442 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | |
443 // ----------- S t a t e ------------- | |
444 // -- rax : key | |
445 // -- rdx : receiver | |
446 // -- rsp[0] : return address | |
447 // ----------------------------------- | |
448 | |
449 __ pop(rbx); | |
450 __ push(rdx); // receiver | |
451 __ push(rax); // name | |
452 __ push(rbx); // return address | |
453 | |
454 // Perform tail call to the entry. | |
455 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | |
456 } | |
457 | |
458 | |
459 // Checks the receiver for special cases (value type, slow case bits). | 428 // Checks the receiver for special cases (value type, slow case bits). |
460 // Falls through for regular JS object. | 429 // Falls through for regular JS object. |
461 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, | 430 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, |
462 Register receiver, | 431 Register receiver, |
463 Register map, | 432 Register map, |
464 int interceptor_bit, | 433 int interceptor_bit, |
465 Label* slow) { | 434 Label* slow) { |
466 // Register use: | 435 // Register use: |
467 // receiver - holds the receiver and is unchanged. | 436 // receiver - holds the receiver and is unchanged. |
468 // Scratch registers: | 437 // Scratch registers: |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
916 | 885 |
917 // Perform tail call to the entry. | 886 // Perform tail call to the entry. |
918 __ TailCallExternalReference(ExternalReference( | 887 __ TailCallExternalReference(ExternalReference( |
919 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); | 888 IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1); |
920 | 889 |
921 __ bind(&slow); | 890 __ bind(&slow); |
922 GenerateMiss(masm); | 891 GenerateMiss(masm); |
923 } | 892 } |
924 | 893 |
925 | 894 |
926 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | |
927 // ----------- S t a t e ------------- | |
928 // -- rax : value | |
929 // -- rcx : key | |
930 // -- rdx : receiver | |
931 // -- rsp[0] : return address | |
932 // ----------------------------------- | |
933 | |
934 __ pop(rbx); | |
935 __ push(rdx); // receiver | |
936 __ push(rcx); // key | |
937 __ push(rax); // value | |
938 __ push(rbx); // return address | |
939 | |
940 // Do tail-call to runtime routine. | |
941 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); | |
942 __ TailCallExternalReference(ref, 3, 1); | |
943 } | |
944 | |
945 | |
946 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { | |
947 // ----------- S t a t e ------------- | |
948 // -- rax : value | |
949 // -- rcx : key | |
950 // -- rdx : receiver | |
951 // -- rsp[0] : return address | |
952 // ----------------------------------- | |
953 | |
954 __ pop(rbx); | |
955 __ push(rdx); // receiver | |
956 __ push(rcx); // key | |
957 __ push(rax); // value | |
958 __ push(rbx); // return address | |
959 | |
960 // Do tail-call to runtime routine. | |
961 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | |
962 } | |
963 | |
964 | |
965 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { | 895 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) { |
966 // ----------- S t a t e ------------- | 896 // ----------- S t a t e ------------- |
967 // -- rax : value | 897 // -- rax : value |
968 // -- rcx : key | 898 // -- rcx : key |
969 // -- rdx : receiver | 899 // -- rdx : receiver |
970 // -- rsp[0] : return address | 900 // -- rsp[0] : return address |
971 // ----------------------------------- | 901 // ----------------------------------- |
972 Label slow, slow_with_tagged_index, fast, array, extra, check_pixel_array; | 902 Label slow, slow_with_tagged_index, fast, array, extra, check_pixel_array; |
973 | 903 |
974 // Check that the object isn't a smi. | 904 // Check that the object isn't a smi. |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1229 } | 1159 } |
1230 __ ret(0); | 1160 __ ret(0); |
1231 } | 1161 } |
1232 | 1162 |
1233 // Slow case: call runtime. | 1163 // Slow case: call runtime. |
1234 __ bind(&slow); | 1164 __ bind(&slow); |
1235 GenerateRuntimeSetProperty(masm); | 1165 GenerateRuntimeSetProperty(masm); |
1236 } | 1166 } |
1237 | 1167 |
1238 | 1168 |
1239 // Defined in ic.cc. | |
1240 Object* CallIC_Miss(Arguments args); | |
1241 | |
1242 | |
1243 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { | |
1244 // ----------- S t a t e ------------- | |
1245 // rcx : function name | |
1246 // rsp[0] : return address | |
1247 // rsp[8] : argument argc | |
1248 // rsp[16] : argument argc - 1 | |
1249 // ... | |
1250 // rsp[argc * 8] : argument 1 | |
1251 // rsp[(argc + 1) * 8] : argument 0 = receiver | |
1252 // ----------------------------------- | |
1253 | |
1254 if (id == IC::kCallIC_Miss) { | |
1255 __ IncrementCounter(&Counters::call_miss, 1); | |
1256 } else { | |
1257 __ IncrementCounter(&Counters::keyed_call_miss, 1); | |
1258 } | |
1259 | |
1260 // Get the receiver of the function from the stack; 1 ~ return address. | |
1261 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | |
1262 | |
1263 // Enter an internal frame. | |
1264 __ EnterInternalFrame(); | |
1265 | |
1266 // Push the receiver and the name of the function. | |
1267 __ push(rdx); | |
1268 __ push(rcx); | |
1269 | |
1270 // Call the entry. | |
1271 CEntryStub stub(1); | |
1272 __ movq(rax, Immediate(2)); | |
1273 __ movq(rbx, ExternalReference(IC_Utility(id))); | |
1274 __ CallStub(&stub); | |
1275 | |
1276 // Move result to rdi and exit the internal frame. | |
1277 __ movq(rdi, rax); | |
1278 __ LeaveInternalFrame(); | |
1279 | |
1280 // Check if the receiver is a global object of some sort. | |
1281 // This can happen only for regular CallIC but not KeyedCallIC. | |
1282 if (id == IC::kCallIC_Miss) { | |
1283 Label invoke, global; | |
1284 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver | |
1285 __ JumpIfSmi(rdx, &invoke); | |
1286 __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx); | |
1287 __ j(equal, &global); | |
1288 __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE); | |
1289 __ j(not_equal, &invoke); | |
1290 | |
1291 // Patch the receiver on the stack. | |
1292 __ bind(&global); | |
1293 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | |
1294 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | |
1295 __ bind(&invoke); | |
1296 } | |
1297 | |
1298 // Invoke the function. | |
1299 ParameterCount actual(argc); | |
1300 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); | |
1301 } | |
1302 | |
1303 | |
1304 // The generated code does not accept smi keys. | 1169 // The generated code does not accept smi keys. |
1305 // The generated code falls through if both probes miss. | 1170 // The generated code falls through if both probes miss. |
1306 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, | 1171 static void GenerateMonomorphicCacheProbe(MacroAssembler* masm, |
1307 int argc, | 1172 int argc, |
1308 Code::Kind kind) { | 1173 Code::Kind kind) { |
1309 // ----------- S t a t e ------------- | 1174 // ----------- S t a t e ------------- |
1310 // rcx : function name | 1175 // rcx : function name |
1311 // rdx : receiver | 1176 // rdx : receiver |
1312 // ----------------------------------- | 1177 // ----------------------------------- |
1313 Label number, non_number, non_string, boolean, probe, miss; | 1178 Label number, non_number, non_string, boolean, probe, miss; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1402 // rax: elements | 1267 // rax: elements |
1403 // Search the dictionary placing the result in rdi. | 1268 // Search the dictionary placing the result in rdi. |
1404 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi); | 1269 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi); |
1405 | 1270 |
1406 GenerateFunctionTailCall(masm, argc, &miss); | 1271 GenerateFunctionTailCall(masm, argc, &miss); |
1407 | 1272 |
1408 __ bind(&miss); | 1273 __ bind(&miss); |
1409 } | 1274 } |
1410 | 1275 |
1411 | 1276 |
1412 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 1277 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { |
1413 // ----------- S t a t e ------------- | 1278 // ----------- S t a t e ------------- |
1414 // rcx : function name | 1279 // rcx : function name |
1415 // rsp[0] : return address | 1280 // rsp[0] : return address |
1416 // rsp[8] : argument argc | 1281 // rsp[8] : argument argc |
1417 // rsp[16] : argument argc - 1 | 1282 // rsp[16] : argument argc - 1 |
1418 // ... | 1283 // ... |
1419 // rsp[argc * 8] : argument 1 | 1284 // rsp[argc * 8] : argument 1 |
1420 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1285 // rsp[(argc + 1) * 8] : argument 0 = receiver |
1421 // ----------------------------------- | 1286 // ----------------------------------- |
1422 GenerateCallMiss(masm, argc, IC::kCallIC_Miss); | 1287 |
| 1288 if (id == IC::kCallIC_Miss) { |
| 1289 __ IncrementCounter(&Counters::call_miss, 1); |
| 1290 } else { |
| 1291 __ IncrementCounter(&Counters::keyed_call_miss, 1); |
| 1292 } |
| 1293 |
| 1294 // Get the receiver of the function from the stack; 1 ~ return address. |
| 1295 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1296 |
| 1297 // Enter an internal frame. |
| 1298 __ EnterInternalFrame(); |
| 1299 |
| 1300 // Push the receiver and the name of the function. |
| 1301 __ push(rdx); |
| 1302 __ push(rcx); |
| 1303 |
| 1304 // Call the entry. |
| 1305 CEntryStub stub(1); |
| 1306 __ movq(rax, Immediate(2)); |
| 1307 __ movq(rbx, ExternalReference(IC_Utility(id))); |
| 1308 __ CallStub(&stub); |
| 1309 |
| 1310 // Move result to rdi and exit the internal frame. |
| 1311 __ movq(rdi, rax); |
| 1312 __ LeaveInternalFrame(); |
| 1313 |
| 1314 // Check if the receiver is a global object of some sort. |
| 1315 // This can happen only for regular CallIC but not KeyedCallIC. |
| 1316 if (id == IC::kCallIC_Miss) { |
| 1317 Label invoke, global; |
| 1318 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver |
| 1319 __ JumpIfSmi(rdx, &invoke); |
| 1320 __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx); |
| 1321 __ j(equal, &global); |
| 1322 __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE); |
| 1323 __ j(not_equal, &invoke); |
| 1324 |
| 1325 // Patch the receiver on the stack. |
| 1326 __ bind(&global); |
| 1327 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 1328 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 1329 __ bind(&invoke); |
| 1330 } |
| 1331 |
| 1332 // Invoke the function. |
| 1333 ParameterCount actual(argc); |
| 1334 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); |
1423 } | 1335 } |
1424 | 1336 |
1425 | 1337 |
1426 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 1338 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
1427 // ----------- S t a t e ------------- | 1339 // ----------- S t a t e ------------- |
1428 // rcx : function name | 1340 // rcx : function name |
1429 // rsp[0] : return address | 1341 // rsp[0] : return address |
1430 // rsp[8] : argument argc | 1342 // rsp[8] : argument argc |
1431 // rsp[16] : argument argc - 1 | 1343 // rsp[16] : argument argc - 1 |
1432 // ... | 1344 // ... |
(...skipping 17 matching lines...) Expand all Loading... |
1450 // ... | 1362 // ... |
1451 // rsp[argc * 8] : argument 1 | 1363 // rsp[argc * 8] : argument 1 |
1452 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1364 // rsp[(argc + 1) * 8] : argument 0 = receiver |
1453 // ----------------------------------- | 1365 // ----------------------------------- |
1454 | 1366 |
1455 GenerateCallNormal(masm, argc); | 1367 GenerateCallNormal(masm, argc); |
1456 GenerateMiss(masm, argc); | 1368 GenerateMiss(masm, argc); |
1457 } | 1369 } |
1458 | 1370 |
1459 | 1371 |
1460 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 1372 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
1461 // ----------- S t a t e ------------- | 1373 // ----------- S t a t e ------------- |
1462 // rcx : function name | 1374 // rcx : function name |
1463 // rsp[0] : return address | 1375 // rsp[0] : return address |
1464 // rsp[8] : argument argc | 1376 // rsp[8] : argument argc |
1465 // rsp[16] : argument argc - 1 | 1377 // rsp[16] : argument argc - 1 |
1466 // ... | 1378 // ... |
1467 // rsp[argc * 8] : argument 1 | 1379 // rsp[argc * 8] : argument 1 |
1468 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1380 // rsp[(argc + 1) * 8] : argument 0 = receiver |
1469 // ----------------------------------- | 1381 // ----------------------------------- |
1470 | 1382 |
1471 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); | 1383 GenerateCallMiss(masm, argc, IC::kCallIC_Miss); |
1472 } | 1384 } |
1473 | 1385 |
1474 | 1386 |
1475 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 1387 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
1476 // ----------- S t a t e ------------- | 1388 // ----------- S t a t e ------------- |
1477 // rcx : function name | 1389 // rcx : function name |
1478 // rsp[0] : return address | 1390 // rsp[0] : return address |
1479 // rsp[8] : argument argc | 1391 // rsp[8] : argument argc |
1480 // rsp[16] : argument argc - 1 | 1392 // rsp[16] : argument argc - 1 |
1481 // ... | 1393 // ... |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1587 // ... | 1499 // ... |
1588 // rsp[argc * 8] : argument 1 | 1500 // rsp[argc * 8] : argument 1 |
1589 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1501 // rsp[(argc + 1) * 8] : argument 0 = receiver |
1590 // ----------------------------------- | 1502 // ----------------------------------- |
1591 | 1503 |
1592 GenerateCallNormal(masm, argc); | 1504 GenerateCallNormal(masm, argc); |
1593 GenerateMiss(masm, argc); | 1505 GenerateMiss(masm, argc); |
1594 } | 1506 } |
1595 | 1507 |
1596 | 1508 |
1597 // The offset from the inlined patch site to the start of the inlined | 1509 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
1598 // load instruction. | |
1599 const int LoadIC::kOffsetToLoadInstruction = 20; | |
1600 | |
1601 | |
1602 void LoadIC::GenerateMiss(MacroAssembler* masm) { | |
1603 // ----------- S t a t e ------------- | 1510 // ----------- S t a t e ------------- |
1604 // -- rax : receiver | 1511 // rcx : function name |
1605 // -- rcx : name | 1512 // rsp[0] : return address |
1606 // -- rsp[0] : return address | 1513 // rsp[8] : argument argc |
| 1514 // rsp[16] : argument argc - 1 |
| 1515 // ... |
| 1516 // rsp[argc * 8] : argument 1 |
| 1517 // rsp[(argc + 1) * 8] : argument 0 = receiver |
1607 // ----------------------------------- | 1518 // ----------------------------------- |
1608 | 1519 |
1609 __ IncrementCounter(&Counters::load_miss, 1); | 1520 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); |
1610 | |
1611 __ pop(rbx); | |
1612 __ push(rax); // receiver | |
1613 __ push(rcx); // name | |
1614 __ push(rbx); // return address | |
1615 | |
1616 // Perform tail call to the entry. | |
1617 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); | |
1618 __ TailCallExternalReference(ref, 2, 1); | |
1619 } | |
1620 | |
1621 | |
1622 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | |
1623 // ----------- S t a t e ------------- | |
1624 // -- rax : receiver | |
1625 // -- rcx : name | |
1626 // -- rsp[0] : return address | |
1627 // ----------------------------------- | |
1628 Label miss; | |
1629 | |
1630 StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss); | |
1631 __ bind(&miss); | |
1632 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | |
1633 } | |
1634 | |
1635 | |
1636 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { | |
1637 // ----------- S t a t e ------------- | |
1638 // -- rax : receiver | |
1639 // -- rcx : name | |
1640 // -- rsp[0] : return address | |
1641 // ----------------------------------- | |
1642 Label miss; | |
1643 | |
1644 StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss); | |
1645 __ bind(&miss); | |
1646 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | |
1647 } | 1521 } |
1648 | 1522 |
1649 | 1523 |
1650 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 1524 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
1651 // ----------- S t a t e ------------- | 1525 // ----------- S t a t e ------------- |
1652 // -- rax : receiver | 1526 // -- rax : receiver |
1653 // -- rcx : name | 1527 // -- rcx : name |
1654 // -- rsp[0] : return address | 1528 // -- rsp[0] : return address |
1655 // ----------------------------------- | 1529 // ----------------------------------- |
1656 | 1530 |
(...skipping 22 matching lines...) Expand all Loading... |
1679 // Search the dictionary placing the result in rax. | 1553 // Search the dictionary placing the result in rax. |
1680 GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax); | 1554 GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax); |
1681 __ ret(0); | 1555 __ ret(0); |
1682 | 1556 |
1683 // Cache miss: Jump to runtime. | 1557 // Cache miss: Jump to runtime. |
1684 __ bind(&miss); | 1558 __ bind(&miss); |
1685 GenerateMiss(masm); | 1559 GenerateMiss(masm); |
1686 } | 1560 } |
1687 | 1561 |
1688 | 1562 |
1689 void LoadIC::GenerateStringLength(MacroAssembler* masm) { | 1563 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
1690 // ----------- S t a t e ------------- | 1564 // ----------- S t a t e ------------- |
1691 // -- rax : receiver | 1565 // -- rax : receiver |
1692 // -- rcx : name | 1566 // -- rcx : name |
1693 // -- rsp[0] : return address | 1567 // -- rsp[0] : return address |
1694 // ----------------------------------- | 1568 // ----------------------------------- |
1695 Label miss; | |
1696 | 1569 |
1697 StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss); | 1570 __ IncrementCounter(&Counters::load_miss, 1); |
1698 __ bind(&miss); | 1571 |
1699 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 1572 __ pop(rbx); |
| 1573 __ push(rax); // receiver |
| 1574 __ push(rcx); // name |
| 1575 __ push(rbx); // return address |
| 1576 |
| 1577 // Perform tail call to the entry. |
| 1578 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); |
| 1579 __ TailCallExternalReference(ref, 2, 1); |
1700 } | 1580 } |
1701 | 1581 |
1702 | 1582 |
1703 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { | 1583 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { |
1704 if (V8::UseCrankshaft()) return false; | 1584 if (V8::UseCrankshaft()) return false; |
1705 | 1585 |
1706 // The address of the instruction following the call. | 1586 // The address of the instruction following the call. |
1707 Address test_instruction_address = | 1587 Address test_instruction_address = |
1708 address + Assembler::kCallTargetAddressOffset; | 1588 address + Assembler::kCallTargetAddressOffset; |
1709 // If the instruction following the call is not a test rax, nothing | 1589 // If the instruction following the call is not a test rax, nothing |
1710 // was inlined. | 1590 // was inlined. |
1711 if (*test_instruction_address != kTestEaxByte) return false; | 1591 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
1712 | 1592 |
1713 Address delta_address = test_instruction_address + 1; | 1593 Address delta_address = test_instruction_address + 1; |
1714 // The delta to the start of the map check instruction. | 1594 // The delta to the start of the map check instruction. |
1715 int delta = *reinterpret_cast<int*>(delta_address); | 1595 int delta = *reinterpret_cast<int*>(delta_address); |
1716 | 1596 |
1717 // The map address is the last 8 bytes of the 10-byte | 1597 // The map address is the last 8 bytes of the 10-byte |
1718 // immediate move instruction, so we add 2 to get the | 1598 // immediate move instruction, so we add 2 to get the |
1719 // offset to the last 8 bytes. | 1599 // offset to the last 8 bytes. |
1720 Address map_address = test_instruction_address + delta + 2; | 1600 Address map_address = test_instruction_address + delta + 2; |
1721 *(reinterpret_cast<Object**>(map_address)) = map; | 1601 *(reinterpret_cast<Object**>(map_address)) = map; |
(...skipping 10 matching lines...) Expand all Loading... |
1732 | 1612 |
1733 bool LoadIC::PatchInlinedContextualLoad(Address address, | 1613 bool LoadIC::PatchInlinedContextualLoad(Address address, |
1734 Object* map, | 1614 Object* map, |
1735 Object* cell, | 1615 Object* cell, |
1736 bool is_dont_delete) { | 1616 bool is_dont_delete) { |
1737 // TODO(<bug#>): implement this. | 1617 // TODO(<bug#>): implement this. |
1738 return false; | 1618 return false; |
1739 } | 1619 } |
1740 | 1620 |
1741 | 1621 |
1742 // The offset from the inlined patch site to the start of the inlined | |
1743 // store instruction. | |
1744 const int StoreIC::kOffsetToStoreInstruction = 20; | |
1745 | |
1746 | |
1747 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { | 1622 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { |
1748 if (V8::UseCrankshaft()) return false; | 1623 if (V8::UseCrankshaft()) return false; |
1749 | 1624 |
1750 // The address of the instruction following the call. | 1625 // The address of the instruction following the call. |
1751 Address test_instruction_address = | 1626 Address test_instruction_address = |
1752 address + Assembler::kCallTargetAddressOffset; | 1627 address + Assembler::kCallTargetAddressOffset; |
1753 | 1628 |
1754 // If the instruction following the call is not a test rax, nothing | 1629 // If the instruction following the call is not a test rax, nothing |
1755 // was inlined. | 1630 // was inlined. |
1756 if (*test_instruction_address != kTestEaxByte) return false; | 1631 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
1757 | 1632 |
1758 // Extract the encoded deltas from the test rax instruction. | 1633 // Extract the encoded deltas from the test rax instruction. |
1759 Address encoded_offsets_address = test_instruction_address + 1; | 1634 Address encoded_offsets_address = test_instruction_address + 1; |
1760 int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); | 1635 int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); |
1761 int delta_to_map_check = -(encoded_offsets & 0xFFFF); | 1636 int delta_to_map_check = -(encoded_offsets & 0xFFFF); |
1762 int delta_to_record_write = encoded_offsets >> 16; | 1637 int delta_to_record_write = encoded_offsets >> 16; |
1763 | 1638 |
1764 // Patch the map to check. The map address is the last 8 bytes of | 1639 // Patch the map to check. The map address is the last 8 bytes of |
1765 // the 10-byte immediate move instruction. | 1640 // the 10-byte immediate move instruction. |
1766 Address map_check_address = test_instruction_address + delta_to_map_check; | 1641 Address map_check_address = test_instruction_address + delta_to_map_check; |
(...skipping 18 matching lines...) Expand all Loading... |
1785 // (-1) or we should be clearing the inlined version. | 1660 // (-1) or we should be clearing the inlined version. |
1786 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || | 1661 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || |
1787 *reinterpret_cast<int*>(offset_address) == -1 || | 1662 *reinterpret_cast<int*>(offset_address) == -1 || |
1788 (offset == 0 && map == Heap::null_value())); | 1663 (offset == 0 && map == Heap::null_value())); |
1789 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; | 1664 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
1790 | 1665 |
1791 return true; | 1666 return true; |
1792 } | 1667 } |
1793 | 1668 |
1794 | 1669 |
1795 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1670 static bool PatchInlinedMapCheck(Address address, Object* map) { |
| 1671 if (V8::UseCrankshaft()) return false; |
| 1672 |
| 1673 // Arguments are address of start of call sequence that called |
| 1674 // the IC, |
| 1675 Address test_instruction_address = |
| 1676 address + Assembler::kCallTargetAddressOffset; |
| 1677 // The keyed load has a fast inlined case if the IC call instruction |
| 1678 // is immediately followed by a test instruction. |
| 1679 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
| 1680 |
| 1681 // Fetch the offset from the test instruction to the map compare |
| 1682 // instructions (starting with the 64-bit immediate mov of the map |
| 1683 // address). This offset is stored in the last 4 bytes of the 5 |
| 1684 // byte test instruction. |
| 1685 Address delta_address = test_instruction_address + 1; |
| 1686 int delta = *reinterpret_cast<int*>(delta_address); |
| 1687 // Compute the map address. The map address is in the last 8 bytes |
| 1688 // of the 10-byte immediate mov instruction (incl. REX prefix), so we add 2 |
| 1689 // to the offset to get the map address. |
| 1690 Address map_address = test_instruction_address + delta + 2; |
| 1691 // Patch the map check. |
| 1692 *(reinterpret_cast<Object**>(map_address)) = map; |
| 1693 return true; |
| 1694 } |
| 1695 |
| 1696 |
| 1697 bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { |
| 1698 return PatchInlinedMapCheck(address, map); |
| 1699 } |
| 1700 |
| 1701 |
| 1702 bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { |
| 1703 return PatchInlinedMapCheck(address, map); |
| 1704 } |
| 1705 |
| 1706 |
| 1707 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
1796 // ----------- S t a t e ------------- | 1708 // ----------- S t a t e ------------- |
1797 // -- rax : value | 1709 // -- rax : key |
1798 // -- rcx : name | |
1799 // -- rdx : receiver | 1710 // -- rdx : receiver |
1800 // -- rsp[0] : return address | 1711 // -- rsp[0] : return address |
| 1712 // ----------------------------------- |
| 1713 |
| 1714 __ IncrementCounter(&Counters::keyed_load_miss, 1); |
| 1715 |
| 1716 __ pop(rbx); |
| 1717 __ push(rdx); // receiver |
| 1718 __ push(rax); // name |
| 1719 __ push(rbx); // return address |
| 1720 |
| 1721 // Perform tail call to the entry. |
| 1722 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); |
| 1723 __ TailCallExternalReference(ref, 2, 1); |
| 1724 } |
| 1725 |
| 1726 |
| 1727 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 1728 // ----------- S t a t e ------------- |
| 1729 // -- rax : key |
| 1730 // -- rdx : receiver |
| 1731 // -- rsp[0] : return address |
1801 // ----------------------------------- | 1732 // ----------------------------------- |
1802 | 1733 |
1803 __ pop(rbx); | 1734 __ pop(rbx); |
1804 __ push(rdx); // receiver | 1735 __ push(rdx); // receiver |
1805 __ push(rcx); // name | 1736 __ push(rax); // name |
1806 __ push(rax); // value | |
1807 __ push(rbx); // return address | 1737 __ push(rbx); // return address |
1808 | 1738 |
1809 // Perform tail call to the entry. | 1739 // Perform tail call to the entry. |
1810 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); | 1740 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
1811 __ TailCallExternalReference(ref, 3, 1); | |
1812 } | 1741 } |
1813 | 1742 |
1814 | 1743 |
1815 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1744 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
1816 // ----------- S t a t e ------------- | 1745 // ----------- S t a t e ------------- |
1817 // -- rax : value | 1746 // -- rax : value |
1818 // -- rcx : name | 1747 // -- rcx : name |
1819 // -- rdx : receiver | 1748 // -- rdx : receiver |
1820 // -- rsp[0] : return address | 1749 // -- rsp[0] : return address |
1821 // ----------------------------------- | 1750 // ----------------------------------- |
1822 | 1751 |
1823 // Get the receiver from the stack and probe the stub cache. | 1752 // Get the receiver from the stack and probe the stub cache. |
1824 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, | 1753 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, |
1825 NOT_IN_LOOP, | 1754 NOT_IN_LOOP, |
1826 MONOMORPHIC); | 1755 MONOMORPHIC); |
1827 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg); | 1756 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, no_reg); |
1828 | 1757 |
1829 // Cache miss: Jump to runtime. | 1758 // Cache miss: Jump to runtime. |
1830 GenerateMiss(masm); | 1759 GenerateMiss(masm); |
1831 } | 1760 } |
1832 | 1761 |
1833 | 1762 |
| 1763 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1764 // ----------- S t a t e ------------- |
| 1765 // -- rax : value |
| 1766 // -- rcx : name |
| 1767 // -- rdx : receiver |
| 1768 // -- rsp[0] : return address |
| 1769 // ----------------------------------- |
| 1770 |
| 1771 __ pop(rbx); |
| 1772 __ push(rdx); // receiver |
| 1773 __ push(rcx); // name |
| 1774 __ push(rax); // value |
| 1775 __ push(rbx); // return address |
| 1776 |
| 1777 // Perform tail call to the entry. |
| 1778 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); |
| 1779 __ TailCallExternalReference(ref, 3, 1); |
| 1780 } |
| 1781 |
| 1782 |
| 1783 // The offset from the inlined patch site to the start of the inlined |
| 1784 // store instruction. |
| 1785 const int StoreIC::kOffsetToStoreInstruction = 20; |
| 1786 |
| 1787 |
1834 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { | 1788 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { |
1835 // ----------- S t a t e ------------- | 1789 // ----------- S t a t e ------------- |
1836 // -- rax : value | 1790 // -- rax : value |
1837 // -- rcx : name | 1791 // -- rcx : name |
1838 // -- rdx : receiver | 1792 // -- rdx : receiver |
1839 // -- rsp[0] : return address | 1793 // -- rsp[0] : return address |
1840 // ----------------------------------- | 1794 // ----------------------------------- |
1841 // | 1795 // |
1842 // This accepts as a receiver anything JSObject::SetElementsLength accepts | 1796 // This accepts as a receiver anything JSObject::SetElementsLength accepts |
1843 // (currently anything except for external and pixel arrays which means | 1797 // (currently anything except for external and pixel arrays which means |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1916 __ push(rdx); | 1870 __ push(rdx); |
1917 __ push(rcx); | 1871 __ push(rcx); |
1918 __ push(rax); | 1872 __ push(rax); |
1919 __ push(rbx); | 1873 __ push(rbx); |
1920 | 1874 |
1921 // Do tail-call to runtime routine. | 1875 // Do tail-call to runtime routine. |
1922 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 1876 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); |
1923 } | 1877 } |
1924 | 1878 |
1925 | 1879 |
| 1880 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { |
| 1881 // ----------- S t a t e ------------- |
| 1882 // -- rax : value |
| 1883 // -- rcx : key |
| 1884 // -- rdx : receiver |
| 1885 // -- rsp[0] : return address |
| 1886 // ----------------------------------- |
| 1887 |
| 1888 __ pop(rbx); |
| 1889 __ push(rdx); // receiver |
| 1890 __ push(rcx); // key |
| 1891 __ push(rax); // value |
| 1892 __ push(rbx); // return address |
| 1893 |
| 1894 // Do tail-call to runtime routine. |
| 1895 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); |
| 1896 } |
| 1897 |
| 1898 |
| 1899 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1900 // ----------- S t a t e ------------- |
| 1901 // -- rax : value |
| 1902 // -- rcx : key |
| 1903 // -- rdx : receiver |
| 1904 // -- rsp[0] : return address |
| 1905 // ----------------------------------- |
| 1906 |
| 1907 __ pop(rbx); |
| 1908 __ push(rdx); // receiver |
| 1909 __ push(rcx); // key |
| 1910 __ push(rax); // value |
| 1911 __ push(rbx); // return address |
| 1912 |
| 1913 // Do tail-call to runtime routine. |
| 1914 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
| 1915 __ TailCallExternalReference(ref, 3, 1); |
| 1916 } |
| 1917 |
| 1918 |
1926 #undef __ | 1919 #undef __ |
1927 | 1920 |
1928 | 1921 |
1929 Condition CompareIC::ComputeCondition(Token::Value op) { | 1922 Condition CompareIC::ComputeCondition(Token::Value op) { |
1930 switch (op) { | 1923 switch (op) { |
1931 case Token::EQ_STRICT: | 1924 case Token::EQ_STRICT: |
1932 case Token::EQ: | 1925 case Token::EQ: |
1933 return equal; | 1926 return equal; |
1934 case Token::LT: | 1927 case Token::LT: |
1935 return less; | 1928 return less; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1969 GetStateName(state), | 1962 GetStateName(state), |
1970 Token::Name(op_)); | 1963 Token::Name(op_)); |
1971 } | 1964 } |
1972 #endif | 1965 #endif |
1973 } | 1966 } |
1974 | 1967 |
1975 void PatchInlinedSmiCode(Address address) { | 1968 void PatchInlinedSmiCode(Address address) { |
1976 UNIMPLEMENTED(); | 1969 UNIMPLEMENTED(); |
1977 } | 1970 } |
1978 | 1971 |
| 1972 |
1979 } } // namespace v8::internal | 1973 } } // namespace v8::internal |
1980 | 1974 |
1981 #endif // V8_TARGET_ARCH_X64 | 1975 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |