| 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 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1404 // rax: elements | 1269 // rax: elements |
| 1405 // Search the dictionary placing the result in rdi. | 1270 // Search the dictionary placing the result in rdi. |
| 1406 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi); | 1271 GenerateDictionaryLoad(masm, &miss, rax, rcx, rbx, rdi, rdi); |
| 1407 | 1272 |
| 1408 GenerateFunctionTailCall(masm, argc, &miss); | 1273 GenerateFunctionTailCall(masm, argc, &miss); |
| 1409 | 1274 |
| 1410 __ bind(&miss); | 1275 __ bind(&miss); |
| 1411 } | 1276 } |
| 1412 | 1277 |
| 1413 | 1278 |
| 1414 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 1279 static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) { |
| 1415 // ----------- S t a t e ------------- | 1280 // ----------- S t a t e ------------- |
| 1416 // rcx : function name | 1281 // rcx : function name |
| 1417 // rsp[0] : return address | 1282 // rsp[0] : return address |
| 1418 // rsp[8] : argument argc | 1283 // rsp[8] : argument argc |
| 1419 // rsp[16] : argument argc - 1 | 1284 // rsp[16] : argument argc - 1 |
| 1420 // ... | 1285 // ... |
| 1421 // rsp[argc * 8] : argument 1 | 1286 // rsp[argc * 8] : argument 1 |
| 1422 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1287 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1423 // ----------------------------------- | 1288 // ----------------------------------- |
| 1424 GenerateCallMiss(masm, argc, IC::kCallIC_Miss); | 1289 |
| 1290 if (id == IC::kCallIC_Miss) { |
| 1291 __ IncrementCounter(COUNTERS->call_miss(), 1); |
| 1292 } else { |
| 1293 __ IncrementCounter(COUNTERS->keyed_call_miss(), 1); |
| 1294 } |
| 1295 |
| 1296 // Get the receiver of the function from the stack; 1 ~ return address. |
| 1297 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1298 |
| 1299 // Enter an internal frame. |
| 1300 __ EnterInternalFrame(); |
| 1301 |
| 1302 // Push the receiver and the name of the function. |
| 1303 __ push(rdx); |
| 1304 __ push(rcx); |
| 1305 |
| 1306 // Call the entry. |
| 1307 CEntryStub stub(1); |
| 1308 __ movq(rax, Immediate(2)); |
| 1309 __ movq(rbx, ExternalReference(IC_Utility(id))); |
| 1310 __ CallStub(&stub); |
| 1311 |
| 1312 // Move result to rdi and exit the internal frame. |
| 1313 __ movq(rdi, rax); |
| 1314 __ LeaveInternalFrame(); |
| 1315 |
| 1316 // Check if the receiver is a global object of some sort. |
| 1317 // This can happen only for regular CallIC but not KeyedCallIC. |
| 1318 if (id == IC::kCallIC_Miss) { |
| 1319 Label invoke, global; |
| 1320 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver |
| 1321 __ JumpIfSmi(rdx, &invoke); |
| 1322 __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx); |
| 1323 __ j(equal, &global); |
| 1324 __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE); |
| 1325 __ j(not_equal, &invoke); |
| 1326 |
| 1327 // Patch the receiver on the stack. |
| 1328 __ bind(&global); |
| 1329 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 1330 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 1331 __ bind(&invoke); |
| 1332 } |
| 1333 |
| 1334 // Invoke the function. |
| 1335 ParameterCount actual(argc); |
| 1336 __ InvokeFunction(rdi, actual, JUMP_FUNCTION); |
| 1425 } | 1337 } |
| 1426 | 1338 |
| 1427 | 1339 |
| 1428 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 1340 void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
| 1429 // ----------- S t a t e ------------- | 1341 // ----------- S t a t e ------------- |
| 1430 // rcx : function name | 1342 // rcx : function name |
| 1431 // rsp[0] : return address | 1343 // rsp[0] : return address |
| 1432 // rsp[8] : argument argc | 1344 // rsp[8] : argument argc |
| 1433 // rsp[16] : argument argc - 1 | 1345 // rsp[16] : argument argc - 1 |
| 1434 // ... | 1346 // ... |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1452 // ... | 1364 // ... |
| 1453 // rsp[argc * 8] : argument 1 | 1365 // rsp[argc * 8] : argument 1 |
| 1454 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1366 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1455 // ----------------------------------- | 1367 // ----------------------------------- |
| 1456 | 1368 |
| 1457 GenerateCallNormal(masm, argc); | 1369 GenerateCallNormal(masm, argc); |
| 1458 GenerateMiss(masm, argc); | 1370 GenerateMiss(masm, argc); |
| 1459 } | 1371 } |
| 1460 | 1372 |
| 1461 | 1373 |
| 1462 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 1374 void CallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
| 1463 // ----------- S t a t e ------------- | 1375 // ----------- S t a t e ------------- |
| 1464 // rcx : function name | 1376 // rcx : function name |
| 1465 // rsp[0] : return address | 1377 // rsp[0] : return address |
| 1466 // rsp[8] : argument argc | 1378 // rsp[8] : argument argc |
| 1467 // rsp[16] : argument argc - 1 | 1379 // rsp[16] : argument argc - 1 |
| 1468 // ... | 1380 // ... |
| 1469 // rsp[argc * 8] : argument 1 | 1381 // rsp[argc * 8] : argument 1 |
| 1470 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1382 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1471 // ----------------------------------- | 1383 // ----------------------------------- |
| 1472 | 1384 |
| 1473 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); | 1385 GenerateCallMiss(masm, argc, IC::kCallIC_Miss); |
| 1474 } | 1386 } |
| 1475 | 1387 |
| 1476 | 1388 |
| 1477 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { | 1389 void KeyedCallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) { |
| 1478 // ----------- S t a t e ------------- | 1390 // ----------- S t a t e ------------- |
| 1479 // rcx : function name | 1391 // rcx : function name |
| 1480 // rsp[0] : return address | 1392 // rsp[0] : return address |
| 1481 // rsp[8] : argument argc | 1393 // rsp[8] : argument argc |
| 1482 // rsp[16] : argument argc - 1 | 1394 // rsp[16] : argument argc - 1 |
| 1483 // ... | 1395 // ... |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1589 // ... | 1501 // ... |
| 1590 // rsp[argc * 8] : argument 1 | 1502 // rsp[argc * 8] : argument 1 |
| 1591 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1503 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1592 // ----------------------------------- | 1504 // ----------------------------------- |
| 1593 | 1505 |
| 1594 GenerateCallNormal(masm, argc); | 1506 GenerateCallNormal(masm, argc); |
| 1595 GenerateMiss(masm, argc); | 1507 GenerateMiss(masm, argc); |
| 1596 } | 1508 } |
| 1597 | 1509 |
| 1598 | 1510 |
| 1599 // The offset from the inlined patch site to the start of the inlined | 1511 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
| 1600 // load instruction. | |
| 1601 const int LoadIC::kOffsetToLoadInstruction = 20; | |
| 1602 | |
| 1603 | |
| 1604 void LoadIC::GenerateMiss(MacroAssembler* masm) { | |
| 1605 // ----------- S t a t e ------------- | 1512 // ----------- S t a t e ------------- |
| 1606 // -- rax : receiver | 1513 // rcx : function name |
| 1607 // -- rcx : name | 1514 // rsp[0] : return address |
| 1608 // -- rsp[0] : return address | 1515 // rsp[8] : argument argc |
| 1516 // rsp[16] : argument argc - 1 |
| 1517 // ... |
| 1518 // rsp[argc * 8] : argument 1 |
| 1519 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1609 // ----------------------------------- | 1520 // ----------------------------------- |
| 1610 | 1521 |
| 1611 __ IncrementCounter(COUNTERS->load_miss(), 1); | 1522 GenerateCallMiss(masm, argc, IC::kKeyedCallIC_Miss); |
| 1612 | |
| 1613 __ pop(rbx); | |
| 1614 __ push(rax); // receiver | |
| 1615 __ push(rcx); // name | |
| 1616 __ push(rbx); // return address | |
| 1617 | |
| 1618 // Perform tail call to the entry. | |
| 1619 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); | |
| 1620 __ TailCallExternalReference(ref, 2, 1); | |
| 1621 } | |
| 1622 | |
| 1623 | |
| 1624 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | |
| 1625 // ----------- S t a t e ------------- | |
| 1626 // -- rax : receiver | |
| 1627 // -- rcx : name | |
| 1628 // -- rsp[0] : return address | |
| 1629 // ----------------------------------- | |
| 1630 Label miss; | |
| 1631 | |
| 1632 StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss); | |
| 1633 __ bind(&miss); | |
| 1634 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | |
| 1635 } | |
| 1636 | |
| 1637 | |
| 1638 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) { | |
| 1639 // ----------- S t a t e ------------- | |
| 1640 // -- rax : receiver | |
| 1641 // -- rcx : name | |
| 1642 // -- rsp[0] : return address | |
| 1643 // ----------------------------------- | |
| 1644 Label miss; | |
| 1645 | |
| 1646 StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss); | |
| 1647 __ bind(&miss); | |
| 1648 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | |
| 1649 } | 1523 } |
| 1650 | 1524 |
| 1651 | 1525 |
| 1652 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 1526 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 1653 // ----------- S t a t e ------------- | 1527 // ----------- S t a t e ------------- |
| 1654 // -- rax : receiver | 1528 // -- rax : receiver |
| 1655 // -- rcx : name | 1529 // -- rcx : name |
| 1656 // -- rsp[0] : return address | 1530 // -- rsp[0] : return address |
| 1657 // ----------------------------------- | 1531 // ----------------------------------- |
| 1658 | 1532 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1682 // Search the dictionary placing the result in rax. | 1556 // Search the dictionary placing the result in rax. |
| 1683 GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax); | 1557 GenerateDictionaryLoad(masm, &miss, rdx, rcx, rbx, rdi, rax); |
| 1684 __ ret(0); | 1558 __ ret(0); |
| 1685 | 1559 |
| 1686 // Cache miss: Jump to runtime. | 1560 // Cache miss: Jump to runtime. |
| 1687 __ bind(&miss); | 1561 __ bind(&miss); |
| 1688 GenerateMiss(masm); | 1562 GenerateMiss(masm); |
| 1689 } | 1563 } |
| 1690 | 1564 |
| 1691 | 1565 |
| 1692 void LoadIC::GenerateStringLength(MacroAssembler* masm) { | 1566 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1693 // ----------- S t a t e ------------- | 1567 // ----------- S t a t e ------------- |
| 1694 // -- rax : receiver | 1568 // -- rax : receiver |
| 1695 // -- rcx : name | 1569 // -- rcx : name |
| 1696 // -- rsp[0] : return address | 1570 // -- rsp[0] : return address |
| 1697 // ----------------------------------- | 1571 // ----------------------------------- |
| 1698 Label miss; | |
| 1699 | 1572 |
| 1700 StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss); | 1573 __ IncrementCounter(COUNTERS->load_miss(), 1); |
| 1701 __ bind(&miss); | 1574 |
| 1702 StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC); | 1575 __ pop(rbx); |
| 1576 __ push(rax); // receiver |
| 1577 __ push(rcx); // name |
| 1578 __ push(rbx); // return address |
| 1579 |
| 1580 // Perform tail call to the entry. |
| 1581 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss)); |
| 1582 __ TailCallExternalReference(ref, 2, 1); |
| 1703 } | 1583 } |
| 1704 | 1584 |
| 1705 | 1585 |
| 1706 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { | 1586 bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) { |
| 1707 if (V8::UseCrankshaft()) return false; | 1587 if (V8::UseCrankshaft()) return false; |
| 1708 | 1588 |
| 1709 // The address of the instruction following the call. | 1589 // The address of the instruction following the call. |
| 1710 Address test_instruction_address = | 1590 Address test_instruction_address = |
| 1711 address + Assembler::kCallTargetAddressOffset; | 1591 address + Assembler::kCallTargetAddressOffset; |
| 1712 // If the instruction following the call is not a test rax, nothing | 1592 // If the instruction following the call is not a test rax, nothing |
| 1713 // was inlined. | 1593 // was inlined. |
| 1714 if (*test_instruction_address != kTestEaxByte) return false; | 1594 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
| 1715 | 1595 |
| 1716 Address delta_address = test_instruction_address + 1; | 1596 Address delta_address = test_instruction_address + 1; |
| 1717 // The delta to the start of the map check instruction. | 1597 // The delta to the start of the map check instruction. |
| 1718 int delta = *reinterpret_cast<int*>(delta_address); | 1598 int delta = *reinterpret_cast<int*>(delta_address); |
| 1719 | 1599 |
| 1720 // The map address is the last 8 bytes of the 10-byte | 1600 // The map address is the last 8 bytes of the 10-byte |
| 1721 // immediate move instruction, so we add 2 to get the | 1601 // immediate move instruction, so we add 2 to get the |
| 1722 // offset to the last 8 bytes. | 1602 // offset to the last 8 bytes. |
| 1723 Address map_address = test_instruction_address + delta + 2; | 1603 Address map_address = test_instruction_address + delta + 2; |
| 1724 *(reinterpret_cast<Object**>(map_address)) = map; | 1604 *(reinterpret_cast<Object**>(map_address)) = map; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1735 | 1615 |
| 1736 bool LoadIC::PatchInlinedContextualLoad(Address address, | 1616 bool LoadIC::PatchInlinedContextualLoad(Address address, |
| 1737 Object* map, | 1617 Object* map, |
| 1738 Object* cell, | 1618 Object* cell, |
| 1739 bool is_dont_delete) { | 1619 bool is_dont_delete) { |
| 1740 // TODO(<bug#>): implement this. | 1620 // TODO(<bug#>): implement this. |
| 1741 return false; | 1621 return false; |
| 1742 } | 1622 } |
| 1743 | 1623 |
| 1744 | 1624 |
| 1745 // The offset from the inlined patch site to the start of the inlined | |
| 1746 // store instruction. | |
| 1747 const int StoreIC::kOffsetToStoreInstruction = 20; | |
| 1748 | |
| 1749 | |
| 1750 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { | 1625 bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) { |
| 1751 if (V8::UseCrankshaft()) return false; | 1626 if (V8::UseCrankshaft()) return false; |
| 1752 | 1627 |
| 1753 // The address of the instruction following the call. | 1628 // The address of the instruction following the call. |
| 1754 Address test_instruction_address = | 1629 Address test_instruction_address = |
| 1755 address + Assembler::kCallTargetAddressOffset; | 1630 address + Assembler::kCallTargetAddressOffset; |
| 1756 | 1631 |
| 1757 // If the instruction following the call is not a test rax, nothing | 1632 // If the instruction following the call is not a test rax, nothing |
| 1758 // was inlined. | 1633 // was inlined. |
| 1759 if (*test_instruction_address != kTestEaxByte) return false; | 1634 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
| 1760 | 1635 |
| 1761 // Extract the encoded deltas from the test rax instruction. | 1636 // Extract the encoded deltas from the test rax instruction. |
| 1762 Address encoded_offsets_address = test_instruction_address + 1; | 1637 Address encoded_offsets_address = test_instruction_address + 1; |
| 1763 int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); | 1638 int encoded_offsets = *reinterpret_cast<int*>(encoded_offsets_address); |
| 1764 int delta_to_map_check = -(encoded_offsets & 0xFFFF); | 1639 int delta_to_map_check = -(encoded_offsets & 0xFFFF); |
| 1765 int delta_to_record_write = encoded_offsets >> 16; | 1640 int delta_to_record_write = encoded_offsets >> 16; |
| 1766 | 1641 |
| 1767 // Patch the map to check. The map address is the last 8 bytes of | 1642 // Patch the map to check. The map address is the last 8 bytes of |
| 1768 // the 10-byte immediate move instruction. | 1643 // the 10-byte immediate move instruction. |
| 1769 Address map_check_address = test_instruction_address + delta_to_map_check; | 1644 Address map_check_address = test_instruction_address + delta_to_map_check; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1788 // (-1) or we should be clearing the inlined version. | 1663 // (-1) or we should be clearing the inlined version. |
| 1789 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || | 1664 ASSERT(*reinterpret_cast<int*>(offset_address) == kMaxInt || |
| 1790 *reinterpret_cast<int*>(offset_address) == -1 || | 1665 *reinterpret_cast<int*>(offset_address) == -1 || |
| 1791 (offset == 0 && map == HEAP->null_value())); | 1666 (offset == 0 && map == HEAP->null_value())); |
| 1792 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; | 1667 *reinterpret_cast<int*>(offset_address) = offset - kHeapObjectTag; |
| 1793 | 1668 |
| 1794 return true; | 1669 return true; |
| 1795 } | 1670 } |
| 1796 | 1671 |
| 1797 | 1672 |
| 1798 void StoreIC::GenerateMiss(MacroAssembler* masm) { | 1673 static bool PatchInlinedMapCheck(Address address, Object* map) { |
| 1674 if (V8::UseCrankshaft()) return false; |
| 1675 |
| 1676 // Arguments are address of start of call sequence that called |
| 1677 // the IC, |
| 1678 Address test_instruction_address = |
| 1679 address + Assembler::kCallTargetAddressOffset; |
| 1680 // The keyed load has a fast inlined case if the IC call instruction |
| 1681 // is immediately followed by a test instruction. |
| 1682 if (*test_instruction_address != Assembler::kTestEaxByte) return false; |
| 1683 |
| 1684 // Fetch the offset from the test instruction to the map compare |
| 1685 // instructions (starting with the 64-bit immediate mov of the map |
| 1686 // address). This offset is stored in the last 4 bytes of the 5 |
| 1687 // byte test instruction. |
| 1688 Address delta_address = test_instruction_address + 1; |
| 1689 int delta = *reinterpret_cast<int*>(delta_address); |
| 1690 // Compute the map address. The map address is in the last 8 bytes |
| 1691 // of the 10-byte immediate mov instruction (incl. REX prefix), so we add 2 |
| 1692 // to the offset to get the map address. |
| 1693 Address map_address = test_instruction_address + delta + 2; |
| 1694 // Patch the map check. |
| 1695 *(reinterpret_cast<Object**>(map_address)) = map; |
| 1696 return true; |
| 1697 } |
| 1698 |
| 1699 |
| 1700 bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { |
| 1701 return PatchInlinedMapCheck(address, map); |
| 1702 } |
| 1703 |
| 1704 |
| 1705 bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) { |
| 1706 return PatchInlinedMapCheck(address, map); |
| 1707 } |
| 1708 |
| 1709 |
| 1710 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { |
| 1799 // ----------- S t a t e ------------- | 1711 // ----------- S t a t e ------------- |
| 1800 // -- rax : value | 1712 // -- rax : key |
| 1801 // -- rcx : name | |
| 1802 // -- rdx : receiver | 1713 // -- rdx : receiver |
| 1803 // -- rsp[0] : return address | 1714 // -- rsp[0] : return address |
| 1715 // ----------------------------------- |
| 1716 |
| 1717 __ IncrementCounter(COUNTERS->keyed_load_miss(), 1); |
| 1718 |
| 1719 __ pop(rbx); |
| 1720 __ push(rdx); // receiver |
| 1721 __ push(rax); // name |
| 1722 __ push(rbx); // return address |
| 1723 |
| 1724 // Perform tail call to the entry. |
| 1725 ExternalReference ref = ExternalReference(IC_Utility(kKeyedLoadIC_Miss)); |
| 1726 __ TailCallExternalReference(ref, 2, 1); |
| 1727 } |
| 1728 |
| 1729 |
| 1730 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { |
| 1731 // ----------- S t a t e ------------- |
| 1732 // -- rax : key |
| 1733 // -- rdx : receiver |
| 1734 // -- rsp[0] : return address |
| 1804 // ----------------------------------- | 1735 // ----------------------------------- |
| 1805 | 1736 |
| 1806 __ pop(rbx); | 1737 __ pop(rbx); |
| 1807 __ push(rdx); // receiver | 1738 __ push(rdx); // receiver |
| 1808 __ push(rcx); // name | 1739 __ push(rax); // name |
| 1809 __ push(rax); // value | |
| 1810 __ push(rbx); // return address | 1740 __ push(rbx); // return address |
| 1811 | 1741 |
| 1812 // Perform tail call to the entry. | 1742 // Perform tail call to the entry. |
| 1813 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); | 1743 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); |
| 1814 __ TailCallExternalReference(ref, 3, 1); | |
| 1815 } | 1744 } |
| 1816 | 1745 |
| 1817 | 1746 |
| 1818 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { | 1747 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 1819 // ----------- S t a t e ------------- | 1748 // ----------- S t a t e ------------- |
| 1820 // -- rax : value | 1749 // -- rax : value |
| 1821 // -- rcx : name | 1750 // -- rcx : name |
| 1822 // -- rdx : receiver | 1751 // -- rdx : receiver |
| 1823 // -- rsp[0] : return address | 1752 // -- rsp[0] : return address |
| 1824 // ----------------------------------- | 1753 // ----------------------------------- |
| 1825 | 1754 |
| 1826 // Get the receiver from the stack and probe the stub cache. | 1755 // Get the receiver from the stack and probe the stub cache. |
| 1827 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, | 1756 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, |
| 1828 NOT_IN_LOOP, | 1757 NOT_IN_LOOP, |
| 1829 MONOMORPHIC); | 1758 MONOMORPHIC); |
| 1830 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx, | 1759 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, rdx, rcx, rbx, |
| 1831 no_reg); | 1760 no_reg); |
| 1832 | 1761 |
| 1833 // Cache miss: Jump to runtime. | 1762 // Cache miss: Jump to runtime. |
| 1834 GenerateMiss(masm); | 1763 GenerateMiss(masm); |
| 1835 } | 1764 } |
| 1836 | 1765 |
| 1837 | 1766 |
| 1767 void StoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1768 // ----------- S t a t e ------------- |
| 1769 // -- rax : value |
| 1770 // -- rcx : name |
| 1771 // -- rdx : receiver |
| 1772 // -- rsp[0] : return address |
| 1773 // ----------------------------------- |
| 1774 |
| 1775 __ pop(rbx); |
| 1776 __ push(rdx); // receiver |
| 1777 __ push(rcx); // name |
| 1778 __ push(rax); // value |
| 1779 __ push(rbx); // return address |
| 1780 |
| 1781 // Perform tail call to the entry. |
| 1782 ExternalReference ref = ExternalReference(IC_Utility(kStoreIC_Miss)); |
| 1783 __ TailCallExternalReference(ref, 3, 1); |
| 1784 } |
| 1785 |
| 1786 |
| 1787 // The offset from the inlined patch site to the start of the inlined |
| 1788 // store instruction. |
| 1789 const int StoreIC::kOffsetToStoreInstruction = 20; |
| 1790 |
| 1791 |
| 1838 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { | 1792 void StoreIC::GenerateArrayLength(MacroAssembler* masm) { |
| 1839 // ----------- S t a t e ------------- | 1793 // ----------- S t a t e ------------- |
| 1840 // -- rax : value | 1794 // -- rax : value |
| 1841 // -- rcx : name | 1795 // -- rcx : name |
| 1842 // -- rdx : receiver | 1796 // -- rdx : receiver |
| 1843 // -- rsp[0] : return address | 1797 // -- rsp[0] : return address |
| 1844 // ----------------------------------- | 1798 // ----------------------------------- |
| 1845 // | 1799 // |
| 1846 // This accepts as a receiver anything JSObject::SetElementsLength accepts | 1800 // This accepts as a receiver anything JSObject::SetElementsLength accepts |
| 1847 // (currently anything except for external and pixel arrays which means | 1801 // (currently anything except for external and pixel arrays which means |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1920 __ push(rdx); | 1874 __ push(rdx); |
| 1921 __ push(rcx); | 1875 __ push(rcx); |
| 1922 __ push(rax); | 1876 __ push(rax); |
| 1923 __ push(rbx); | 1877 __ push(rbx); |
| 1924 | 1878 |
| 1925 // Do tail-call to runtime routine. | 1879 // Do tail-call to runtime routine. |
| 1926 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); | 1880 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); |
| 1927 } | 1881 } |
| 1928 | 1882 |
| 1929 | 1883 |
| 1884 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) { |
| 1885 // ----------- S t a t e ------------- |
| 1886 // -- rax : value |
| 1887 // -- rcx : key |
| 1888 // -- rdx : receiver |
| 1889 // -- rsp[0] : return address |
| 1890 // ----------------------------------- |
| 1891 |
| 1892 __ pop(rbx); |
| 1893 __ push(rdx); // receiver |
| 1894 __ push(rcx); // key |
| 1895 __ push(rax); // value |
| 1896 __ push(rbx); // return address |
| 1897 |
| 1898 // Do tail-call to runtime routine. |
| 1899 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); |
| 1900 } |
| 1901 |
| 1902 |
| 1903 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 1904 // ----------- S t a t e ------------- |
| 1905 // -- rax : value |
| 1906 // -- rcx : key |
| 1907 // -- rdx : receiver |
| 1908 // -- rsp[0] : return address |
| 1909 // ----------------------------------- |
| 1910 |
| 1911 __ pop(rbx); |
| 1912 __ push(rdx); // receiver |
| 1913 __ push(rcx); // key |
| 1914 __ push(rax); // value |
| 1915 __ push(rbx); // return address |
| 1916 |
| 1917 // Do tail-call to runtime routine. |
| 1918 ExternalReference ref = ExternalReference(IC_Utility(kKeyedStoreIC_Miss)); |
| 1919 __ TailCallExternalReference(ref, 3, 1); |
| 1920 } |
| 1921 |
| 1922 |
| 1930 #undef __ | 1923 #undef __ |
| 1931 | 1924 |
| 1932 | 1925 |
| 1933 Condition CompareIC::ComputeCondition(Token::Value op) { | 1926 Condition CompareIC::ComputeCondition(Token::Value op) { |
| 1934 switch (op) { | 1927 switch (op) { |
| 1935 case Token::EQ_STRICT: | 1928 case Token::EQ_STRICT: |
| 1936 case Token::EQ: | 1929 case Token::EQ: |
| 1937 return equal; | 1930 return equal; |
| 1938 case Token::LT: | 1931 case Token::LT: |
| 1939 return less; | 1932 return less; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1973 GetStateName(state), | 1966 GetStateName(state), |
| 1974 Token::Name(op_)); | 1967 Token::Name(op_)); |
| 1975 } | 1968 } |
| 1976 #endif | 1969 #endif |
| 1977 } | 1970 } |
| 1978 | 1971 |
| 1979 void PatchInlinedSmiCode(Address address) { | 1972 void PatchInlinedSmiCode(Address address) { |
| 1980 UNIMPLEMENTED(); | 1973 UNIMPLEMENTED(); |
| 1981 } | 1974 } |
| 1982 | 1975 |
| 1976 |
| 1983 } } // namespace v8::internal | 1977 } } // namespace v8::internal |
| 1984 | 1978 |
| 1985 #endif // V8_TARGET_ARCH_X64 | 1979 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |