Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 1237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1248 | 1248 |
| 1249 | 1249 |
| 1250 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { | 1250 void CallStubCompiler::GenerateNameCheck(String* name, Label* miss) { |
| 1251 if (kind_ == Code::KEYED_CALL_IC) { | 1251 if (kind_ == Code::KEYED_CALL_IC) { |
| 1252 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); | 1252 __ cmp(Operand(ecx), Immediate(Handle<String>(name))); |
| 1253 __ j(not_equal, miss, not_taken); | 1253 __ j(not_equal, miss, not_taken); |
| 1254 } | 1254 } |
| 1255 } | 1255 } |
| 1256 | 1256 |
| 1257 | 1257 |
| 1258 void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object, | |
| 1259 JSObject* holder, | |
| 1260 String* name, | |
| 1261 Label* miss) { | |
| 1262 // Get the number of arguments. | |
| 1263 const int argc = arguments().immediate(); | |
| 1264 | |
| 1265 // Get the receiver from the stack. | |
| 1266 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | |
| 1267 | |
| 1268 // If the object is the holder then we know that it's a global | |
| 1269 // object which can only happen for contextual calls. In this case, | |
| 1270 // the receiver cannot be a smi. | |
| 1271 if (object != holder) { | |
| 1272 __ test(edx, Immediate(kSmiTagMask)); | |
| 1273 __ j(zero, miss, not_taken); | |
| 1274 } | |
| 1275 | |
| 1276 // Check that the maps haven't changed. | |
| 1277 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); | |
| 1278 } | |
| 1279 | |
| 1280 | |
| 1281 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, | |
| 1282 JSFunction* function, | |
| 1283 Label* miss) { | |
| 1284 // Get the value from the cell. | |
| 1285 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | |
| 1286 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | |
| 1287 | |
| 1288 // Check that the cell contains the same function. | |
| 1289 if (Heap::InNewSpace(function)) { | |
| 1290 // We can't embed a pointer to a function in new space so we have | |
| 1291 // to verify that the shared function info is unchanged. This has | |
| 1292 // the nice side effect that multiple closures based on the same | |
| 1293 // function can all use this call IC. Before we load through the | |
| 1294 // function, we have to verify that it still is a function. | |
| 1295 __ test(edi, Immediate(kSmiTagMask)); | |
| 1296 __ j(zero, miss, not_taken); | |
| 1297 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | |
| 1298 __ j(not_equal, miss, not_taken); | |
| 1299 | |
| 1300 // Check the shared function info. Make sure it hasn't changed. | |
| 1301 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | |
| 1302 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | |
| 1303 __ j(not_equal, miss, not_taken); | |
| 1304 } else { | |
| 1305 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | |
| 1306 __ j(not_equal, miss, not_taken); | |
| 1307 } | |
| 1308 } | |
| 1309 | |
| 1310 | |
| 1258 Object* CallStubCompiler::GenerateMissBranch() { | 1311 Object* CallStubCompiler::GenerateMissBranch() { |
| 1259 Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_); | 1312 Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_); |
| 1260 if (obj->IsFailure()) return obj; | 1313 if (obj->IsFailure()) return obj; |
| 1261 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); | 1314 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); |
| 1262 return obj; | 1315 return obj; |
| 1263 } | 1316 } |
| 1264 | 1317 |
| 1265 | 1318 |
| 1266 Object* CallStubCompiler::CompileCallField(JSObject* object, | 1319 Object* CallStubCompiler::CompileCallField(JSObject* object, |
| 1267 JSObject* holder, | 1320 JSObject* holder, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1313 Object* obj = GenerateMissBranch(); | 1366 Object* obj = GenerateMissBranch(); |
| 1314 if (obj->IsFailure()) return obj; | 1367 if (obj->IsFailure()) return obj; |
| 1315 | 1368 |
| 1316 // Return the generated code. | 1369 // Return the generated code. |
| 1317 return GetCode(FIELD, name); | 1370 return GetCode(FIELD, name); |
| 1318 } | 1371 } |
| 1319 | 1372 |
| 1320 | 1373 |
| 1321 Object* CallStubCompiler::CompileArrayPushCall(Object* object, | 1374 Object* CallStubCompiler::CompileArrayPushCall(Object* object, |
| 1322 JSObject* holder, | 1375 JSObject* holder, |
| 1376 JSGlobalPropertyCell* cell, | |
| 1323 JSFunction* function, | 1377 JSFunction* function, |
| 1324 String* name, | 1378 String* name) { |
| 1325 CheckType check) { | |
| 1326 // ----------- S t a t e ------------- | 1379 // ----------- S t a t e ------------- |
| 1327 // -- ecx : name | 1380 // -- ecx : name |
| 1328 // -- esp[0] : return address | 1381 // -- esp[0] : return address |
| 1329 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1382 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1330 // -- ... | 1383 // -- ... |
| 1331 // -- esp[(argc + 1) * 4] : receiver | 1384 // -- esp[(argc + 1) * 4] : receiver |
| 1332 // ----------------------------------- | 1385 // ----------------------------------- |
| 1333 ASSERT(check == RECEIVER_MAP_CHECK); | |
| 1334 | 1386 |
| 1335 // If object is not an array, bail out to regular call. | 1387 // If object is not an array, bail out to regular call. |
| 1336 if (!object->IsJSArray()) { | 1388 if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); |
| 1337 return Heap::undefined_value(); | |
| 1338 } | |
| 1339 | 1389 |
| 1340 Label miss; | 1390 Label miss; |
| 1341 | 1391 |
| 1342 GenerateNameCheck(name, &miss); | 1392 GenerateNameCheck(name, &miss); |
| 1343 | 1393 |
| 1344 // Get the receiver from the stack. | 1394 // Get the receiver from the stack. |
| 1345 const int argc = arguments().immediate(); | 1395 const int argc = arguments().immediate(); |
| 1346 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1396 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1347 | 1397 |
| 1348 // Check that the receiver isn't a smi. | 1398 // Check that the receiver isn't a smi. |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1462 Object* obj = GenerateMissBranch(); | 1512 Object* obj = GenerateMissBranch(); |
| 1463 if (obj->IsFailure()) return obj; | 1513 if (obj->IsFailure()) return obj; |
| 1464 | 1514 |
| 1465 // Return the generated code. | 1515 // Return the generated code. |
| 1466 return GetCode(function); | 1516 return GetCode(function); |
| 1467 } | 1517 } |
| 1468 | 1518 |
| 1469 | 1519 |
| 1470 Object* CallStubCompiler::CompileArrayPopCall(Object* object, | 1520 Object* CallStubCompiler::CompileArrayPopCall(Object* object, |
| 1471 JSObject* holder, | 1521 JSObject* holder, |
| 1522 JSGlobalPropertyCell* cell, | |
| 1472 JSFunction* function, | 1523 JSFunction* function, |
| 1473 String* name, | 1524 String* name) { |
| 1474 CheckType check) { | |
| 1475 // ----------- S t a t e ------------- | 1525 // ----------- S t a t e ------------- |
| 1476 // -- ecx : name | 1526 // -- ecx : name |
| 1477 // -- esp[0] : return address | 1527 // -- esp[0] : return address |
| 1478 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1528 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1479 // -- ... | 1529 // -- ... |
| 1480 // -- esp[(argc + 1) * 4] : receiver | 1530 // -- esp[(argc + 1) * 4] : receiver |
| 1481 // ----------------------------------- | 1531 // ----------------------------------- |
| 1482 ASSERT(check == RECEIVER_MAP_CHECK); | |
| 1483 | 1532 |
| 1484 // If object is not an array, bail out to regular call. | 1533 // If object is not an array, bail out to regular call. |
| 1485 if (!object->IsJSArray()) { | 1534 if (!object->IsJSArray() || cell != NULL) return Heap::undefined_value(); |
| 1486 return Heap::undefined_value(); | |
| 1487 } | |
| 1488 | 1535 |
| 1489 Label miss, return_undefined, call_builtin; | 1536 Label miss, return_undefined, call_builtin; |
| 1490 | 1537 |
| 1491 GenerateNameCheck(name, &miss); | 1538 GenerateNameCheck(name, &miss); |
| 1492 | 1539 |
| 1493 // Get the receiver from the stack. | 1540 // Get the receiver from the stack. |
| 1494 const int argc = arguments().immediate(); | 1541 const int argc = arguments().immediate(); |
| 1495 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1542 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1496 | 1543 |
| 1497 // Check that the receiver isn't a smi. | 1544 // Check that the receiver isn't a smi. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1544 | 1591 |
| 1545 __ bind(&miss); | 1592 __ bind(&miss); |
| 1546 Object* obj = GenerateMissBranch(); | 1593 Object* obj = GenerateMissBranch(); |
| 1547 if (obj->IsFailure()) return obj; | 1594 if (obj->IsFailure()) return obj; |
| 1548 | 1595 |
| 1549 // Return the generated code. | 1596 // Return the generated code. |
| 1550 return GetCode(function); | 1597 return GetCode(function); |
| 1551 } | 1598 } |
| 1552 | 1599 |
| 1553 | 1600 |
| 1554 Object* CallStubCompiler::CompileStringCharCodeAtCall(Object* object, | 1601 Object* CallStubCompiler::CompileStringCharCodeAtCall( |
| 1555 JSObject* holder, | 1602 Object* object, |
| 1556 JSFunction* function, | 1603 JSObject* holder, |
| 1557 String* name, | 1604 JSGlobalPropertyCell* cell, |
| 1558 CheckType check) { | 1605 JSFunction* function, |
| 1606 String* name) { | |
| 1559 // ----------- S t a t e ------------- | 1607 // ----------- S t a t e ------------- |
| 1560 // -- ecx : function name | 1608 // -- ecx : function name |
| 1561 // -- esp[0] : return address | 1609 // -- esp[0] : return address |
| 1562 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1610 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1563 // -- ... | 1611 // -- ... |
| 1564 // -- esp[(argc + 1) * 4] : receiver | 1612 // -- esp[(argc + 1) * 4] : receiver |
| 1565 // ----------------------------------- | 1613 // ----------------------------------- |
| 1566 | 1614 |
| 1567 // If object is not a string, bail out to regular call. | 1615 // If object is not a string, bail out to regular call. |
| 1568 if (!object->IsString()) return Heap::undefined_value(); | 1616 if (!object->IsString() || cell != NULL) return Heap::undefined_value(); |
| 1569 | 1617 |
| 1570 const int argc = arguments().immediate(); | 1618 const int argc = arguments().immediate(); |
| 1571 | 1619 |
| 1572 Label miss; | 1620 Label miss; |
| 1573 Label index_out_of_range; | 1621 Label index_out_of_range; |
| 1574 GenerateNameCheck(name, &miss); | 1622 GenerateNameCheck(name, &miss); |
| 1575 | 1623 |
| 1576 // Check that the maps starting from the prototype haven't changed. | 1624 // Check that the maps starting from the prototype haven't changed. |
| 1577 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1625 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| 1578 Context::STRING_FUNCTION_INDEX, | 1626 Context::STRING_FUNCTION_INDEX, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1614 Object* obj = GenerateMissBranch(); | 1662 Object* obj = GenerateMissBranch(); |
| 1615 if (obj->IsFailure()) return obj; | 1663 if (obj->IsFailure()) return obj; |
| 1616 | 1664 |
| 1617 // Return the generated code. | 1665 // Return the generated code. |
| 1618 return GetCode(function); | 1666 return GetCode(function); |
| 1619 } | 1667 } |
| 1620 | 1668 |
| 1621 | 1669 |
| 1622 Object* CallStubCompiler::CompileStringCharAtCall(Object* object, | 1670 Object* CallStubCompiler::CompileStringCharAtCall(Object* object, |
| 1623 JSObject* holder, | 1671 JSObject* holder, |
| 1672 JSGlobalPropertyCell* cell, | |
| 1624 JSFunction* function, | 1673 JSFunction* function, |
| 1625 String* name, | 1674 String* name) { |
| 1626 CheckType check) { | |
| 1627 // ----------- S t a t e ------------- | 1675 // ----------- S t a t e ------------- |
| 1628 // -- ecx : function name | 1676 // -- ecx : function name |
| 1629 // -- esp[0] : return address | 1677 // -- esp[0] : return address |
| 1630 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1678 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1631 // -- ... | 1679 // -- ... |
| 1632 // -- esp[(argc + 1) * 4] : receiver | 1680 // -- esp[(argc + 1) * 4] : receiver |
| 1633 // ----------------------------------- | 1681 // ----------------------------------- |
| 1634 | 1682 |
| 1635 // If object is not a string, bail out to regular call. | 1683 // If object is not a string, bail out to regular call. |
| 1636 if (!object->IsString()) return Heap::undefined_value(); | 1684 if (!object->IsString() || cell != NULL) return Heap::undefined_value(); |
| 1637 | 1685 |
| 1638 const int argc = arguments().immediate(); | 1686 const int argc = arguments().immediate(); |
| 1639 | 1687 |
| 1640 Label miss; | 1688 Label miss; |
| 1641 Label index_out_of_range; | 1689 Label index_out_of_range; |
| 1642 | 1690 |
| 1643 GenerateNameCheck(name, &miss); | 1691 GenerateNameCheck(name, &miss); |
| 1644 | 1692 |
| 1645 // Check that the maps starting from the prototype haven't changed. | 1693 // Check that the maps starting from the prototype haven't changed. |
| 1646 GenerateDirectLoadGlobalFunctionPrototype(masm(), | 1694 GenerateDirectLoadGlobalFunctionPrototype(masm(), |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1683 | 1731 |
| 1684 __ bind(&miss); | 1732 __ bind(&miss); |
| 1685 Object* obj = GenerateMissBranch(); | 1733 Object* obj = GenerateMissBranch(); |
| 1686 if (obj->IsFailure()) return obj; | 1734 if (obj->IsFailure()) return obj; |
| 1687 | 1735 |
| 1688 // Return the generated code. | 1736 // Return the generated code. |
| 1689 return GetCode(function); | 1737 return GetCode(function); |
| 1690 } | 1738 } |
| 1691 | 1739 |
| 1692 | 1740 |
| 1741 Object* CallStubCompiler::CompileStringFromCharCodeCall( | |
| 1742 Object* object, | |
| 1743 JSObject* holder, | |
| 1744 JSGlobalPropertyCell* cell, | |
| 1745 JSFunction* function, | |
| 1746 String* name) { | |
| 1747 // ----------- S t a t e ------------- | |
| 1748 // -- ecx : function name | |
| 1749 // -- esp[0] : return address | |
| 1750 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | |
| 1751 // -- ... | |
| 1752 // -- esp[(argc + 1) * 4] : receiver | |
| 1753 // ----------------------------------- | |
| 1754 | |
| 1755 const int argc = arguments().immediate(); | |
| 1756 | |
| 1757 // If the object is not a JSObject or we got an unexpected number of | |
| 1758 // arguments, bail out to the regular call. | |
| 1759 if (!object->IsJSObject() || argc != 1) return Heap::undefined_value(); | |
| 1760 | |
| 1761 Label miss; | |
| 1762 GenerateNameCheck(name, &miss); | |
| 1763 | |
| 1764 if (cell == NULL) { | |
| 1765 __ mov(edx, Operand(esp, 2 * kPointerSize)); | |
| 1766 | |
| 1767 STATIC_ASSERT(kSmiTag == 0); | |
| 1768 __ test(edx, Immediate(kSmiTagMask)); | |
| 1769 __ j(zero, &miss); | |
| 1770 | |
| 1771 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, | |
| 1772 &miss); | |
| 1773 } else { | |
| 1774 ASSERT(cell->value() == function); | |
| 1775 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); | |
| 1776 GenerateLoadFunctionFromCell(cell, function, &miss); | |
| 1777 } | |
| 1778 | |
| 1779 // Load the char code argument. | |
| 1780 Register code = ebx; | |
| 1781 __ mov(code, Operand(esp, 1 * kPointerSize)); | |
| 1782 | |
| 1783 // Check the code is a smi. | |
| 1784 Label slow; | |
| 1785 STATIC_ASSERT(kSmiTag == 0); | |
| 1786 __ test(code, Immediate(kSmiTagMask)); | |
| 1787 __ j(not_zero, &slow); | |
| 1788 | |
| 1789 // Convert the smi code to uint16. | |
| 1790 __ and_(code, (0xffff << kSmiTagSize) | kSmiTag); | |
|
antonm
2010/09/08 15:26:05
could it be rewritten as __ and_(Operand(code), Im
| |
| 1791 | |
| 1792 StringCharFromCodeGenerator char_from_code_generator(code, eax); | |
| 1793 char_from_code_generator.GenerateFast(masm()); | |
| 1794 __ ret(2 * kPointerSize); | |
| 1795 | |
| 1796 ICRuntimeCallHelper call_helper; | |
| 1797 char_from_code_generator.GenerateSlow(masm(), call_helper); | |
| 1798 | |
| 1799 // Tail call the full function. We do not have to patch the receiver | |
| 1800 // because the function makes no use of it. | |
| 1801 __ bind(&slow); | |
| 1802 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); | |
| 1803 | |
| 1804 __ bind(&miss); | |
| 1805 // ecx: function name. | |
| 1806 Object* obj = GenerateMissBranch(); | |
| 1807 if (obj->IsFailure()) return obj; | |
| 1808 | |
| 1809 // Return the generated code. | |
| 1810 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); | |
| 1811 } | |
| 1812 | |
| 1813 | |
| 1693 Object* CallStubCompiler::CompileCallConstant(Object* object, | 1814 Object* CallStubCompiler::CompileCallConstant(Object* object, |
| 1694 JSObject* holder, | 1815 JSObject* holder, |
| 1695 JSFunction* function, | 1816 JSFunction* function, |
| 1696 String* name, | 1817 String* name, |
| 1697 CheckType check) { | 1818 CheckType check) { |
| 1698 // ----------- S t a t e ------------- | 1819 // ----------- S t a t e ------------- |
| 1699 // -- ecx : name | 1820 // -- ecx : name |
| 1700 // -- esp[0] : return address | 1821 // -- esp[0] : return address |
| 1701 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1822 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1702 // -- ... | 1823 // -- ... |
| 1703 // -- esp[(argc + 1) * 4] : receiver | 1824 // -- esp[(argc + 1) * 4] : receiver |
| 1704 // ----------------------------------- | 1825 // ----------------------------------- |
| 1705 | 1826 |
| 1706 SharedFunctionInfo* function_info = function->shared(); | 1827 SharedFunctionInfo* function_info = function->shared(); |
| 1707 if (function_info->HasCustomCallGenerator()) { | 1828 if (function_info->HasCustomCallGenerator()) { |
| 1708 const int id = function_info->custom_call_generator_id(); | 1829 const int id = function_info->custom_call_generator_id(); |
| 1709 Object* result = | 1830 Object* result = CompileCustomCall( |
| 1710 CompileCustomCall(id, object, holder, function, name, check); | 1831 id, object, holder, NULL, function, name); |
| 1711 // undefined means bail out to regular compiler. | 1832 // undefined means bail out to regular compiler. |
| 1712 if (!result->IsUndefined()) { | 1833 if (!result->IsUndefined()) return result; |
| 1713 return result; | |
| 1714 } | |
| 1715 } | 1834 } |
| 1716 | 1835 |
| 1717 Label miss_in_smi_check; | 1836 Label miss_in_smi_check; |
| 1718 | 1837 |
| 1719 GenerateNameCheck(name, &miss_in_smi_check); | 1838 GenerateNameCheck(name, &miss_in_smi_check); |
| 1720 | 1839 |
| 1721 // Get the receiver from the stack. | 1840 // Get the receiver from the stack. |
| 1722 const int argc = arguments().immediate(); | 1841 const int argc = arguments().immediate(); |
| 1723 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1842 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1724 | 1843 |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1915 JSGlobalPropertyCell* cell, | 2034 JSGlobalPropertyCell* cell, |
| 1916 JSFunction* function, | 2035 JSFunction* function, |
| 1917 String* name) { | 2036 String* name) { |
| 1918 // ----------- S t a t e ------------- | 2037 // ----------- S t a t e ------------- |
| 1919 // -- ecx : name | 2038 // -- ecx : name |
| 1920 // -- esp[0] : return address | 2039 // -- esp[0] : return address |
| 1921 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 2040 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1922 // -- ... | 2041 // -- ... |
| 1923 // -- esp[(argc + 1) * 4] : receiver | 2042 // -- esp[(argc + 1) * 4] : receiver |
| 1924 // ----------------------------------- | 2043 // ----------------------------------- |
| 2044 | |
| 2045 SharedFunctionInfo* function_info = function->shared(); | |
| 2046 if (function_info->HasCustomCallGenerator()) { | |
| 2047 const int id = function_info->custom_call_generator_id(); | |
| 2048 Object* result = CompileCustomCall( | |
| 2049 id, object, holder, cell, function, name); | |
| 2050 // undefined means bail out to regular compiler. | |
| 2051 if (!result->IsUndefined()) return result; | |
| 2052 } | |
| 2053 | |
| 1925 Label miss; | 2054 Label miss; |
| 1926 | 2055 |
| 1927 GenerateNameCheck(name, &miss); | 2056 GenerateNameCheck(name, &miss); |
| 1928 | 2057 |
| 1929 // Get the number of arguments. | 2058 // Get the number of arguments. |
| 1930 const int argc = arguments().immediate(); | 2059 const int argc = arguments().immediate(); |
| 1931 | 2060 |
| 1932 // Get the receiver from the stack. | 2061 GenerateGlobalReceiverCheck(object, holder, name, &miss); |
| 1933 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | |
| 1934 | 2062 |
| 1935 // If the object is the holder then we know that it's a global | 2063 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1936 // object which can only happen for contextual calls. In this case, | |
| 1937 // the receiver cannot be a smi. | |
| 1938 if (object != holder) { | |
| 1939 __ test(edx, Immediate(kSmiTagMask)); | |
| 1940 __ j(zero, &miss, not_taken); | |
| 1941 } | |
| 1942 | |
| 1943 // Check that the maps haven't changed. | |
| 1944 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, &miss); | |
| 1945 | |
| 1946 // Get the value from the cell. | |
| 1947 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); | |
| 1948 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); | |
| 1949 | |
| 1950 // Check that the cell contains the same function. | |
| 1951 if (Heap::InNewSpace(function)) { | |
| 1952 // We can't embed a pointer to a function in new space so we have | |
| 1953 // to verify that the shared function info is unchanged. This has | |
| 1954 // the nice side effect that multiple closures based on the same | |
| 1955 // function can all use this call IC. Before we load through the | |
| 1956 // function, we have to verify that it still is a function. | |
| 1957 __ test(edi, Immediate(kSmiTagMask)); | |
| 1958 __ j(zero, &miss, not_taken); | |
| 1959 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); | |
| 1960 __ j(not_equal, &miss, not_taken); | |
| 1961 | |
| 1962 // Check the shared function info. Make sure it hasn't changed. | |
| 1963 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), | |
| 1964 Immediate(Handle<SharedFunctionInfo>(function->shared()))); | |
| 1965 __ j(not_equal, &miss, not_taken); | |
| 1966 } else { | |
| 1967 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); | |
| 1968 __ j(not_equal, &miss, not_taken); | |
| 1969 } | |
| 1970 | 2064 |
| 1971 // Patch the receiver on the stack with the global proxy. | 2065 // Patch the receiver on the stack with the global proxy. |
| 1972 if (object->IsGlobalObject()) { | 2066 if (object->IsGlobalObject()) { |
| 1973 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 2067 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| 1974 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); | 2068 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); |
| 1975 } | 2069 } |
| 1976 | 2070 |
| 1977 // Setup the context (function already in edi). | 2071 // Setup the context (function already in edi). |
| 1978 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2072 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
| 1979 | 2073 |
| (...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2724 // Return the generated code. | 2818 // Return the generated code. |
| 2725 return GetCode(); | 2819 return GetCode(); |
| 2726 } | 2820 } |
| 2727 | 2821 |
| 2728 | 2822 |
| 2729 #undef __ | 2823 #undef __ |
| 2730 | 2824 |
| 2731 } } // namespace v8::internal | 2825 } } // namespace v8::internal |
| 2732 | 2826 |
| 2733 #endif // V8_TARGET_ARCH_IA32 | 2827 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |