Chromium Code Reviews| 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 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 814 | 814 |
| 815 | 815 |
| 816 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 816 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { |
| 817 if (kind_ == Code::KEYED_CALL_IC) { | 817 if (kind_ == Code::KEYED_CALL_IC) { |
| 818 __ Cmp(rcx, Handle<String>(name)); | 818 __ Cmp(rcx, Handle<String>(name)); |
| 819 __ j(not_equal, miss); | 819 __ j(not_equal, miss); |
| 820 } | 820 } |
| 821 } | 821 } |
| 822 | 822 |
| 823 | 823 |
| 824 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | |
| 825 JSObject* holder, | |
| 826 String* name, | |
| 827 Label* miss) { | |
| 828 // Get the number of arguments. | |
| 829 const int argc = arguments().immediate(); | |
| 830 | |
| 831 // Get the receiver from the stack. | |
| 832 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | |
| 833 | |
| 834 // If the object is the holder then we know that it's a global | |
| 835 // object which can only happen for contextual calls. In this case, | |
| 836 // the receiver cannot be a smi. | |
| 837 if (object != holder) { | |
| 838 __ JumpIfSmi(rdx, miss); | |
| 839 } | |
| 840 | |
| 841 // Check that the maps haven't changed. | |
| 842 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); | |
| 843 } | |
| 844 | |
| 845 | |
| 846 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | |
| 847 JSFunction* function, | |
| 848 Label* miss) { | |
| 849 // Get the value from the cell. | |
| 850 __ Move(rdi, Handle<JSGlobalPropertyCell>(cell)); | |
| 851 __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); | |
| 852 | |
| 853 // Check that the cell contains the same function. | |
| 854 if (Heap::InNewSpace(function)) { | |
| 855 // We can't embed a pointer to a function in new space so we have | |
| 856 // to verify that the shared function info is unchanged. This has | |
| 857 // the nice side effect that multiple closures based on the same | |
| 858 // function can all use this call IC. Before we load through the | |
| 859 // function, we have to verify that it still is a function. | |
| 860 __ JumpIfSmi(rdi, miss); | |
| 861 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); | |
| 862 __ j(not_equal, miss); | |
| 863 | |
| 864 // Check the shared function info. Make sure it hasn't changed. | |
| 865 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); | |
| 866 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); | |
| 867 __ j(not_equal, miss); | |
| 868 } else { | |
| 869 __ Cmp(rdi, Handle<JSFunction>(function)); | |
| 870 __ j(not_equal, miss); | |
| 871 } | |
| 872 } | |
| 873 | |
| 874 | |
| 824 Object* CallStubCompiler::GenerateMissBranch() { | 875 Object* CallStubCompiler::GenerateMissBranch() { |
| 825 Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_); | 876 Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_); |
| 826 if (obj->IsFailure()) return obj; | 877 if (obj->IsFailure()) return obj; |
| 827 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 878 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
| 828 return obj; | 879 return obj; |
| 829 } | 880 } |
| 830 | 881 |
| 831 | 882 |
| 832 Object* CallStubCompiler::CompileCallConstant(Object* object, | 883 Object* CallStubCompiler::CompileCallConstant(Object* object, |
| 833 JSObject* holder, | 884 JSObject* holder, |
| 834 JSFunction* function, | 885 JSFunction* function, |
| 835 String* name, | 886 String* name, |
| 836 StubCompiler::CheckType check) { | 887 StubCompiler::CheckType check) { |
| 837 // ----------- S t a t e ------------- | 888 // ----------- S t a t e ------------- |
| 838 // rcx : function name | 889 // rcx : function name |
| 839 // rsp[0] : return address | 890 // rsp[0] : return address |
| 840 // rsp[8] : argument argc | 891 // rsp[8] : argument argc |
| 841 // rsp[16] : argument argc - 1 | 892 // rsp[16] : argument argc - 1 |
| 842 // ... | 893 // ... |
| 843 // rsp[argc * 8] : argument 1 | 894 // rsp[argc * 8] : argument 1 |
| 844 // rsp[(argc + 1) * 8] : argument 0 = receiver | 895 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 845 // ----------------------------------- | 896 // ----------------------------------- |
| 846 | 897 |
| 847 SharedFunctionInfo* function_info = function->shared(); | 898 SharedFunctionInfo* function_info = function->shared(); |
| 848 if (function_info->HasCustomCallGenerator()) { | 899 if (function_info->HasCustomCallGenerator()) { |
| 849 const int id = function_info->custom_call_generator_id(); | 900 const int id = function_info->custom_call_generator_id(); |
| 850 Object* result = | 901 Object* result = CompileCustomCall( |
| 851 CompileCustomCall(id, object, holder, function, name, check); | 902 id, object, holder, NULL, function, name); |
| 852 // undefined means bail out to regular compiler. | 903 // undefined means bail out to regular compiler. |
| 853 if (!result->IsUndefined()) { | 904 if (!result->IsUndefined()) return result; |
| 854 return result; | |
| 855 } | |
| 856 } | 905 } |
| 857 | 906 |
| 858 Label miss_in_smi_check; | 907 Label miss_in_smi_check; |
| 859 | 908 |
| 860 GenerateNameCheck(name, &miss_in_smi_check); | 909 GenerateNameCheck(name, &miss_in_smi_check); |
| 861 | 910 |
| 862 // Get the receiver from the stack. | 911 // Get the receiver from the stack. |
| 863 const int argc = arguments().immediate(); | 912 const int argc = arguments().immediate(); |
| 864 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 913 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 865 | 914 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1036 Object* obj = GenerateMissBranch(); | 1085 Object* obj = GenerateMissBranch(); |
| 1037 if (obj->IsFailure()) return obj; | 1086 if (obj->IsFailure()) return obj; |
| 1038 | 1087 |
| 1039 // Return the generated code. | 1088 // Return the generated code. |
| 1040 return GetCode(FIELD, name); | 1089 return GetCode(FIELD, name); |
| 1041 } | 1090 } |
| 1042 | 1091 |
| 1043 | 1092 |
| 1044 Object* CallStubCompiler::CompileArrayPushCall(Object* object, | 1093 Object* CallStubCompiler::CompileArrayPushCall(Object* object, |
| 1045 JSObject* holder, | 1094 JSObject* holder, |
| 1095 JSGlobalPropertyCell* cell, | |
| 1046 JSFunction* function, | 1096 JSFunction* function, |
| 1047 String* name, | 1097 String* name) { |
| 1048 CheckType check) { | |
| 1049 // ----------- S t a t e ------------- | 1098 // ----------- S t a t e ------------- |
| 1050 // -- rcx : name | 1099 // -- rcx : name |
| 1051 // -- rsp[0] : return address | 1100 // -- rsp[0] : return address |
| 1052 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1101 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1053 // -- ... | 1102 // -- ... |
| 1054 // -- rsp[(argc + 1) * 8] : receiver | 1103 // -- rsp[(argc + 1) * 8] : receiver |
| 1055 // ----------------------------------- | 1104 // ----------------------------------- |
| 1056 ASSERT(check == RECEIVER_MAP_CHECK); | |
| 1057 | 1105 |
| 1058 // If object is not an array, bail out to regular call. | 1106 // If object is not an array, bail out to regular call. |
| 1059 if (!object->IsJSArray()) { | 1107 if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); |
| 1060 return Heap::undefined_value(); | |
| 1061 } | |
| 1062 | 1108 |
| 1063 Label miss; | 1109 Label miss; |
| 1064 | 1110 |
| 1065 GenerateNameCheck(name, &miss); | 1111 GenerateNameCheck(name, &miss); |
| 1066 | 1112 |
| 1067 // Get the receiver from the stack. | 1113 // Get the receiver from the stack. |
| 1068 const int argc = arguments().immediate(); | 1114 const int argc = arguments().immediate(); |
| 1069 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1115 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1070 | 1116 |
| 1071 // Check that the receiver isn't a smi. | 1117 // Check that the receiver isn't a smi. |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1197 Object* obj = GenerateMissBranch(); | 1243 Object* obj = GenerateMissBranch(); |
| 1198 if (obj->IsFailure()) return obj; | 1244 if (obj->IsFailure()) return obj; |
| 1199 | 1245 |
| 1200 // Return the generated code. | 1246 // Return the generated code. |
| 1201 return GetCode(function); | 1247 return GetCode(function); |
| 1202 } | 1248 } |
| 1203 | 1249 |
| 1204 | 1250 |
| 1205 Object* CallStubCompiler::CompileArrayPopCall(Object* object, | 1251 Object* CallStubCompiler::CompileArrayPopCall(Object* object, |
| 1206 JSObject* holder, | 1252 JSObject* holder, |
| 1253 JSGlobalPropertyCell* cell, | |
| 1207 JSFunction* function, | 1254 JSFunction* function, |
| 1208 String* name, | 1255 String* name) { |
| 1209 CheckType check) { | |
| 1210 // ----------- S t a t e ------------- | 1256 // ----------- S t a t e ------------- |
| 1211 // -- rcx : name | 1257 // -- rcx : name |
| 1212 // -- rsp[0] : return address | 1258 // -- rsp[0] : return address |
| 1213 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1259 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1214 // -- ... | 1260 // -- ... |
| 1215 // -- rsp[(argc + 1) * 8] : receiver | 1261 // -- rsp[(argc + 1) * 8] : receiver |
| 1216 // ----------------------------------- | 1262 // ----------------------------------- |
| 1217 ASSERT(check == RECEIVER_MAP_CHECK); | |
| 1218 | 1263 |
| 1219 // If object is not an array, bail out to regular call. | 1264 // If object is not an array, bail out to regular call. |
| 1220 if (!object->IsJSArray()) { | 1265 if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); |
| 1221 return Heap::undefined_value(); | |
| 1222 } | |
| 1223 | 1266 |
| 1224 Label miss, return_undefined, call_builtin; | 1267 Label miss, return_undefined, call_builtin; |
| 1225 | 1268 |
| 1226 GenerateNameCheck(name, &miss); | 1269 GenerateNameCheck(name, &miss); |
| 1227 | 1270 |
| 1228 // Get the receiver from the stack. | 1271 // Get the receiver from the stack. |
| 1229 const int argc = arguments().immediate(); | 1272 const int argc = arguments().immediate(); |
| 1230 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 1273 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
| 1231 | 1274 |
| 1232 // Check that the receiver isn't a smi. | 1275 // Check that the receiver isn't a smi. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1282 Object* obj = GenerateMissBranch(); | 1325 Object* obj = GenerateMissBranch(); |
| 1283 if (obj->IsFailure()) return obj; | 1326 if (obj->IsFailure()) return obj; |
| 1284 | 1327 |
| 1285 // Return the generated code. | 1328 // Return the generated code. |
| 1286 return GetCode(function); | 1329 return GetCode(function); |
| 1287 } | 1330 } |
| 1288 | 1331 |
| 1289 | 1332 |
| 1290 Object* CallStubCompiler::CompileStringCharAtCall(Object* object, | 1333 Object* CallStubCompiler::CompileStringCharAtCall(Object* object, |
| 1291 JSObject* holder, | 1334 JSObject* holder, |
| 1335 JSGlobalPropertyCell* cell, | |
| 1292 JSFunction* function, | 1336 JSFunction* function, |
| 1293 String* name, | 1337 String* name) { |
| 1294 CheckType check) { | |
| 1295 // ----------- S t a t e ------------- | 1338 // ----------- S t a t e ------------- |
| 1296 // -- rcx : function name | 1339 // -- rcx : function name |
| 1297 // -- rsp[0] : return address | 1340 // -- rsp[0] : return address |
| 1298 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1341 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1299 // -- ... | 1342 // -- ... |
| 1300 // -- rsp[(argc + 1) * 8] : receiver | 1343 // -- rsp[(argc + 1) * 8] : receiver |
| 1301 // ----------------------------------- | 1344 // ----------------------------------- |
| 1302 | 1345 |
| 1303 // If object is not a string, bail out to regular call. | 1346 // If object is not a string, bail out to regular call. |
| 1304 if (!object->IsString()) return Heap::undefined_value(); | 1347 if (!object->IsString() || cell != NULL) return Heap::undefined_value(); |
| 1305 | 1348 |
| 1306 const int argc = arguments().immediate(); | 1349 const int argc = arguments().immediate(); |
| 1307 | 1350 |
| 1308 Label miss; | 1351 Label miss; |
| 1309 Label index_out_of_range; | 1352 Label index_out_of_range; |
| 1310 | 1353 |
| 1311 GenerateNameCheck(name, &miss); | 1354 GenerateNameCheck(name, &miss); |
| 1312 | 1355 |
| 1313 // Check that the maps starting from the prototype haven't changed. | 1356 // Check that the maps starting from the prototype haven't changed. |
| 1314 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1357 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1351 | 1394 |
| 1352 __ bind(&miss); | 1395 __ bind(&miss); |
| 1353 Object* obj = GenerateMissBranch(); | 1396 Object* obj = GenerateMissBranch(); |
| 1354 if (obj->IsFailure()) return obj; | 1397 if (obj->IsFailure()) return obj; |
| 1355 | 1398 |
| 1356 // Return the generated code. | 1399 // Return the generated code. |
| 1357 return GetCode(function); | 1400 return GetCode(function); |
| 1358 } | 1401 } |
| 1359 | 1402 |
| 1360 | 1403 |
| 1361 Object* CallStubCompiler::CompileStringCharCodeAtCall(Object* object, | 1404 Object* CallStubCompiler::CompileStringCharCodeAtCall( |
| 1362 JSObject* holder, | 1405 Object* object, |
| 1363 JSFunction* function, | 1406 JSObject* holder, |
| 1364 String* name, | 1407 JSGlobalPropertyCell* cell, |
| 1365 CheckType check) { | 1408 JSFunction* function, |
| 1409 String* name) { | |
| 1366 // ----------- S t a t e ------------- | 1410 // ----------- S t a t e ------------- |
| 1367 // -- rcx : function name | 1411 // -- rcx : function name |
| 1368 // -- rsp[0] : return address | 1412 // -- rsp[0] : return address |
| 1369 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | 1413 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) |
| 1370 // -- ... | 1414 // -- ... |
| 1371 // -- rsp[(argc + 1) * 8] : receiver | 1415 // -- rsp[(argc + 1) * 8] : receiver |
| 1372 // ----------------------------------- | 1416 // ----------------------------------- |
| 1373 | 1417 |
| 1374 // If object is not a string, bail out to regular call. | 1418 // If object is not a string, bail out to regular call. |
| 1375 if (!object->IsString()) return Heap::undefined_value(); | 1419 if (!object->IsString() || cell != NULL) return Heap::undefined_value(); |
| 1376 | 1420 |
| 1377 const int argc = arguments().immediate(); | 1421 const int argc = arguments().immediate(); |
| 1378 | 1422 |
| 1379 Label miss; | 1423 Label miss; |
| 1380 Label index_out_of_range; | 1424 Label index_out_of_range; |
| 1381 GenerateNameCheck(name, &miss); | 1425 GenerateNameCheck(name, &miss); |
| 1382 | 1426 |
| 1383 // Check that the maps starting from the prototype haven't changed. | 1427 // Check that the maps starting from the prototype haven't changed. |
| 1384 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1428 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1385 Context::STRING_FUNCTION_INDEX, | 1429 Context::STRING_FUNCTION_INDEX, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1419 | 1463 |
| 1420 __ bind(&miss); | 1464 __ bind(&miss); |
| 1421 Object* obj = GenerateMissBranch(); | 1465 Object* obj = GenerateMissBranch(); |
| 1422 if (obj->IsFailure()) return obj; | 1466 if (obj->IsFailure()) return obj; |
| 1423 | 1467 |
| 1424 // Return the generated code. | 1468 // Return the generated code. |
| 1425 return GetCode(function); | 1469 return GetCode(function); |
| 1426 } | 1470 } |
| 1427 | 1471 |
| 1428 | 1472 |
| 1473 Object* CallStubCompiler::CompileStringFromCharCodeCall( | |
| 1474 Object* object, | |
| 1475 JSObject* holder, | |
| 1476 JSGlobalPropertyCell* cell, | |
| 1477 JSFunction* function, | |
| 1478 String* name) { | |
| 1479 // ----------- S t a t e ------------- | |
| 1480 // -- rcx : function name | |
| 1481 // -- rsp[0] : return address | |
| 1482 // -- rsp[(argc - n) * 8] : arg[n] (zero-based) | |
| 1483 // -- ... | |
| 1484 // -- rsp[(argc + 1) * 8] : receiver | |
| 1485 // ----------------------------------- | |
| 1486 | |
| 1487 const int argc = arguments().immediate(); | |
| 1488 | |
| 1489 // If the object is not a JSObject or we got an unexpected number of | |
| 1490 // arguments, bail out to the regular call. | |
| 1491 if (!object->IsJSObject() || argc != 1) return Heap::undefined_value(); | |
| 1492 | |
| 1493 Label miss; | |
| 1494 GenerateNameCheck(name, &miss); | |
| 1495 | |
| 1496 if (cell == NULL) { | |
| 1497 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); | |
| 1498 | |
| 1499 __ JumpIfSmi(rdx, &miss); | |
| 1500 | |
| 1501 CheckPrototypes(JSObject::cast(object), rdx, holder, rbx, rax, rdi, name, | |
| 1502 &miss); | |
| 1503 } else { | |
| 1504 ASSERT(cell->value() == function); | |
| 1505 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | |
| 1506 GenerateLoadFunctionFromCell(cell, function, &miss); | |
| 1507 } | |
| 1508 | |
| 1509 // Load the char code argument. | |
| 1510 Register code = rbx; | |
| 1511 __ movq(code, Operand(rsp, 1 * kPointerSize)); | |
| 1512 | |
| 1513 // Check the code is a smi. | |
| 1514 Label slow; | |
| 1515 __ JumpIfNotSmi(code, &slow); | |
| 1516 | |
| 1517 // Convert the smi code to uint16. | |
| 1518 __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); | |
| 1519 | |
| 1520 StringCharFromCodeGenerator char_from_code_generator(code, rax); | |
| 1521 char_from_code_generator.GenerateFast(masm()); | |
| 1522 __ ret(2 * kPointerSize); | |
| 1523 | |
| 1524 ICRuntimeCallHelper call_helper; | |
| 1525 char_from_code_generator.GenerateSlow(masm(), call_helper); | |
| 1526 | |
| 1527 // Tail call the full function. | |
|
antonm
2010/09/08 15:26:05
do you want to unify this comment across platforms
| |
| 1528 __ bind(&slow); | |
| 1529 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | |
| 1530 | |
| 1531 __ bind(&miss); | |
| 1532 // rcx: function name. | |
| 1533 Object* obj = GenerateMissBranch(); | |
| 1534 if (obj->IsFailure()) return obj; | |
| 1535 | |
| 1536 // Return the generated code. | |
| 1537 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | |
| 1538 } | |
| 1539 | |
| 1540 | |
| 1429 Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, | 1541 Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, |
| 1430 JSObject* holder, | 1542 JSObject* holder, |
| 1431 String* name) { | 1543 String* name) { |
| 1432 // ----------- S t a t e ------------- | 1544 // ----------- S t a t e ------------- |
| 1433 // rcx : function name | 1545 // rcx : function name |
| 1434 // rsp[0] : return address | 1546 // rsp[0] : return address |
| 1435 // rsp[8] : argument argc | 1547 // rsp[8] : argument argc |
| 1436 // rsp[16] : argument argc - 1 | 1548 // rsp[16] : argument argc - 1 |
| 1437 // ... | 1549 // ... |
| 1438 // rsp[argc * 8] : argument 1 | 1550 // rsp[argc * 8] : argument 1 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1491 return GetCode(INTERCEPTOR, name); | 1603 return GetCode(INTERCEPTOR, name); |
| 1492 } | 1604 } |
| 1493 | 1605 |
| 1494 | 1606 |
| 1495 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, | 1607 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, |
| 1496 GlobalObject* holder, | 1608 GlobalObject* holder, |
| 1497 JSGlobalPropertyCell* cell, | 1609 JSGlobalPropertyCell* cell, |
| 1498 JSFunction* function, | 1610 JSFunction* function, |
| 1499 String* name) { | 1611 String* name) { |
| 1500 // ----------- S t a t e ------------- | 1612 // ----------- S t a t e ------------- |
| 1501 // ----------------------------------- | |
| 1502 // rcx : function name | 1613 // rcx : function name |
| 1503 // rsp[0] : return address | 1614 // rsp[0] : return address |
| 1504 // rsp[8] : argument argc | 1615 // rsp[8] : argument argc |
| 1505 // rsp[16] : argument argc - 1 | 1616 // rsp[16] : argument argc - 1 |
| 1506 // ... | 1617 // ... |
| 1507 // rsp[argc * 8] : argument 1 | 1618 // rsp[argc * 8] : argument 1 |
| 1508 // rsp[(argc + 1) * 8] : argument 0 = receiver | 1619 // rsp[(argc + 1) * 8] : argument 0 = receiver |
| 1620 // ----------------------------------- | |
| 1621 | |
| 1622 SharedFunctionInfo* function_info = function->shared(); | |
| 1623 if (function_info->HasCustomCallGenerator()) { | |
| 1624 const int id = function_info->custom_call_generator_id(); | |
| 1625 Object* result = CompileCustomCall( | |
| 1626 id, object, holder, cell, function, name); | |
| 1627 // undefined means bail out to regular compiler. | |
| 1628 if (!result->IsUndefined()) return result; | |
| 1629 } | |
| 1630 | |
| 1509 Label miss; | 1631 Label miss; |
| 1510 | 1632 |
| 1511 GenerateNameCheck(name, &miss); | 1633 GenerateNameCheck(name, &miss); |
| 1512 | 1634 |
| 1513 // Get the number of arguments. | 1635 // Get the number of arguments. |
| 1514 const int argc = arguments().immediate(); | 1636 const int argc = arguments().immediate(); |
| 1515 | 1637 |
| 1516 // Get the receiver from the stack. | 1638 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
| 1517 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | |
| 1518 | 1639 |
| 1519 // If the object is the holder then we know that it's a global | 1640 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1520 // object which can only happen for contextual calls. In this case, | |
| 1521 // the receiver cannot be a smi. | |
| 1522 if (object != holder) { | |
| 1523 __ JumpIfSmi(rdx, &miss); | |
| 1524 } | |
| 1525 | |
| 1526 // Check that the maps haven't changed. | |
| 1527 CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, &miss); | |
| 1528 | |
| 1529 // Get the value from the cell. | |
| 1530 __ Move(rdi, Handle<JSGlobalPropertyCell>(cell)); | |
| 1531 __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); | |
| 1532 | |
| 1533 // Check that the cell contains the same function. | |
| 1534 if (Heap::InNewSpace(function)) { | |
| 1535 // We can't embed a pointer to a function in new space so we have | |
| 1536 // to verify that the shared function info is unchanged. This has | |
| 1537 // the nice side effect that multiple closures based on the same | |
| 1538 // function can all use this call IC. Before we load through the | |
| 1539 // function, we have to verify that it still is a function. | |
| 1540 __ JumpIfSmi(rdi, &miss); | |
| 1541 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); | |
| 1542 __ j(not_equal, &miss); | |
| 1543 | |
| 1544 // Check the shared function info. Make sure it hasn't changed. | |
| 1545 __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); | |
| 1546 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); | |
| 1547 __ j(not_equal, &miss); | |
| 1548 } else { | |
| 1549 __ Cmp(rdi, Handle<JSFunction>(function)); | |
| 1550 __ j(not_equal, &miss); | |
| 1551 } | |
| 1552 | 1641 |
| 1553 // Patch the receiver on the stack with the global proxy. | 1642 // Patch the receiver on the stack with the global proxy. |
| 1554 if (object->IsGlobalObject()) { | 1643 if (object->IsGlobalObject()) { |
| 1555 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 1644 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
| 1556 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 1645 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
| 1557 } | 1646 } |
| 1558 | 1647 |
| 1559 // Setup the context (function already in edi). | 1648 // Setup the context (function already in edi). |
| 1560 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 1649 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 1561 | 1650 |
| (...skipping 1151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2713 // Return the generated code. | 2802 // Return the generated code. |
| 2714 return GetCode(); | 2803 return GetCode(); |
| 2715 } | 2804 } |
| 2716 | 2805 |
| 2717 | 2806 |
| 2718 #undef __ | 2807 #undef __ |
| 2719 | 2808 |
| 2720 } } // namespace v8::internal | 2809 } } // namespace v8::internal |
| 2721 | 2810 |
| 2722 #endif // V8_TARGET_ARCH_X64 | 2811 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |