| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 725 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, |
| 726 Label* label, | 726 Label* label, |
| 727 Handle<Name> name) { | 727 Handle<Name> name) { |
| 728 if (!label->is_unused()) { | 728 if (!label->is_unused()) { |
| 729 __ bind(label); | 729 __ bind(label); |
| 730 __ li(this->name(), Operand(name)); | 730 __ li(this->name(), Operand(name)); |
| 731 } | 731 } |
| 732 } | 732 } |
| 733 | 733 |
| 734 | 734 |
| 735 static void GenerateCallFunction(MacroAssembler* masm, | |
| 736 Handle<Object> object, | |
| 737 const ParameterCount& arguments, | |
| 738 Label* miss, | |
| 739 Code::ExtraICState extra_ic_state) { | |
| 740 // ----------- S t a t e ------------- | |
| 741 // -- a0: receiver | |
| 742 // -- a1: function to call | |
| 743 // ----------------------------------- | |
| 744 // Check that the function really is a function. | |
| 745 __ JumpIfSmi(a1, miss); | |
| 746 __ GetObjectType(a1, a3, a3); | |
| 747 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); | |
| 748 | |
| 749 // Patch the receiver on the stack with the global proxy if | |
| 750 // necessary. | |
| 751 if (object->IsGlobalObject()) { | |
| 752 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); | |
| 753 __ sw(a3, MemOperand(sp, arguments.immediate() * kPointerSize)); | |
| 754 } | |
| 755 | |
| 756 // Invoke the function. | |
| 757 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) | |
| 758 ? CALL_AS_FUNCTION | |
| 759 : CALL_AS_METHOD; | |
| 760 __ InvokeFunction(a1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 761 } | |
| 762 | |
| 763 | |
| 764 static void PushInterceptorArguments(MacroAssembler* masm, | 735 static void PushInterceptorArguments(MacroAssembler* masm, |
| 765 Register receiver, | 736 Register receiver, |
| 766 Register holder, | 737 Register holder, |
| 767 Register name, | 738 Register name, |
| 768 Handle<JSObject> holder_obj) { | 739 Handle<JSObject> holder_obj) { |
| 769 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); | 740 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
| 770 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); | 741 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
| 771 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); | 742 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
| 772 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); | 743 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
| 773 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); | 744 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 ASSERT(!scratch.is(values[i])); | 906 ASSERT(!scratch.is(values[i])); |
| 936 __ sw(receiver, MemOperand(sp, index-- * kPointerSize)); | 907 __ sw(receiver, MemOperand(sp, index-- * kPointerSize)); |
| 937 } | 908 } |
| 938 | 909 |
| 939 GenerateFastApiDirectCall(masm, optimization, argc, true); | 910 GenerateFastApiDirectCall(masm, optimization, argc, true); |
| 940 } | 911 } |
| 941 | 912 |
| 942 | 913 |
| 943 class CallInterceptorCompiler BASE_EMBEDDED { | 914 class CallInterceptorCompiler BASE_EMBEDDED { |
| 944 public: | 915 public: |
| 945 CallInterceptorCompiler(StubCompiler* stub_compiler, | 916 CallInterceptorCompiler(CallStubCompiler* stub_compiler, |
| 946 const ParameterCount& arguments, | 917 const ParameterCount& arguments, |
| 947 Register name, | 918 Register name, |
| 948 Code::ExtraICState extra_ic_state) | 919 ExtraICState extra_ic_state) |
| 949 : stub_compiler_(stub_compiler), | 920 : stub_compiler_(stub_compiler), |
| 950 arguments_(arguments), | 921 arguments_(arguments), |
| 951 name_(name), | 922 name_(name), |
| 952 extra_ic_state_(extra_ic_state) {} | 923 extra_ic_state_(extra_ic_state) {} |
| 953 | 924 |
| 954 void Compile(MacroAssembler* masm, | 925 void Compile(MacroAssembler* masm, |
| 955 Handle<JSObject> object, | 926 Handle<JSObject> object, |
| 956 Handle<JSObject> holder, | 927 Handle<JSObject> holder, |
| 957 Handle<Name> name, | 928 Handle<Name> name, |
| 958 LookupResult* lookup, | 929 LookupResult* lookup, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1047 // safe to omit it here, as if present, it should be fetched | 1018 // safe to omit it here, as if present, it should be fetched |
| 1048 // by the previous CheckPrototypes. | 1019 // by the previous CheckPrototypes. |
| 1049 ASSERT(depth2 == kInvalidProtoDepth); | 1020 ASSERT(depth2 == kInvalidProtoDepth); |
| 1050 } | 1021 } |
| 1051 | 1022 |
| 1052 // Invoke function. | 1023 // Invoke function. |
| 1053 if (can_do_fast_api_call) { | 1024 if (can_do_fast_api_call) { |
| 1054 GenerateFastApiDirectCall( | 1025 GenerateFastApiDirectCall( |
| 1055 masm, optimization, arguments_.immediate(), false); | 1026 masm, optimization, arguments_.immediate(), false); |
| 1056 } else { | 1027 } else { |
| 1057 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) | |
| 1058 ? CALL_AS_FUNCTION | |
| 1059 : CALL_AS_METHOD; | |
| 1060 Handle<JSFunction> function = optimization.constant_function(); | 1028 Handle<JSFunction> function = optimization.constant_function(); |
| 1061 ParameterCount expected(function); | 1029 stub_compiler_->GenerateJumpFunction(object, function); |
| 1062 __ InvokeFunction(function, expected, arguments_, | |
| 1063 JUMP_FUNCTION, NullCallWrapper(), call_kind); | |
| 1064 } | 1030 } |
| 1065 | 1031 |
| 1066 // Deferred code for fast API call case---clean preallocated space. | 1032 // Deferred code for fast API call case---clean preallocated space. |
| 1067 if (can_do_fast_api_call) { | 1033 if (can_do_fast_api_call) { |
| 1068 __ bind(&miss_cleanup); | 1034 __ bind(&miss_cleanup); |
| 1069 FreeSpaceForFastApiCall(masm); | 1035 FreeSpaceForFastApiCall(masm); |
| 1070 __ Branch(miss_label); | 1036 __ Branch(miss_label); |
| 1071 } | 1037 } |
| 1072 | 1038 |
| 1073 // Invoke a regular function. | 1039 // Invoke a regular function. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1119 masm, receiver, holder, name_, holder_obj, | 1085 masm, receiver, holder, name_, holder_obj, |
| 1120 IC::kLoadPropertyWithInterceptorOnly); | 1086 IC::kLoadPropertyWithInterceptorOnly); |
| 1121 __ pop(name_); // Restore the name. | 1087 __ pop(name_); // Restore the name. |
| 1122 __ pop(receiver); // Restore the holder. | 1088 __ pop(receiver); // Restore the holder. |
| 1123 } | 1089 } |
| 1124 // If interceptor returns no-result sentinel, call the constant function. | 1090 // If interceptor returns no-result sentinel, call the constant function. |
| 1125 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 1091 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
| 1126 __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); | 1092 __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); |
| 1127 } | 1093 } |
| 1128 | 1094 |
| 1129 StubCompiler* stub_compiler_; | 1095 CallStubCompiler* stub_compiler_; |
| 1130 const ParameterCount& arguments_; | 1096 const ParameterCount& arguments_; |
| 1131 Register name_; | 1097 Register name_; |
| 1132 Code::ExtraICState extra_ic_state_; | 1098 ExtraICState extra_ic_state_; |
| 1133 }; | 1099 }; |
| 1134 | 1100 |
| 1135 | 1101 |
| 1136 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 1102 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { |
| 1137 __ Jump(code, RelocInfo::CODE_TARGET); | 1103 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1138 } | 1104 } |
| 1139 | 1105 |
| 1140 | 1106 |
| 1141 #undef __ | 1107 #undef __ |
| 1142 #define __ ACCESS_MASM(masm()) | 1108 #define __ ACCESS_MASM(masm()) |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1520 } | 1486 } |
| 1521 | 1487 |
| 1522 | 1488 |
| 1523 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { | 1489 void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) { |
| 1524 if (kind_ == Code::KEYED_CALL_IC) { | 1490 if (kind_ == Code::KEYED_CALL_IC) { |
| 1525 __ Branch(miss, ne, a2, Operand(name)); | 1491 __ Branch(miss, ne, a2, Operand(name)); |
| 1526 } | 1492 } |
| 1527 } | 1493 } |
| 1528 | 1494 |
| 1529 | 1495 |
| 1530 void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, | 1496 void CallStubCompiler::GenerateFunctionCheck(Register function, |
| 1531 Handle<JSObject> holder, | 1497 Register scratch, |
| 1532 Handle<Name> name, | 1498 Label* miss) { |
| 1533 Label* miss) { | 1499 __ JumpIfSmi(function, miss); |
| 1534 ASSERT(holder->IsGlobalObject()); | 1500 __ GetObjectType(function, scratch, scratch); |
| 1535 | 1501 __ Branch(miss, ne, scratch, Operand(JS_FUNCTION_TYPE)); |
| 1536 // Get the number of arguments. | |
| 1537 const int argc = arguments().immediate(); | |
| 1538 | |
| 1539 // Get the receiver from the stack. | |
| 1540 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | |
| 1541 | |
| 1542 // Check that the maps haven't changed. | |
| 1543 __ JumpIfSmi(a0, miss); | |
| 1544 CheckPrototypes( | |
| 1545 IC::CurrentTypeOf(object, isolate()), a0, holder, a3, a1, t0, name, miss); | |
| 1546 } | 1502 } |
| 1547 | 1503 |
| 1548 | 1504 |
| 1549 void CallStubCompiler::GenerateLoadFunctionFromCell( | 1505 void CallStubCompiler::GenerateLoadFunctionFromCell( |
| 1550 Handle<Cell> cell, | 1506 Handle<Cell> cell, |
| 1551 Handle<JSFunction> function, | 1507 Handle<JSFunction> function, |
| 1552 Label* miss) { | 1508 Label* miss) { |
| 1553 // Get the value from the cell. | 1509 // Get the value from the cell. |
| 1554 __ li(a3, Operand(cell)); | 1510 __ li(a3, Operand(cell)); |
| 1555 __ lw(a1, FieldMemOperand(a3, Cell::kValueOffset)); | 1511 __ lw(a1, FieldMemOperand(a3, Cell::kValueOffset)); |
| 1556 | 1512 |
| 1557 // Check that the cell contains the same function. | 1513 // Check that the cell contains the same function. |
| 1558 if (heap()->InNewSpace(*function)) { | 1514 if (heap()->InNewSpace(*function)) { |
| 1559 // We can't embed a pointer to a function in new space so we have | 1515 // We can't embed a pointer to a function in new space so we have |
| 1560 // to verify that the shared function info is unchanged. This has | 1516 // to verify that the shared function info is unchanged. This has |
| 1561 // the nice side effect that multiple closures based on the same | 1517 // the nice side effect that multiple closures based on the same |
| 1562 // function can all use this call IC. Before we load through the | 1518 // function can all use this call IC. Before we load through the |
| 1563 // function, we have to verify that it still is a function. | 1519 // function, we have to verify that it still is a function. |
| 1564 __ JumpIfSmi(a1, miss); | 1520 GenerateFunctionCheck(a1, a3, miss); |
| 1565 __ GetObjectType(a1, a3, a3); | |
| 1566 __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); | |
| 1567 | 1521 |
| 1568 // Check the shared function info. Make sure it hasn't changed. | 1522 // Check the shared function info. Make sure it hasn't changed. |
| 1569 __ li(a3, Handle<SharedFunctionInfo>(function->shared())); | 1523 __ li(a3, Handle<SharedFunctionInfo>(function->shared())); |
| 1570 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 1524 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 1571 __ Branch(miss, ne, t0, Operand(a3)); | 1525 __ Branch(miss, ne, t0, Operand(a3)); |
| 1572 } else { | 1526 } else { |
| 1573 __ Branch(miss, ne, a1, Operand(function)); | 1527 __ Branch(miss, ne, a1, Operand(function)); |
| 1574 } | 1528 } |
| 1575 } | 1529 } |
| 1576 | 1530 |
| 1577 | 1531 |
| 1578 void CallStubCompiler::GenerateMissBranch() { | 1532 void CallStubCompiler::GenerateMissBranch() { |
| 1579 Handle<Code> code = | 1533 Handle<Code> code = |
| 1580 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), | 1534 isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), |
| 1581 kind_, | 1535 kind_, |
| 1582 extra_state_); | 1536 extra_state_); |
| 1583 __ Jump(code, RelocInfo::CODE_TARGET); | 1537 __ Jump(code, RelocInfo::CODE_TARGET); |
| 1584 } | 1538 } |
| 1585 | 1539 |
| 1586 | 1540 |
| 1587 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, | 1541 Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, |
| 1588 Handle<JSObject> holder, | 1542 Handle<JSObject> holder, |
| 1589 PropertyIndex index, | 1543 PropertyIndex index, |
| 1590 Handle<Name> name) { | 1544 Handle<Name> name) { |
| 1591 // ----------- S t a t e ------------- | |
| 1592 // -- a2 : name | |
| 1593 // -- ra : return address | |
| 1594 // ----------------------------------- | |
| 1595 Label miss; | 1545 Label miss; |
| 1596 | 1546 |
| 1597 GenerateNameCheck(name, &miss); | 1547 Register reg = HandlerFrontendHeader( |
| 1598 | 1548 object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1599 const int argc = arguments().immediate(); | |
| 1600 | |
| 1601 // Get the receiver of the function from the stack into a0. | |
| 1602 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | |
| 1603 // Check that the receiver isn't a smi. | |
| 1604 __ JumpIfSmi(a0, &miss, t0); | |
| 1605 | |
| 1606 // Do the right check and compute the holder register. | |
| 1607 Register reg = CheckPrototypes( | |
| 1608 IC::CurrentTypeOf(object, isolate()), | |
| 1609 a0, holder, a1, a3, t0, name, &miss); | |
| 1610 GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder), | 1549 GenerateFastPropertyLoad(masm(), a1, reg, index.is_inobject(holder), |
| 1611 index.translate(holder), Representation::Tagged()); | 1550 index.translate(holder), Representation::Tagged()); |
| 1551 GenerateJumpFunction(object, a1, &miss); |
| 1612 | 1552 |
| 1613 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); | 1553 HandlerFrontendFooter(&miss); |
| 1614 | |
| 1615 // Handle call cache miss. | |
| 1616 __ bind(&miss); | |
| 1617 GenerateMissBranch(); | |
| 1618 | 1554 |
| 1619 // Return the generated code. | 1555 // Return the generated code. |
| 1620 return GetCode(Code::FAST, name); | 1556 return GetCode(Code::FAST, name); |
| 1621 } | 1557 } |
| 1622 | 1558 |
| 1623 | 1559 |
| 1624 Handle<Code> CallStubCompiler::CompileArrayCodeCall( | 1560 Handle<Code> CallStubCompiler::CompileArrayCodeCall( |
| 1625 Handle<Object> object, | 1561 Handle<Object> object, |
| 1626 Handle<JSObject> holder, | 1562 Handle<JSObject> holder, |
| 1627 Handle<Cell> cell, | 1563 Handle<Cell> cell, |
| 1628 Handle<JSFunction> function, | 1564 Handle<JSFunction> function, |
| 1629 Handle<String> name, | 1565 Handle<String> name, |
| 1630 Code::StubType type) { | 1566 Code::StubType type) { |
| 1631 Label miss; | 1567 Label miss; |
| 1632 | 1568 |
| 1633 // Check that function is still array. | 1569 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1634 const int argc = arguments().immediate(); | 1570 if (!cell.is_null()) { |
| 1635 GenerateNameCheck(name, &miss); | |
| 1636 Register receiver = a1; | |
| 1637 | |
| 1638 if (cell.is_null()) { | |
| 1639 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
| 1640 | |
| 1641 // Check that the receiver isn't a smi. | |
| 1642 __ JumpIfSmi(receiver, &miss); | |
| 1643 | |
| 1644 // Check that the maps haven't changed. | |
| 1645 CheckPrototypes( | |
| 1646 IC::CurrentTypeOf(object, isolate()), receiver, holder, | |
| 1647 a3, a0, t0, name, &miss); | |
| 1648 } else { | |
| 1649 ASSERT(cell->value() == *function); | 1571 ASSERT(cell->value() == *function); |
| 1650 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 1651 &miss); | |
| 1652 GenerateLoadFunctionFromCell(cell, function, &miss); | 1572 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 1653 } | 1573 } |
| 1654 | 1574 |
| 1655 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); | 1575 Handle<AllocationSite> site = isolate()->factory()->NewAllocationSite(); |
| 1656 site->SetElementsKind(GetInitialFastElementsKind()); | 1576 site->SetElementsKind(GetInitialFastElementsKind()); |
| 1657 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); | 1577 Handle<Cell> site_feedback_cell = isolate()->factory()->NewCell(site); |
| 1578 const int argc = arguments().immediate(); |
| 1658 __ li(a0, Operand(argc)); | 1579 __ li(a0, Operand(argc)); |
| 1659 __ li(a2, Operand(site_feedback_cell)); | 1580 __ li(a2, Operand(site_feedback_cell)); |
| 1660 __ li(a1, Operand(function)); | 1581 __ li(a1, Operand(function)); |
| 1661 | 1582 |
| 1662 ArrayConstructorStub stub(isolate()); | 1583 ArrayConstructorStub stub(isolate()); |
| 1663 __ TailCallStub(&stub); | 1584 __ TailCallStub(&stub); |
| 1664 | 1585 |
| 1665 __ bind(&miss); | 1586 HandlerFrontendFooter(&miss); |
| 1666 GenerateMissBranch(); | |
| 1667 | 1587 |
| 1668 // Return the generated code. | 1588 // Return the generated code. |
| 1669 return GetCode(type, name); | 1589 return GetCode(type, name); |
| 1670 } | 1590 } |
| 1671 | 1591 |
| 1672 | 1592 |
| 1673 Handle<Code> CallStubCompiler::CompileArrayPushCall( | 1593 Handle<Code> CallStubCompiler::CompileArrayPushCall( |
| 1674 Handle<Object> object, | 1594 Handle<Object> object, |
| 1675 Handle<JSObject> holder, | 1595 Handle<JSObject> holder, |
| 1676 Handle<Cell> cell, | 1596 Handle<Cell> cell, |
| 1677 Handle<JSFunction> function, | 1597 Handle<JSFunction> function, |
| 1678 Handle<String> name, | 1598 Handle<String> name, |
| 1679 Code::StubType type) { | 1599 Code::StubType type) { |
| 1680 // ----------- S t a t e ------------- | |
| 1681 // -- a2 : name | |
| 1682 // -- ra : return address | |
| 1683 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 1684 // -- ... | |
| 1685 // -- sp[argc * 4] : receiver | |
| 1686 // ----------------------------------- | |
| 1687 | |
| 1688 // If object is not an array or is observed, bail out to regular call. | 1600 // If object is not an array or is observed, bail out to regular call. |
| 1689 if (!object->IsJSArray() || | 1601 if (!object->IsJSArray() || |
| 1690 !cell.is_null() || | 1602 !cell.is_null() || |
| 1691 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1603 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 1692 return Handle<Code>::null(); | 1604 return Handle<Code>::null(); |
| 1693 } | 1605 } |
| 1694 | 1606 |
| 1695 Label miss; | 1607 Label miss; |
| 1608 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1609 Register receiver = a0; |
| 1610 Register scratch = a1; |
| 1696 | 1611 |
| 1697 GenerateNameCheck(name, &miss); | |
| 1698 | |
| 1699 Register receiver = a1; | |
| 1700 | |
| 1701 // Get the receiver from the stack. | |
| 1702 const int argc = arguments().immediate(); | 1612 const int argc = arguments().immediate(); |
| 1703 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
| 1704 | |
| 1705 // Check that the receiver isn't a smi. | |
| 1706 __ JumpIfSmi(receiver, &miss); | |
| 1707 | |
| 1708 // Check that the maps haven't changed. | |
| 1709 CheckPrototypes( | |
| 1710 IC::CurrentTypeOf(object, isolate()), receiver, holder, | |
| 1711 a3, v0, t0, name, &miss); | |
| 1712 | 1613 |
| 1713 if (argc == 0) { | 1614 if (argc == 0) { |
| 1714 // Nothing to do, just return the length. | 1615 // Nothing to do, just return the length. |
| 1715 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1616 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1716 __ DropAndRet(argc + 1); | 1617 __ DropAndRet(argc + 1); |
| 1717 } else { | 1618 } else { |
| 1718 Label call_builtin; | 1619 Label call_builtin; |
| 1719 if (argc == 1) { // Otherwise fall through to call the builtin. | 1620 if (argc == 1) { // Otherwise fall through to call the builtin. |
| 1720 Label attempt_to_grow_elements, with_write_barrier, check_double; | 1621 Label attempt_to_grow_elements, with_write_barrier, check_double; |
| 1721 | 1622 |
| 1722 Register elements = t2; | 1623 Register elements = t2; |
| 1723 Register end_elements = t1; | 1624 Register end_elements = t1; |
| 1724 // Get the elements array of the object. | 1625 // Get the elements array of the object. |
| 1725 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1626 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 1726 | 1627 |
| 1727 // Check that the elements are in fast mode and writable. | 1628 // Check that the elements are in fast mode and writable. |
| 1728 __ CheckMap(elements, | 1629 __ CheckMap(elements, |
| 1729 v0, | 1630 scratch, |
| 1730 Heap::kFixedArrayMapRootIndex, | 1631 Heap::kFixedArrayMapRootIndex, |
| 1731 &check_double, | 1632 &check_double, |
| 1732 DONT_DO_SMI_CHECK); | 1633 DONT_DO_SMI_CHECK); |
| 1733 | 1634 |
| 1734 // Get the array's length into v0 and calculate new length. | 1635 // Get the array's length into scratch and calculate new length. |
| 1735 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1636 __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1736 STATIC_ASSERT(kSmiTagSize == 1); | 1637 STATIC_ASSERT(kSmiTagSize == 1); |
| 1737 STATIC_ASSERT(kSmiTag == 0); | 1638 STATIC_ASSERT(kSmiTag == 0); |
| 1738 __ Addu(v0, v0, Operand(Smi::FromInt(argc))); | 1639 __ Addu(scratch, scratch, Operand(Smi::FromInt(argc))); |
| 1739 | 1640 |
| 1740 // Get the elements' length. | 1641 // Get the elements' length. |
| 1741 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1642 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1742 | 1643 |
| 1743 // Check if we could survive without allocation. | 1644 // Check if we could survive without allocation. |
| 1744 __ Branch(&attempt_to_grow_elements, gt, v0, Operand(t0)); | 1645 __ Branch(&attempt_to_grow_elements, gt, scratch, Operand(t0)); |
| 1745 | 1646 |
| 1746 // Check if value is a smi. | 1647 // Check if value is a smi. |
| 1747 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); | 1648 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 1748 __ JumpIfNotSmi(t0, &with_write_barrier); | 1649 __ JumpIfNotSmi(t0, &with_write_barrier); |
| 1749 | 1650 |
| 1750 // Save new length. | 1651 // Save new length. |
| 1751 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1652 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1752 | 1653 |
| 1753 // Store the value. | 1654 // Store the value. |
| 1754 // We may need a register containing the address end_elements below, | 1655 // We may need a register containing the address end_elements below, |
| 1755 // so write back the value in end_elements. | 1656 // so write back the value in end_elements. |
| 1756 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1657 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); |
| 1757 __ Addu(end_elements, elements, end_elements); | 1658 __ Addu(end_elements, elements, end_elements); |
| 1758 const int kEndElementsOffset = | 1659 const int kEndElementsOffset = |
| 1759 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; | 1660 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; |
| 1760 __ Addu(end_elements, end_elements, kEndElementsOffset); | 1661 __ Addu(end_elements, end_elements, kEndElementsOffset); |
| 1761 __ sw(t0, MemOperand(end_elements)); | 1662 __ sw(t0, MemOperand(end_elements)); |
| 1762 | 1663 |
| 1763 // Check for a smi. | 1664 // Check for a smi. |
| 1665 __ mov(v0, scratch); |
| 1764 __ DropAndRet(argc + 1); | 1666 __ DropAndRet(argc + 1); |
| 1765 | 1667 |
| 1766 __ bind(&check_double); | 1668 __ bind(&check_double); |
| 1767 | 1669 |
| 1768 // Check that the elements are in fast mode and writable. | 1670 // Check that the elements are in fast mode and writable. |
| 1769 __ CheckMap(elements, | 1671 __ CheckMap(elements, |
| 1770 a0, | 1672 scratch, |
| 1771 Heap::kFixedDoubleArrayMapRootIndex, | 1673 Heap::kFixedDoubleArrayMapRootIndex, |
| 1772 &call_builtin, | 1674 &call_builtin, |
| 1773 DONT_DO_SMI_CHECK); | 1675 DONT_DO_SMI_CHECK); |
| 1774 | 1676 |
| 1775 // Get the array's length into v0 and calculate new length. | 1677 // Get the array's length into scratch and calculate new length. |
| 1776 __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1678 __ lw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1777 STATIC_ASSERT(kSmiTagSize == 1); | 1679 STATIC_ASSERT(kSmiTagSize == 1); |
| 1778 STATIC_ASSERT(kSmiTag == 0); | 1680 STATIC_ASSERT(kSmiTag == 0); |
| 1779 __ Addu(v0, v0, Operand(Smi::FromInt(argc))); | 1681 __ Addu(scratch, scratch, Operand(Smi::FromInt(argc))); |
| 1780 | 1682 |
| 1781 // Get the elements' length. | 1683 // Get the elements' length. |
| 1782 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1684 __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1783 | 1685 |
| 1784 // Check if we could survive without allocation. | 1686 // Check if we could survive without allocation. |
| 1785 __ Branch(&call_builtin, gt, v0, Operand(t0)); | 1687 __ Branch(&call_builtin, gt, scratch, Operand(t0)); |
| 1786 | 1688 |
| 1787 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); | 1689 __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 1788 __ StoreNumberToDoubleElements( | 1690 __ StoreNumberToDoubleElements( |
| 1789 t0, v0, elements, a3, t1, a2, | 1691 t0, scratch, elements, a3, t1, a2, |
| 1790 &call_builtin, argc * kDoubleSize); | 1692 &call_builtin, argc * kDoubleSize); |
| 1791 | 1693 |
| 1792 // Save new length. | 1694 // Save new length. |
| 1793 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1695 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1794 | 1696 |
| 1795 // Check for a smi. | 1697 __ mov(v0, scratch); |
| 1796 __ DropAndRet(argc + 1); | 1698 __ DropAndRet(argc + 1); |
| 1797 | 1699 |
| 1798 __ bind(&with_write_barrier); | 1700 __ bind(&with_write_barrier); |
| 1799 | 1701 |
| 1800 __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1702 __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1801 | 1703 |
| 1802 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { | 1704 if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { |
| 1803 Label fast_object, not_fast_object; | 1705 Label fast_object, not_fast_object; |
| 1804 __ CheckFastObjectElements(a3, t3, ¬_fast_object); | 1706 __ CheckFastObjectElements(a3, t3, ¬_fast_object); |
| 1805 __ jmp(&fast_object); | 1707 __ jmp(&fast_object); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1835 ElementsTransitionGenerator:: | 1737 ElementsTransitionGenerator:: |
| 1836 GenerateMapChangeElementsTransition(masm(), | 1738 GenerateMapChangeElementsTransition(masm(), |
| 1837 DONT_TRACK_ALLOCATION_SITE, | 1739 DONT_TRACK_ALLOCATION_SITE, |
| 1838 NULL); | 1740 NULL); |
| 1839 __ bind(&fast_object); | 1741 __ bind(&fast_object); |
| 1840 } else { | 1742 } else { |
| 1841 __ CheckFastObjectElements(a3, a3, &call_builtin); | 1743 __ CheckFastObjectElements(a3, a3, &call_builtin); |
| 1842 } | 1744 } |
| 1843 | 1745 |
| 1844 // Save new length. | 1746 // Save new length. |
| 1845 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1747 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1846 | 1748 |
| 1847 // Store the value. | 1749 // Store the value. |
| 1848 // We may need a register containing the address end_elements below, | 1750 // We may need a register containing the address end_elements below, |
| 1849 // so write back the value in end_elements. | 1751 // so write back the value in end_elements. |
| 1850 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1752 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); |
| 1851 __ Addu(end_elements, elements, end_elements); | 1753 __ Addu(end_elements, elements, end_elements); |
| 1852 __ Addu(end_elements, end_elements, kEndElementsOffset); | 1754 __ Addu(end_elements, end_elements, kEndElementsOffset); |
| 1853 __ sw(t0, MemOperand(end_elements)); | 1755 __ sw(t0, MemOperand(end_elements)); |
| 1854 | 1756 |
| 1855 __ RecordWrite(elements, | 1757 __ RecordWrite(elements, |
| 1856 end_elements, | 1758 end_elements, |
| 1857 t0, | 1759 t0, |
| 1858 kRAHasNotBeenSaved, | 1760 kRAHasNotBeenSaved, |
| 1859 kDontSaveFPRegs, | 1761 kDontSaveFPRegs, |
| 1860 EMIT_REMEMBERED_SET, | 1762 EMIT_REMEMBERED_SET, |
| 1861 OMIT_SMI_CHECK); | 1763 OMIT_SMI_CHECK); |
| 1764 __ mov(v0, scratch); |
| 1862 __ DropAndRet(argc + 1); | 1765 __ DropAndRet(argc + 1); |
| 1863 | 1766 |
| 1864 __ bind(&attempt_to_grow_elements); | 1767 __ bind(&attempt_to_grow_elements); |
| 1865 // v0: array's length + 1. | 1768 // scratch: array's length + 1. |
| 1866 // t0: elements' length. | 1769 // t0: elements' length. |
| 1867 | 1770 |
| 1868 if (!FLAG_inline_new) { | 1771 if (!FLAG_inline_new) { |
| 1869 __ Branch(&call_builtin); | 1772 __ Branch(&call_builtin); |
| 1870 } | 1773 } |
| 1871 | 1774 |
| 1872 __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize)); | 1775 __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 1873 // Growing elements that are SMI-only requires special handling in case | 1776 // Growing elements that are SMI-only requires special handling in case |
| 1874 // the new element is non-Smi. For now, delegate to the builtin. | 1777 // the new element is non-Smi. For now, delegate to the builtin. |
| 1875 Label no_fast_elements_check; | 1778 Label no_fast_elements_check; |
| 1876 __ JumpIfSmi(a2, &no_fast_elements_check); | 1779 __ JumpIfSmi(a2, &no_fast_elements_check); |
| 1877 __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset)); | 1780 __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1878 __ CheckFastObjectElements(t3, t3, &call_builtin); | 1781 __ CheckFastObjectElements(t3, t3, &call_builtin); |
| 1879 __ bind(&no_fast_elements_check); | 1782 __ bind(&no_fast_elements_check); |
| 1880 | 1783 |
| 1881 ExternalReference new_space_allocation_top = | 1784 ExternalReference new_space_allocation_top = |
| 1882 ExternalReference::new_space_allocation_top_address(isolate()); | 1785 ExternalReference::new_space_allocation_top_address(isolate()); |
| 1883 ExternalReference new_space_allocation_limit = | 1786 ExternalReference new_space_allocation_limit = |
| 1884 ExternalReference::new_space_allocation_limit_address(isolate()); | 1787 ExternalReference::new_space_allocation_limit_address(isolate()); |
| 1885 | 1788 |
| 1886 const int kAllocationDelta = 4; | 1789 const int kAllocationDelta = 4; |
| 1887 // Load top and check if it is the end of elements. | 1790 // Load top and check if it is the end of elements. |
| 1888 __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); | 1791 __ sll(end_elements, scratch, kPointerSizeLog2 - kSmiTagSize); |
| 1889 __ Addu(end_elements, elements, end_elements); | 1792 __ Addu(end_elements, elements, end_elements); |
| 1890 __ Addu(end_elements, end_elements, Operand(kEndElementsOffset)); | 1793 __ Addu(end_elements, end_elements, Operand(kEndElementsOffset)); |
| 1891 __ li(t3, Operand(new_space_allocation_top)); | 1794 __ li(t3, Operand(new_space_allocation_top)); |
| 1892 __ lw(a3, MemOperand(t3)); | 1795 __ lw(a3, MemOperand(t3)); |
| 1893 __ Branch(&call_builtin, ne, end_elements, Operand(a3)); | 1796 __ Branch(&call_builtin, ne, end_elements, Operand(a3)); |
| 1894 | 1797 |
| 1895 __ li(t5, Operand(new_space_allocation_limit)); | 1798 __ li(t5, Operand(new_space_allocation_limit)); |
| 1896 __ lw(t5, MemOperand(t5)); | 1799 __ lw(t5, MemOperand(t5)); |
| 1897 __ Addu(a3, a3, Operand(kAllocationDelta * kPointerSize)); | 1800 __ Addu(a3, a3, Operand(kAllocationDelta * kPointerSize)); |
| 1898 __ Branch(&call_builtin, hi, a3, Operand(t5)); | 1801 __ Branch(&call_builtin, hi, a3, Operand(t5)); |
| 1899 | 1802 |
| 1900 // We fit and could grow elements. | 1803 // We fit and could grow elements. |
| 1901 // Update new_space_allocation_top. | 1804 // Update new_space_allocation_top. |
| 1902 __ sw(a3, MemOperand(t3)); | 1805 __ sw(a3, MemOperand(t3)); |
| 1903 // Push the argument. | 1806 // Push the argument. |
| 1904 __ sw(a2, MemOperand(end_elements)); | 1807 __ sw(a2, MemOperand(end_elements)); |
| 1905 // Fill the rest with holes. | 1808 // Fill the rest with holes. |
| 1906 __ LoadRoot(a3, Heap::kTheHoleValueRootIndex); | 1809 __ LoadRoot(a3, Heap::kTheHoleValueRootIndex); |
| 1907 for (int i = 1; i < kAllocationDelta; i++) { | 1810 for (int i = 1; i < kAllocationDelta; i++) { |
| 1908 __ sw(a3, MemOperand(end_elements, i * kPointerSize)); | 1811 __ sw(a3, MemOperand(end_elements, i * kPointerSize)); |
| 1909 } | 1812 } |
| 1910 | 1813 |
| 1911 // Update elements' and array's sizes. | 1814 // Update elements' and array's sizes. |
| 1912 __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1815 __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1913 __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta))); | 1816 __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta))); |
| 1914 __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1817 __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
| 1915 | 1818 |
| 1916 // Elements are in new space, so write barrier is not required. | 1819 // Elements are in new space, so write barrier is not required. |
| 1820 __ mov(v0, scratch); |
| 1917 __ DropAndRet(argc + 1); | 1821 __ DropAndRet(argc + 1); |
| 1918 } | 1822 } |
| 1919 __ bind(&call_builtin); | 1823 __ bind(&call_builtin); |
| 1920 __ TailCallExternalReference( | 1824 __ TailCallExternalReference( |
| 1921 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1); | 1825 ExternalReference(Builtins::c_ArrayPush, isolate()), argc + 1, 1); |
| 1922 } | 1826 } |
| 1923 | 1827 |
| 1924 // Handle call cache miss. | 1828 HandlerFrontendFooter(&miss); |
| 1925 __ bind(&miss); | |
| 1926 GenerateMissBranch(); | |
| 1927 | 1829 |
| 1928 // Return the generated code. | 1830 // Return the generated code. |
| 1929 return GetCode(type, name); | 1831 return GetCode(type, name); |
| 1930 } | 1832 } |
| 1931 | 1833 |
| 1932 | 1834 |
| 1933 Handle<Code> CallStubCompiler::CompileArrayPopCall( | 1835 Handle<Code> CallStubCompiler::CompileArrayPopCall( |
| 1934 Handle<Object> object, | 1836 Handle<Object> object, |
| 1935 Handle<JSObject> holder, | 1837 Handle<JSObject> holder, |
| 1936 Handle<Cell> cell, | 1838 Handle<Cell> cell, |
| 1937 Handle<JSFunction> function, | 1839 Handle<JSFunction> function, |
| 1938 Handle<String> name, | 1840 Handle<String> name, |
| 1939 Code::StubType type) { | 1841 Code::StubType type) { |
| 1940 // ----------- S t a t e ------------- | |
| 1941 // -- a2 : name | |
| 1942 // -- ra : return address | |
| 1943 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 1944 // -- ... | |
| 1945 // -- sp[argc * 4] : receiver | |
| 1946 // ----------------------------------- | |
| 1947 | |
| 1948 // If object is not an array or is observed, bail out to regular call. | 1842 // If object is not an array or is observed, bail out to regular call. |
| 1949 if (!object->IsJSArray() || | 1843 if (!object->IsJSArray() || |
| 1950 !cell.is_null() || | 1844 !cell.is_null() || |
| 1951 Handle<JSArray>::cast(object)->map()->is_observed()) { | 1845 Handle<JSArray>::cast(object)->map()->is_observed()) { |
| 1952 return Handle<Code>::null(); | 1846 return Handle<Code>::null(); |
| 1953 } | 1847 } |
| 1954 | 1848 |
| 1955 Label miss, return_undefined, call_builtin; | 1849 Label miss, return_undefined, call_builtin; |
| 1956 Register receiver = a1; | 1850 Register receiver = a0; |
| 1851 Register scratch = a1; |
| 1957 Register elements = a3; | 1852 Register elements = a3; |
| 1958 GenerateNameCheck(name, &miss); | 1853 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 1959 | |
| 1960 // Get the receiver from the stack. | |
| 1961 const int argc = arguments().immediate(); | |
| 1962 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
| 1963 // Check that the receiver isn't a smi. | |
| 1964 __ JumpIfSmi(receiver, &miss); | |
| 1965 | |
| 1966 // Check that the maps haven't changed. | |
| 1967 CheckPrototypes( | |
| 1968 IC::CurrentTypeOf(object, isolate()), receiver, holder, | |
| 1969 elements, t0, v0, name, &miss); | |
| 1970 | 1854 |
| 1971 // Get the elements array of the object. | 1855 // Get the elements array of the object. |
| 1972 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1856 __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
| 1973 | 1857 |
| 1974 // Check that the elements are in fast mode and writable. | 1858 // Check that the elements are in fast mode and writable. |
| 1975 __ CheckMap(elements, | 1859 __ CheckMap(elements, |
| 1976 v0, | 1860 scratch, |
| 1977 Heap::kFixedArrayMapRootIndex, | 1861 Heap::kFixedArrayMapRootIndex, |
| 1978 &call_builtin, | 1862 &call_builtin, |
| 1979 DONT_DO_SMI_CHECK); | 1863 DONT_DO_SMI_CHECK); |
| 1980 | 1864 |
| 1981 // Get the array's length into t0 and calculate new length. | 1865 // Get the array's length into t0 and calculate new length. |
| 1982 __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1866 __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1983 __ Subu(t0, t0, Operand(Smi::FromInt(1))); | 1867 __ Subu(t0, t0, Operand(Smi::FromInt(1))); |
| 1984 __ Branch(&return_undefined, lt, t0, Operand(zero_reg)); | 1868 __ Branch(&return_undefined, lt, t0, Operand(zero_reg)); |
| 1985 | 1869 |
| 1986 // Get the last element. | 1870 // Get the last element. |
| 1987 __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); | 1871 __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); |
| 1988 STATIC_ASSERT(kSmiTagSize == 1); | 1872 STATIC_ASSERT(kSmiTagSize == 1); |
| 1989 STATIC_ASSERT(kSmiTag == 0); | 1873 STATIC_ASSERT(kSmiTag == 0); |
| 1990 // We can't address the last element in one operation. Compute the more | 1874 // We can't address the last element in one operation. Compute the more |
| 1991 // expensive shift first, and use an offset later on. | 1875 // expensive shift first, and use an offset later on. |
| 1992 __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize); | 1876 __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize); |
| 1993 __ Addu(elements, elements, t1); | 1877 __ Addu(elements, elements, t1); |
| 1994 __ lw(v0, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 1878 __ lw(scratch, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
| 1995 __ Branch(&call_builtin, eq, v0, Operand(t2)); | 1879 __ Branch(&call_builtin, eq, scratch, Operand(t2)); |
| 1996 | 1880 |
| 1997 // Set the array's length. | 1881 // Set the array's length. |
| 1998 __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1882 __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1999 | 1883 |
| 2000 // Fill with the hole. | 1884 // Fill with the hole. |
| 2001 __ sw(t2, FieldMemOperand(elements, FixedArray::kHeaderSize)); | 1885 __ sw(t2, FieldMemOperand(elements, FixedArray::kHeaderSize)); |
| 1886 const int argc = arguments().immediate(); |
| 1887 __ mov(v0, scratch); |
| 2002 __ DropAndRet(argc + 1); | 1888 __ DropAndRet(argc + 1); |
| 2003 | 1889 |
| 2004 __ bind(&return_undefined); | 1890 __ bind(&return_undefined); |
| 2005 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); | 1891 __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); |
| 2006 __ DropAndRet(argc + 1); | 1892 __ DropAndRet(argc + 1); |
| 2007 | 1893 |
| 2008 __ bind(&call_builtin); | 1894 __ bind(&call_builtin); |
| 2009 __ TailCallExternalReference( | 1895 __ TailCallExternalReference( |
| 2010 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1); | 1896 ExternalReference(Builtins::c_ArrayPop, isolate()), argc + 1, 1); |
| 2011 | 1897 |
| 2012 // Handle call cache miss. | 1898 HandlerFrontendFooter(&miss); |
| 2013 __ bind(&miss); | |
| 2014 GenerateMissBranch(); | |
| 2015 | 1899 |
| 2016 // Return the generated code. | 1900 // Return the generated code. |
| 2017 return GetCode(type, name); | 1901 return GetCode(type, name); |
| 2018 } | 1902 } |
| 2019 | 1903 |
| 2020 | 1904 |
| 2021 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( | 1905 Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall( |
| 2022 Handle<Object> object, | 1906 Handle<Object> object, |
| 2023 Handle<JSObject> holder, | 1907 Handle<JSObject> holder, |
| 2024 Handle<Cell> cell, | 1908 Handle<Cell> cell, |
| 2025 Handle<JSFunction> function, | 1909 Handle<JSFunction> function, |
| 2026 Handle<String> name, | 1910 Handle<String> name, |
| 2027 Code::StubType type) { | 1911 Code::StubType type) { |
| 2028 // ----------- S t a t e ------------- | |
| 2029 // -- a2 : function name | |
| 2030 // -- ra : return address | |
| 2031 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 2032 // -- ... | |
| 2033 // -- sp[argc * 4] : receiver | |
| 2034 // ----------------------------------- | |
| 2035 | |
| 2036 // If object is not a string, bail out to regular call. | 1912 // If object is not a string, bail out to regular call. |
| 2037 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1913 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2038 | 1914 |
| 2039 const int argc = arguments().immediate(); | |
| 2040 Label miss; | 1915 Label miss; |
| 2041 Label name_miss; | 1916 Label name_miss; |
| 2042 Label index_out_of_range; | 1917 Label index_out_of_range; |
| 2043 | 1918 |
| 2044 Label* index_out_of_range_label = &index_out_of_range; | 1919 Label* index_out_of_range_label = &index_out_of_range; |
| 2045 | 1920 |
| 2046 if (kind_ == Code::CALL_IC && | 1921 if (kind_ == Code::CALL_IC && |
| 2047 (CallICBase::StringStubState::decode(extra_state_) == | 1922 (CallICBase::StringStubState::decode(extra_state_) == |
| 2048 DEFAULT_STRING_STUB)) { | 1923 DEFAULT_STRING_STUB)) { |
| 2049 index_out_of_range_label = &miss; | 1924 index_out_of_range_label = &miss; |
| 2050 } | 1925 } |
| 2051 | 1926 |
| 2052 GenerateNameCheck(name, &name_miss); | 1927 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2053 | 1928 |
| 2054 // Check that the maps starting from the prototype haven't changed. | 1929 Register receiver = a0; |
| 2055 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2056 Context::STRING_FUNCTION_INDEX, | |
| 2057 v0, | |
| 2058 &miss); | |
| 2059 ASSERT(!object.is_identical_to(holder)); | |
| 2060 Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate()))); | |
| 2061 CheckPrototypes( | |
| 2062 IC::CurrentTypeOf(prototype, isolate()), | |
| 2063 v0, holder, a1, a3, t0, name, &miss); | |
| 2064 | |
| 2065 Register receiver = a1; | |
| 2066 Register index = t1; | 1930 Register index = t1; |
| 2067 Register result = v0; | 1931 Register result = a1; |
| 1932 const int argc = arguments().immediate(); |
| 2068 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | 1933 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); |
| 2069 if (argc > 0) { | 1934 if (argc > 0) { |
| 2070 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 1935 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 2071 } else { | 1936 } else { |
| 2072 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 1937 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2073 } | 1938 } |
| 2074 | 1939 |
| 2075 StringCharCodeAtGenerator generator(receiver, | 1940 StringCharCodeAtGenerator generator(receiver, |
| 2076 index, | 1941 index, |
| 2077 result, | 1942 result, |
| 2078 &miss, // When not a string. | 1943 &miss, // When not a string. |
| 2079 &miss, // When not a number. | 1944 &miss, // When not a number. |
| 2080 index_out_of_range_label, | 1945 index_out_of_range_label, |
| 2081 STRING_INDEX_IS_NUMBER); | 1946 STRING_INDEX_IS_NUMBER); |
| 2082 generator.GenerateFast(masm()); | 1947 generator.GenerateFast(masm()); |
| 1948 __ mov(v0, result); |
| 2083 __ DropAndRet(argc + 1); | 1949 __ DropAndRet(argc + 1); |
| 2084 | 1950 |
| 2085 StubRuntimeCallHelper call_helper; | 1951 StubRuntimeCallHelper call_helper; |
| 2086 generator.GenerateSlow(masm(), call_helper); | 1952 generator.GenerateSlow(masm(), call_helper); |
| 2087 | 1953 |
| 2088 if (index_out_of_range.is_linked()) { | 1954 if (index_out_of_range.is_linked()) { |
| 2089 __ bind(&index_out_of_range); | 1955 __ bind(&index_out_of_range); |
| 2090 __ LoadRoot(v0, Heap::kNanValueRootIndex); | 1956 __ LoadRoot(v0, Heap::kNanValueRootIndex); |
| 2091 __ DropAndRet(argc + 1); | 1957 __ DropAndRet(argc + 1); |
| 2092 } | 1958 } |
| 2093 | 1959 |
| 2094 __ bind(&miss); | 1960 __ bind(&miss); |
| 2095 // Restore function name in a2. | 1961 // Restore function name in a2. |
| 2096 __ li(a2, name); | 1962 __ li(a2, name); |
| 2097 __ bind(&name_miss); | 1963 HandlerFrontendFooter(&name_miss); |
| 2098 GenerateMissBranch(); | |
| 2099 | 1964 |
| 2100 // Return the generated code. | 1965 // Return the generated code. |
| 2101 return GetCode(type, name); | 1966 return GetCode(type, name); |
| 2102 } | 1967 } |
| 2103 | 1968 |
| 2104 | 1969 |
| 2105 Handle<Code> CallStubCompiler::CompileStringCharAtCall( | 1970 Handle<Code> CallStubCompiler::CompileStringCharAtCall( |
| 2106 Handle<Object> object, | 1971 Handle<Object> object, |
| 2107 Handle<JSObject> holder, | 1972 Handle<JSObject> holder, |
| 2108 Handle<Cell> cell, | 1973 Handle<Cell> cell, |
| 2109 Handle<JSFunction> function, | 1974 Handle<JSFunction> function, |
| 2110 Handle<String> name, | 1975 Handle<String> name, |
| 2111 Code::StubType type) { | 1976 Code::StubType type) { |
| 2112 // ----------- S t a t e ------------- | |
| 2113 // -- a2 : function name | |
| 2114 // -- ra : return address | |
| 2115 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 2116 // -- ... | |
| 2117 // -- sp[argc * 4] : receiver | |
| 2118 // ----------------------------------- | |
| 2119 | |
| 2120 // If object is not a string, bail out to regular call. | 1977 // If object is not a string, bail out to regular call. |
| 2121 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); | 1978 if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); |
| 2122 | 1979 |
| 2123 const int argc = arguments().immediate(); | 1980 const int argc = arguments().immediate(); |
| 2124 Label miss; | 1981 Label miss; |
| 2125 Label name_miss; | 1982 Label name_miss; |
| 2126 Label index_out_of_range; | 1983 Label index_out_of_range; |
| 2127 Label* index_out_of_range_label = &index_out_of_range; | 1984 Label* index_out_of_range_label = &index_out_of_range; |
| 2128 if (kind_ == Code::CALL_IC && | 1985 if (kind_ == Code::CALL_IC && |
| 2129 (CallICBase::StringStubState::decode(extra_state_) == | 1986 (CallICBase::StringStubState::decode(extra_state_) == |
| 2130 DEFAULT_STRING_STUB)) { | 1987 DEFAULT_STRING_STUB)) { |
| 2131 index_out_of_range_label = &miss; | 1988 index_out_of_range_label = &miss; |
| 2132 } | 1989 } |
| 2133 GenerateNameCheck(name, &name_miss); | |
| 2134 | 1990 |
| 2135 // Check that the maps starting from the prototype haven't changed. | 1991 HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss); |
| 2136 GenerateDirectLoadGlobalFunctionPrototype(masm(), | |
| 2137 Context::STRING_FUNCTION_INDEX, | |
| 2138 v0, | |
| 2139 &miss); | |
| 2140 ASSERT(!object.is_identical_to(holder)); | |
| 2141 Handle<JSObject> prototype(JSObject::cast(object->GetPrototype(isolate()))); | |
| 2142 CheckPrototypes( | |
| 2143 IC::CurrentTypeOf(prototype, isolate()), | |
| 2144 v0, holder, a1, a3, t0, name, &miss); | |
| 2145 | 1992 |
| 2146 Register receiver = v0; | 1993 Register receiver = a0; |
| 2147 Register index = t1; | 1994 Register index = t1; |
| 2148 Register scratch = a3; | 1995 Register scratch = a3; |
| 2149 Register result = v0; | 1996 Register result = a1; |
| 2150 __ lw(receiver, MemOperand(sp, argc * kPointerSize)); | |
| 2151 if (argc > 0) { | 1997 if (argc > 0) { |
| 2152 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); | 1998 __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 2153 } else { | 1999 } else { |
| 2154 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); | 2000 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); |
| 2155 } | 2001 } |
| 2156 | 2002 |
| 2157 StringCharAtGenerator generator(receiver, | 2003 StringCharAtGenerator generator(receiver, |
| 2158 index, | 2004 index, |
| 2159 scratch, | 2005 scratch, |
| 2160 result, | 2006 result, |
| 2161 &miss, // When not a string. | 2007 &miss, // When not a string. |
| 2162 &miss, // When not a number. | 2008 &miss, // When not a number. |
| 2163 index_out_of_range_label, | 2009 index_out_of_range_label, |
| 2164 STRING_INDEX_IS_NUMBER); | 2010 STRING_INDEX_IS_NUMBER); |
| 2165 generator.GenerateFast(masm()); | 2011 generator.GenerateFast(masm()); |
| 2012 __ mov(v0, result); |
| 2166 __ DropAndRet(argc + 1); | 2013 __ DropAndRet(argc + 1); |
| 2167 | 2014 |
| 2168 StubRuntimeCallHelper call_helper; | 2015 StubRuntimeCallHelper call_helper; |
| 2169 generator.GenerateSlow(masm(), call_helper); | 2016 generator.GenerateSlow(masm(), call_helper); |
| 2170 | 2017 |
| 2171 if (index_out_of_range.is_linked()) { | 2018 if (index_out_of_range.is_linked()) { |
| 2172 __ bind(&index_out_of_range); | 2019 __ bind(&index_out_of_range); |
| 2173 __ LoadRoot(v0, Heap::kempty_stringRootIndex); | 2020 __ LoadRoot(v0, Heap::kempty_stringRootIndex); |
| 2174 __ DropAndRet(argc + 1); | 2021 __ DropAndRet(argc + 1); |
| 2175 } | 2022 } |
| 2176 | 2023 |
| 2177 __ bind(&miss); | 2024 __ bind(&miss); |
| 2178 // Restore function name in a2. | 2025 // Restore function name in a2. |
| 2179 __ li(a2, name); | 2026 __ li(a2, name); |
| 2180 __ bind(&name_miss); | 2027 HandlerFrontendFooter(&name_miss); |
| 2181 GenerateMissBranch(); | |
| 2182 | 2028 |
| 2183 // Return the generated code. | 2029 // Return the generated code. |
| 2184 return GetCode(type, name); | 2030 return GetCode(type, name); |
| 2185 } | 2031 } |
| 2186 | 2032 |
| 2187 | 2033 |
| 2188 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( | 2034 Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall( |
| 2189 Handle<Object> object, | 2035 Handle<Object> object, |
| 2190 Handle<JSObject> holder, | 2036 Handle<JSObject> holder, |
| 2191 Handle<Cell> cell, | 2037 Handle<Cell> cell, |
| 2192 Handle<JSFunction> function, | 2038 Handle<JSFunction> function, |
| 2193 Handle<String> name, | 2039 Handle<String> name, |
| 2194 Code::StubType type) { | 2040 Code::StubType type) { |
| 2195 // ----------- S t a t e ------------- | |
| 2196 // -- a2 : function name | |
| 2197 // -- ra : return address | |
| 2198 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 2199 // -- ... | |
| 2200 // -- sp[argc * 4] : receiver | |
| 2201 // ----------------------------------- | |
| 2202 | |
| 2203 const int argc = arguments().immediate(); | 2041 const int argc = arguments().immediate(); |
| 2204 | 2042 |
| 2205 // If the object is not a JSObject or we got an unexpected number of | 2043 // If the object is not a JSObject or we got an unexpected number of |
| 2206 // arguments, bail out to the regular call. | 2044 // arguments, bail out to the regular call. |
| 2207 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2045 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2208 | 2046 |
| 2209 Label miss; | 2047 Label miss; |
| 2210 GenerateNameCheck(name, &miss); | 2048 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2211 | 2049 if (!cell.is_null()) { |
| 2212 if (cell.is_null()) { | |
| 2213 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | |
| 2214 | |
| 2215 STATIC_ASSERT(kSmiTag == 0); | |
| 2216 __ JumpIfSmi(a1, &miss); | |
| 2217 | |
| 2218 CheckPrototypes( | |
| 2219 IC::CurrentTypeOf(object, isolate()), | |
| 2220 a1, holder, v0, a3, t0, name, &miss); | |
| 2221 } else { | |
| 2222 ASSERT(cell->value() == *function); | 2050 ASSERT(cell->value() == *function); |
| 2223 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2224 &miss); | |
| 2225 GenerateLoadFunctionFromCell(cell, function, &miss); | 2051 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2226 } | 2052 } |
| 2227 | 2053 |
| 2228 // Load the char code argument. | 2054 // Load the char code argument. |
| 2229 Register code = a1; | 2055 Register code = a1; |
| 2230 __ lw(code, MemOperand(sp, 0 * kPointerSize)); | 2056 __ lw(code, MemOperand(sp, 0 * kPointerSize)); |
| 2231 | 2057 |
| 2232 // Check the code is a smi. | 2058 // Check the code is a smi. |
| 2233 Label slow; | 2059 Label slow; |
| 2234 STATIC_ASSERT(kSmiTag == 0); | 2060 STATIC_ASSERT(kSmiTag == 0); |
| 2235 __ JumpIfNotSmi(code, &slow); | 2061 __ JumpIfNotSmi(code, &slow); |
| 2236 | 2062 |
| 2237 // Convert the smi code to uint16. | 2063 // Convert the smi code to uint16. |
| 2238 __ And(code, code, Operand(Smi::FromInt(0xffff))); | 2064 __ And(code, code, Operand(Smi::FromInt(0xffff))); |
| 2239 | 2065 |
| 2240 StringCharFromCodeGenerator generator(code, v0); | 2066 StringCharFromCodeGenerator generator(code, v0); |
| 2241 generator.GenerateFast(masm()); | 2067 generator.GenerateFast(masm()); |
| 2242 __ DropAndRet(argc + 1); | 2068 __ DropAndRet(argc + 1); |
| 2243 | 2069 |
| 2244 StubRuntimeCallHelper call_helper; | 2070 StubRuntimeCallHelper call_helper; |
| 2245 generator.GenerateSlow(masm(), call_helper); | 2071 generator.GenerateSlow(masm(), call_helper); |
| 2246 | 2072 |
| 2247 // Tail call the full function. We do not have to patch the receiver | |
| 2248 // because the function makes no use of it. | |
| 2249 __ bind(&slow); | 2073 __ bind(&slow); |
| 2250 ParameterCount expected(function); | 2074 // We do not have to patch the receiver because the function makes no use of |
| 2251 __ InvokeFunction(function, expected, arguments(), | 2075 // it. |
| 2252 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2076 GenerateJumpFunctionIgnoreReceiver(function); |
| 2253 | 2077 |
| 2254 __ bind(&miss); | 2078 HandlerFrontendFooter(&miss); |
| 2255 // a2: function name. | |
| 2256 GenerateMissBranch(); | |
| 2257 | 2079 |
| 2258 // Return the generated code. | 2080 // Return the generated code. |
| 2259 return GetCode(type, name); | 2081 return GetCode(type, name); |
| 2260 } | 2082 } |
| 2261 | 2083 |
| 2262 | 2084 |
| 2263 Handle<Code> CallStubCompiler::CompileMathFloorCall( | 2085 Handle<Code> CallStubCompiler::CompileMathFloorCall( |
| 2264 Handle<Object> object, | 2086 Handle<Object> object, |
| 2265 Handle<JSObject> holder, | 2087 Handle<JSObject> holder, |
| 2266 Handle<Cell> cell, | 2088 Handle<Cell> cell, |
| 2267 Handle<JSFunction> function, | 2089 Handle<JSFunction> function, |
| 2268 Handle<String> name, | 2090 Handle<String> name, |
| 2269 Code::StubType type) { | 2091 Code::StubType type) { |
| 2270 // ----------- S t a t e ------------- | |
| 2271 // -- a2 : function name | |
| 2272 // -- ra : return address | |
| 2273 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 2274 // -- ... | |
| 2275 // -- sp[argc * 4] : receiver | |
| 2276 // ----------------------------------- | |
| 2277 | |
| 2278 | |
| 2279 const int argc = arguments().immediate(); | 2092 const int argc = arguments().immediate(); |
| 2280 // If the object is not a JSObject or we got an unexpected number of | 2093 // If the object is not a JSObject or we got an unexpected number of |
| 2281 // arguments, bail out to the regular call. | 2094 // arguments, bail out to the regular call. |
| 2282 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2095 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2283 | 2096 |
| 2284 Label miss, slow; | 2097 Label miss, slow; |
| 2285 GenerateNameCheck(name, &miss); | 2098 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2286 | 2099 if (!cell.is_null()) { |
| 2287 if (cell.is_null()) { | |
| 2288 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | |
| 2289 STATIC_ASSERT(kSmiTag == 0); | |
| 2290 __ JumpIfSmi(a1, &miss); | |
| 2291 CheckPrototypes( | |
| 2292 IC::CurrentTypeOf(object, isolate()), | |
| 2293 a1, holder, a0, a3, t0, name, &miss); | |
| 2294 } else { | |
| 2295 ASSERT(cell->value() == *function); | 2100 ASSERT(cell->value() == *function); |
| 2296 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2297 &miss); | |
| 2298 GenerateLoadFunctionFromCell(cell, function, &miss); | 2101 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2299 } | 2102 } |
| 2300 | 2103 |
| 2301 // Load the (only) argument into v0. | 2104 // Load the (only) argument into v0. |
| 2302 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | 2105 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); |
| 2303 | 2106 |
| 2304 // If the argument is a smi, just return. | 2107 // If the argument is a smi, just return. |
| 2305 STATIC_ASSERT(kSmiTag == 0); | 2108 STATIC_ASSERT(kSmiTag == 0); |
| 2306 __ SmiTst(v0, t0); | 2109 __ SmiTst(v0, t0); |
| 2307 __ DropAndRet(argc + 1, eq, t0, Operand(zero_reg)); | 2110 __ DropAndRet(argc + 1, eq, t0, Operand(zero_reg)); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2369 // Restore FCSR and return. | 2172 // Restore FCSR and return. |
| 2370 __ ctc1(a3, FCSR); | 2173 __ ctc1(a3, FCSR); |
| 2371 | 2174 |
| 2372 __ DropAndRet(argc + 1); | 2175 __ DropAndRet(argc + 1); |
| 2373 | 2176 |
| 2374 __ bind(&wont_fit_smi); | 2177 __ bind(&wont_fit_smi); |
| 2375 // Restore FCSR and fall to slow case. | 2178 // Restore FCSR and fall to slow case. |
| 2376 __ ctc1(a3, FCSR); | 2179 __ ctc1(a3, FCSR); |
| 2377 | 2180 |
| 2378 __ bind(&slow); | 2181 __ bind(&slow); |
| 2379 // Tail call the full function. We do not have to patch the receiver | 2182 // We do not have to patch the receiver because the function makes no use of |
| 2380 // because the function makes no use of it. | 2183 // it. |
| 2381 ParameterCount expected(function); | 2184 GenerateJumpFunctionIgnoreReceiver(function); |
| 2382 __ InvokeFunction(function, expected, arguments(), | |
| 2383 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | |
| 2384 | 2185 |
| 2385 __ bind(&miss); | 2186 HandlerFrontendFooter(&miss); |
| 2386 // a2: function name. | |
| 2387 GenerateMissBranch(); | |
| 2388 | 2187 |
| 2389 // Return the generated code. | 2188 // Return the generated code. |
| 2390 return GetCode(type, name); | 2189 return GetCode(type, name); |
| 2391 } | 2190 } |
| 2392 | 2191 |
| 2393 | 2192 |
| 2394 Handle<Code> CallStubCompiler::CompileMathAbsCall( | 2193 Handle<Code> CallStubCompiler::CompileMathAbsCall( |
| 2395 Handle<Object> object, | 2194 Handle<Object> object, |
| 2396 Handle<JSObject> holder, | 2195 Handle<JSObject> holder, |
| 2397 Handle<Cell> cell, | 2196 Handle<Cell> cell, |
| 2398 Handle<JSFunction> function, | 2197 Handle<JSFunction> function, |
| 2399 Handle<String> name, | 2198 Handle<String> name, |
| 2400 Code::StubType type) { | 2199 Code::StubType type) { |
| 2401 // ----------- S t a t e ------------- | |
| 2402 // -- a2 : function name | |
| 2403 // -- ra : return address | |
| 2404 // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) | |
| 2405 // -- ... | |
| 2406 // -- sp[argc * 4] : receiver | |
| 2407 // ----------------------------------- | |
| 2408 | |
| 2409 const int argc = arguments().immediate(); | 2200 const int argc = arguments().immediate(); |
| 2410 // If the object is not a JSObject or we got an unexpected number of | 2201 // If the object is not a JSObject or we got an unexpected number of |
| 2411 // arguments, bail out to the regular call. | 2202 // arguments, bail out to the regular call. |
| 2412 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); | 2203 if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); |
| 2413 | 2204 |
| 2414 Label miss; | 2205 Label miss; |
| 2415 | 2206 |
| 2416 GenerateNameCheck(name, &miss); | 2207 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2417 if (cell.is_null()) { | 2208 if (!cell.is_null()) { |
| 2418 __ lw(a1, MemOperand(sp, 1 * kPointerSize)); | |
| 2419 STATIC_ASSERT(kSmiTag == 0); | |
| 2420 __ JumpIfSmi(a1, &miss); | |
| 2421 CheckPrototypes( | |
| 2422 IC::CurrentTypeOf(object, isolate()), | |
| 2423 a1, holder, v0, a3, t0, name, &miss); | |
| 2424 } else { | |
| 2425 ASSERT(cell->value() == *function); | 2209 ASSERT(cell->value() == *function); |
| 2426 GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, | |
| 2427 &miss); | |
| 2428 GenerateLoadFunctionFromCell(cell, function, &miss); | 2210 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2429 } | 2211 } |
| 2430 | 2212 |
| 2431 // Load the (only) argument into v0. | 2213 // Load the (only) argument into v0. |
| 2432 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); | 2214 __ lw(v0, MemOperand(sp, 0 * kPointerSize)); |
| 2433 | 2215 |
| 2434 // Check if the argument is a smi. | 2216 // Check if the argument is a smi. |
| 2435 Label not_smi; | 2217 Label not_smi; |
| 2436 STATIC_ASSERT(kSmiTag == 0); | 2218 STATIC_ASSERT(kSmiTag == 0); |
| 2437 __ JumpIfNotSmi(v0, ¬_smi); | 2219 __ JumpIfNotSmi(v0, ¬_smi); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2469 // number. | 2251 // number. |
| 2470 __ bind(&negative_sign); | 2252 __ bind(&negative_sign); |
| 2471 __ Xor(a1, a1, Operand(HeapNumber::kSignMask)); | 2253 __ Xor(a1, a1, Operand(HeapNumber::kSignMask)); |
| 2472 __ lw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | 2254 __ lw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
| 2473 __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex); | 2255 __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex); |
| 2474 __ AllocateHeapNumber(v0, t0, t1, t2, &slow); | 2256 __ AllocateHeapNumber(v0, t0, t1, t2, &slow); |
| 2475 __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); | 2257 __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); |
| 2476 __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); | 2258 __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
| 2477 __ DropAndRet(argc + 1); | 2259 __ DropAndRet(argc + 1); |
| 2478 | 2260 |
| 2479 // Tail call the full function. We do not have to patch the receiver | |
| 2480 // because the function makes no use of it. | |
| 2481 __ bind(&slow); | 2261 __ bind(&slow); |
| 2482 ParameterCount expected(function); | 2262 // We do not have to patch the receiver because the function makes no use of |
| 2483 __ InvokeFunction(function, expected, arguments(), | 2263 // it. |
| 2484 JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); | 2264 GenerateJumpFunctionIgnoreReceiver(function); |
| 2485 | 2265 |
| 2486 __ bind(&miss); | 2266 HandlerFrontendFooter(&miss); |
| 2487 // a2: function name. | |
| 2488 GenerateMissBranch(); | |
| 2489 | 2267 |
| 2490 // Return the generated code. | 2268 // Return the generated code. |
| 2491 return GetCode(type, name); | 2269 return GetCode(type, name); |
| 2492 } | 2270 } |
| 2493 | 2271 |
| 2494 | 2272 |
| 2495 Handle<Code> CallStubCompiler::CompileFastApiCall( | 2273 Handle<Code> CallStubCompiler::CompileFastApiCall( |
| 2496 const CallOptimization& optimization, | 2274 const CallOptimization& optimization, |
| 2497 Handle<Object> object, | 2275 Handle<Object> object, |
| 2498 Handle<JSObject> holder, | 2276 Handle<JSObject> holder, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2531 // Check that the maps haven't changed and find a Holder as a side effect. | 2309 // Check that the maps haven't changed and find a Holder as a side effect. |
| 2532 CheckPrototypes( | 2310 CheckPrototypes( |
| 2533 IC::CurrentTypeOf(object, isolate()), | 2311 IC::CurrentTypeOf(object, isolate()), |
| 2534 a1, holder, a0, a3, t0, name, depth, &miss); | 2312 a1, holder, a0, a3, t0, name, depth, &miss); |
| 2535 | 2313 |
| 2536 GenerateFastApiDirectCall(masm(), optimization, argc, false); | 2314 GenerateFastApiDirectCall(masm(), optimization, argc, false); |
| 2537 | 2315 |
| 2538 __ bind(&miss); | 2316 __ bind(&miss); |
| 2539 FreeSpaceForFastApiCall(masm()); | 2317 FreeSpaceForFastApiCall(masm()); |
| 2540 | 2318 |
| 2541 __ bind(&miss_before_stack_reserved); | 2319 HandlerFrontendFooter(&miss_before_stack_reserved); |
| 2542 GenerateMissBranch(); | |
| 2543 | 2320 |
| 2544 // Return the generated code. | 2321 // Return the generated code. |
| 2545 return GetCode(function); | 2322 return GetCode(function); |
| 2546 } | 2323 } |
| 2547 | 2324 |
| 2548 | 2325 |
| 2549 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { | 2326 void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { |
| 2550 Label success; | 2327 Label success; |
| 2551 // Check that the object is a boolean. | 2328 // Check that the object is a boolean. |
| 2552 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 2329 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
| 2553 __ Branch(&success, eq, object, Operand(at)); | 2330 __ Branch(&success, eq, object, Operand(at)); |
| 2554 __ LoadRoot(at, Heap::kFalseValueRootIndex); | 2331 __ LoadRoot(at, Heap::kFalseValueRootIndex); |
| 2555 __ Branch(miss, ne, object, Operand(at)); | 2332 __ Branch(miss, ne, object, Operand(at)); |
| 2556 __ bind(&success); | 2333 __ bind(&success); |
| 2557 } | 2334 } |
| 2558 | 2335 |
| 2559 | 2336 |
| 2560 void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, | 2337 void CallStubCompiler::PatchGlobalProxy(Handle<Object> object) { |
| 2561 Handle<JSObject> holder, | 2338 if (!object.is_null() && object->IsGlobalObject()) { |
| 2562 Handle<Name> name, | 2339 const int argc = arguments().immediate(); |
| 2563 CheckType check) { | 2340 const int receiver_offset = argc * kPointerSize; |
| 2341 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); |
| 2342 __ sw(a3, MemOperand(sp, receiver_offset)); |
| 2343 } |
| 2344 } |
| 2345 |
| 2346 |
| 2347 Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object, |
| 2348 Handle<JSObject> holder, |
| 2349 Handle<Name> name, |
| 2350 CheckType check, |
| 2351 Label* miss) { |
| 2564 // ----------- S t a t e ------------- | 2352 // ----------- S t a t e ------------- |
| 2565 // -- a2 : name | 2353 // -- a2 : name |
| 2566 // -- ra : return address | 2354 // -- ra : return address |
| 2567 // ----------------------------------- | 2355 // ----------------------------------- |
| 2568 Label miss; | 2356 GenerateNameCheck(name, miss); |
| 2569 GenerateNameCheck(name, &miss); | 2357 |
| 2358 Register reg = a0; |
| 2570 | 2359 |
| 2571 // Get the receiver from the stack. | 2360 // Get the receiver from the stack. |
| 2572 const int argc = arguments().immediate(); | 2361 const int argc = arguments().immediate(); |
| 2573 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2362 const int receiver_offset = argc * kPointerSize; |
| 2363 __ lw(a0, MemOperand(sp, receiver_offset)); |
| 2574 | 2364 |
| 2575 // Check that the receiver isn't a smi. | 2365 // Check that the receiver isn't a smi. |
| 2576 if (check != NUMBER_CHECK) { | 2366 if (check != NUMBER_CHECK) { |
| 2577 __ JumpIfSmi(a1, &miss); | 2367 __ JumpIfSmi(a0, miss); |
| 2578 } | 2368 } |
| 2579 | 2369 |
| 2580 // Make sure that it's okay not to patch the on stack receiver | 2370 // Make sure that it's okay not to patch the on stack receiver |
| 2581 // unless we're doing a receiver map check. | 2371 // unless we're doing a receiver map check. |
| 2582 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); | 2372 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); |
| 2583 switch (check) { | 2373 switch (check) { |
| 2584 case RECEIVER_MAP_CHECK: | 2374 case RECEIVER_MAP_CHECK: |
| 2585 __ IncrementCounter(isolate()->counters()->call_const(), 1, a0, a3); | 2375 __ IncrementCounter(isolate()->counters()->call_const(), 1, a1, a3); |
| 2586 | 2376 |
| 2587 // Check that the maps haven't changed. | 2377 // Check that the maps haven't changed. |
| 2588 CheckPrototypes( | 2378 reg = CheckPrototypes( |
| 2589 IC::CurrentTypeOf(object, isolate()), | 2379 IC::CurrentTypeOf(object, isolate()), |
| 2590 a1, holder, a0, a3, t0, name, &miss); | 2380 reg, holder, a1, a3, t0, name, miss); |
| 2591 | |
| 2592 // Patch the receiver on the stack with the global proxy if | |
| 2593 // necessary. | |
| 2594 if (object->IsGlobalObject()) { | |
| 2595 __ lw(a3, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); | |
| 2596 __ sw(a3, MemOperand(sp, argc * kPointerSize)); | |
| 2597 } | |
| 2598 break; | 2381 break; |
| 2599 | 2382 |
| 2600 case STRING_CHECK: { | 2383 case STRING_CHECK: { |
| 2601 // Check that the object is a string. | 2384 // Check that the object is a string. |
| 2602 __ GetObjectType(a1, a3, a3); | 2385 __ GetObjectType(reg, a3, a3); |
| 2603 __ Branch(&miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE)); | 2386 __ Branch(miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE)); |
| 2604 // Check that the maps starting from the prototype haven't changed. | 2387 // Check that the maps starting from the prototype haven't changed. |
| 2605 GenerateDirectLoadGlobalFunctionPrototype( | 2388 GenerateDirectLoadGlobalFunctionPrototype( |
| 2606 masm(), Context::STRING_FUNCTION_INDEX, a0, &miss); | 2389 masm(), Context::STRING_FUNCTION_INDEX, a1, miss); |
| 2607 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2608 CheckPrototypes( | |
| 2609 IC::CurrentTypeOf(prototype, isolate()), | |
| 2610 a0, holder, a3, a1, t0, name, &miss); | |
| 2611 break; | 2390 break; |
| 2612 } | 2391 } |
| 2613 case SYMBOL_CHECK: { | 2392 case SYMBOL_CHECK: { |
| 2614 // Check that the object is a symbol. | 2393 // Check that the object is a symbol. |
| 2615 __ GetObjectType(a1, a1, a3); | 2394 __ GetObjectType(reg, a1, a3); |
| 2616 __ Branch(&miss, ne, a3, Operand(SYMBOL_TYPE)); | 2395 __ Branch(miss, ne, a3, Operand(SYMBOL_TYPE)); |
| 2617 // Check that the maps starting from the prototype haven't changed. | 2396 // Check that the maps starting from the prototype haven't changed. |
| 2618 GenerateDirectLoadGlobalFunctionPrototype( | 2397 GenerateDirectLoadGlobalFunctionPrototype( |
| 2619 masm(), Context::SYMBOL_FUNCTION_INDEX, a0, &miss); | 2398 masm(), Context::SYMBOL_FUNCTION_INDEX, a1, miss); |
| 2620 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2621 CheckPrototypes( | |
| 2622 IC::CurrentTypeOf(prototype, isolate()), | |
| 2623 a0, holder, a3, a1, t0, name, &miss); | |
| 2624 break; | 2399 break; |
| 2625 } | 2400 } |
| 2626 case NUMBER_CHECK: { | 2401 case NUMBER_CHECK: { |
| 2627 Label fast; | 2402 Label fast; |
| 2628 // Check that the object is a smi or a heap number. | 2403 // Check that the object is a smi or a heap number. |
| 2629 __ JumpIfSmi(a1, &fast); | 2404 __ JumpIfSmi(reg, &fast); |
| 2630 __ GetObjectType(a1, a0, a0); | 2405 __ GetObjectType(reg, a3, a3); |
| 2631 __ Branch(&miss, ne, a0, Operand(HEAP_NUMBER_TYPE)); | 2406 __ Branch(miss, ne, a3, Operand(HEAP_NUMBER_TYPE)); |
| 2632 __ bind(&fast); | 2407 __ bind(&fast); |
| 2633 // Check that the maps starting from the prototype haven't changed. | 2408 // Check that the maps starting from the prototype haven't changed. |
| 2634 GenerateDirectLoadGlobalFunctionPrototype( | 2409 GenerateDirectLoadGlobalFunctionPrototype( |
| 2635 masm(), Context::NUMBER_FUNCTION_INDEX, a0, &miss); | 2410 masm(), Context::NUMBER_FUNCTION_INDEX, a1, miss); |
| 2636 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2637 CheckPrototypes( | |
| 2638 IC::CurrentTypeOf(prototype, isolate()), | |
| 2639 a0, holder, a3, a1, t0, name, &miss); | |
| 2640 break; | 2411 break; |
| 2641 } | 2412 } |
| 2642 case BOOLEAN_CHECK: { | 2413 case BOOLEAN_CHECK: { |
| 2643 GenerateBooleanCheck(a1, &miss); | 2414 GenerateBooleanCheck(reg, miss); |
| 2644 | 2415 |
| 2645 // Check that the maps starting from the prototype haven't changed. | 2416 // Check that the maps starting from the prototype haven't changed. |
| 2646 GenerateDirectLoadGlobalFunctionPrototype( | 2417 GenerateDirectLoadGlobalFunctionPrototype( |
| 2647 masm(), Context::BOOLEAN_FUNCTION_INDEX, a0, &miss); | 2418 masm(), Context::BOOLEAN_FUNCTION_INDEX, a1, miss); |
| 2648 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); | |
| 2649 CheckPrototypes( | |
| 2650 IC::CurrentTypeOf(prototype, isolate()), | |
| 2651 a0, holder, a3, a1, t0, name, &miss); | |
| 2652 break; | 2419 break; |
| 2653 } | 2420 } |
| 2654 } | 2421 } |
| 2655 | 2422 |
| 2656 Label success; | 2423 if (check != RECEIVER_MAP_CHECK) { |
| 2657 __ Branch(&success); | 2424 Handle<Object> prototype(object->GetPrototype(isolate()), isolate()); |
| 2425 reg = CheckPrototypes( |
| 2426 IC::CurrentTypeOf(prototype, isolate()), |
| 2427 a1, holder, a1, a3, t0, name, miss); |
| 2428 } |
| 2658 | 2429 |
| 2659 // Handle call cache miss. | 2430 return reg; |
| 2660 __ bind(&miss); | |
| 2661 | |
| 2662 GenerateMissBranch(); | |
| 2663 | |
| 2664 __ bind(&success); | |
| 2665 } | 2431 } |
| 2666 | 2432 |
| 2667 | 2433 |
| 2668 void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) { | 2434 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, |
| 2669 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2435 Register function, |
| 2670 ? CALL_AS_FUNCTION | 2436 Label* miss) { |
| 2671 : CALL_AS_METHOD; | 2437 ASSERT(function.is(a1)); |
| 2672 ParameterCount expected(function); | 2438 // Check that the function really is a function. |
| 2673 __ InvokeFunction(function, expected, arguments(), | 2439 GenerateFunctionCheck(function, a3, miss); |
| 2674 JUMP_FUNCTION, NullCallWrapper(), call_kind); | 2440 if (!function.is(a1)) __ mov(a1, function); |
| 2675 } | 2441 PatchGlobalProxy(object); |
| 2676 | 2442 // Invoke the function. |
| 2677 | 2443 __ InvokeFunction(a1, arguments(), JUMP_FUNCTION, |
| 2678 Handle<Code> CallStubCompiler::CompileCallConstant( | 2444 NullCallWrapper(), call_kind()); |
| 2679 Handle<Object> object, | |
| 2680 Handle<JSObject> holder, | |
| 2681 Handle<Name> name, | |
| 2682 CheckType check, | |
| 2683 Handle<JSFunction> function) { | |
| 2684 if (HasCustomCallGenerator(function)) { | |
| 2685 Handle<Code> code = CompileCustomCall(object, holder, | |
| 2686 Handle<Cell>::null(), | |
| 2687 function, Handle<String>::cast(name), | |
| 2688 Code::FAST); | |
| 2689 // A null handle means bail out to the regular compiler code below. | |
| 2690 if (!code.is_null()) return code; | |
| 2691 } | |
| 2692 | |
| 2693 CompileHandlerFrontend(object, holder, name, check); | |
| 2694 CompileHandlerBackend(function); | |
| 2695 | |
| 2696 // Return the generated code. | |
| 2697 return GetCode(function); | |
| 2698 } | 2445 } |
| 2699 | 2446 |
| 2700 | 2447 |
| 2701 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, | 2448 Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, |
| 2702 Handle<JSObject> holder, | 2449 Handle<JSObject> holder, |
| 2703 Handle<Name> name) { | 2450 Handle<Name> name) { |
| 2704 // ----------- S t a t e ------------- | |
| 2705 // -- a2 : name | |
| 2706 // -- ra : return address | |
| 2707 // ----------------------------------- | |
| 2708 | |
| 2709 Label miss; | 2451 Label miss; |
| 2710 | 2452 |
| 2711 GenerateNameCheck(name, &miss); | 2453 GenerateNameCheck(name, &miss); |
| 2712 | 2454 |
| 2713 // Get the number of arguments. | 2455 // Get the number of arguments. |
| 2714 const int argc = arguments().immediate(); | 2456 const int argc = arguments().immediate(); |
| 2715 LookupResult lookup(isolate()); | 2457 LookupResult lookup(isolate()); |
| 2716 LookupPostInterceptor(holder, name, &lookup); | 2458 LookupPostInterceptor(holder, name, &lookup); |
| 2717 | 2459 |
| 2718 // Get the receiver from the stack. | 2460 // Get the receiver from the stack. |
| 2719 __ lw(a1, MemOperand(sp, argc * kPointerSize)); | 2461 __ lw(a1, MemOperand(sp, argc * kPointerSize)); |
| 2720 | 2462 |
| 2721 CallInterceptorCompiler compiler(this, arguments(), a2, extra_state_); | 2463 CallInterceptorCompiler compiler(this, arguments(), a2, extra_state_); |
| 2722 compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0, | 2464 compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0, |
| 2723 &miss); | 2465 &miss); |
| 2724 | 2466 |
| 2725 // Move returned value, the function to call, to a1. | 2467 // Move returned value, the function to call, to a1. |
| 2726 __ mov(a1, v0); | 2468 __ mov(a1, v0); |
| 2727 // Restore receiver. | 2469 // Restore receiver. |
| 2728 __ lw(a0, MemOperand(sp, argc * kPointerSize)); | 2470 __ lw(a0, MemOperand(sp, argc * kPointerSize)); |
| 2729 | 2471 |
| 2730 GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); | 2472 GenerateJumpFunction(object, a1, &miss); |
| 2731 | 2473 |
| 2732 // Handle call cache miss. | 2474 HandlerFrontendFooter(&miss); |
| 2733 __ bind(&miss); | |
| 2734 GenerateMissBranch(); | |
| 2735 | 2475 |
| 2736 // Return the generated code. | 2476 // Return the generated code. |
| 2737 return GetCode(Code::FAST, name); | 2477 return GetCode(Code::FAST, name); |
| 2738 } | 2478 } |
| 2739 | 2479 |
| 2740 | 2480 |
| 2741 Handle<Code> CallStubCompiler::CompileCallGlobal( | 2481 Handle<Code> CallStubCompiler::CompileCallGlobal( |
| 2742 Handle<JSObject> object, | 2482 Handle<JSObject> object, |
| 2743 Handle<GlobalObject> holder, | 2483 Handle<GlobalObject> holder, |
| 2744 Handle<PropertyCell> cell, | 2484 Handle<PropertyCell> cell, |
| 2745 Handle<JSFunction> function, | 2485 Handle<JSFunction> function, |
| 2746 Handle<Name> name) { | 2486 Handle<Name> name) { |
| 2747 // ----------- S t a t e ------------- | |
| 2748 // -- a2 : name | |
| 2749 // -- ra : return address | |
| 2750 // ----------------------------------- | |
| 2751 | |
| 2752 if (HasCustomCallGenerator(function)) { | 2487 if (HasCustomCallGenerator(function)) { |
| 2753 Handle<Code> code = CompileCustomCall( | 2488 Handle<Code> code = CompileCustomCall( |
| 2754 object, holder, cell, function, Handle<String>::cast(name), | 2489 object, holder, cell, function, Handle<String>::cast(name), |
| 2755 Code::NORMAL); | 2490 Code::NORMAL); |
| 2756 // A null handle means bail out to the regular compiler code below. | 2491 // A null handle means bail out to the regular compiler code below. |
| 2757 if (!code.is_null()) return code; | 2492 if (!code.is_null()) return code; |
| 2758 } | 2493 } |
| 2759 | 2494 |
| 2760 Label miss; | 2495 Label miss; |
| 2761 GenerateNameCheck(name, &miss); | 2496 HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); |
| 2762 | 2497 // Potentially loads a closure that matches the shared function info of the |
| 2763 // Get the number of arguments. | 2498 // function, rather than function. |
| 2764 const int argc = arguments().immediate(); | |
| 2765 GenerateGlobalReceiverCheck(object, holder, name, &miss); | |
| 2766 GenerateLoadFunctionFromCell(cell, function, &miss); | 2499 GenerateLoadFunctionFromCell(cell, function, &miss); |
| 2767 | |
| 2768 // Patch the receiver on the stack with the global proxy if | |
| 2769 // necessary. | |
| 2770 if (object->IsGlobalObject()) { | |
| 2771 __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); | |
| 2772 __ sw(a3, MemOperand(sp, argc * kPointerSize)); | |
| 2773 } | |
| 2774 | |
| 2775 // Set up the context (function already in r1). | |
| 2776 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | |
| 2777 | |
| 2778 // Jump to the cached code (tail call). | |
| 2779 Counters* counters = isolate()->counters(); | 2500 Counters* counters = isolate()->counters(); |
| 2780 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); | 2501 __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); |
| 2781 ParameterCount expected(function->shared()->formal_parameter_count()); | 2502 GenerateJumpFunction(object, a1, function); |
| 2782 CallKind call_kind = CallICBase::Contextual::decode(extra_state_) | 2503 HandlerFrontendFooter(&miss); |
| 2783 ? CALL_AS_FUNCTION | |
| 2784 : CALL_AS_METHOD; | |
| 2785 // We call indirectly through the code field in the function to | |
| 2786 // allow recompilation to take effect without changing any of the | |
| 2787 // call sites. | |
| 2788 __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | |
| 2789 __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION, | |
| 2790 NullCallWrapper(), call_kind); | |
| 2791 | |
| 2792 // Handle call cache miss. | |
| 2793 __ bind(&miss); | |
| 2794 __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); | |
| 2795 GenerateMissBranch(); | |
| 2796 | 2504 |
| 2797 // Return the generated code. | 2505 // Return the generated code. |
| 2798 return GetCode(Code::NORMAL, name); | 2506 return GetCode(Code::NORMAL, name); |
| 2799 } | 2507 } |
| 2800 | 2508 |
| 2801 | 2509 |
| 2802 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 2510 Handle<Code> StoreStubCompiler::CompileStoreCallback( |
| 2803 Handle<JSObject> object, | 2511 Handle<JSObject> object, |
| 2804 Handle<JSObject> holder, | 2512 Handle<JSObject> holder, |
| 2805 Handle<Name> name, | 2513 Handle<Name> name, |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2904 if (object->IsJSGlobalProxy()) { | 2612 if (object->IsJSGlobalProxy()) { |
| 2905 __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss); | 2613 __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss); |
| 2906 } | 2614 } |
| 2907 | 2615 |
| 2908 // Stub is never generated for non-global objects that require access | 2616 // Stub is never generated for non-global objects that require access |
| 2909 // checks. | 2617 // checks. |
| 2910 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 2618 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
| 2911 | 2619 |
| 2912 __ Push(receiver(), this->name(), value()); | 2620 __ Push(receiver(), this->name(), value()); |
| 2913 | 2621 |
| 2914 __ li(scratch1(), Operand(Smi::FromInt(strict_mode()))); | |
| 2915 __ push(scratch1()); // strict mode | |
| 2916 | |
| 2917 // Do tail-call to the runtime system. | 2622 // Do tail-call to the runtime system. |
| 2918 ExternalReference store_ic_property = | 2623 ExternalReference store_ic_property = |
| 2919 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 2624 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
| 2920 __ TailCallExternalReference(store_ic_property, 4, 1); | 2625 __ TailCallExternalReference(store_ic_property, 3, 1); |
| 2921 | 2626 |
| 2922 // Handle store cache miss. | 2627 // Handle store cache miss. |
| 2923 __ bind(&miss); | 2628 __ bind(&miss); |
| 2924 TailCallBuiltin(masm(), MissBuiltin(kind())); | 2629 TailCallBuiltin(masm(), MissBuiltin(kind())); |
| 2925 | 2630 |
| 2926 // Return the generated code. | 2631 // Return the generated code. |
| 2927 return GetCode(kind(), Code::FAST, name); | 2632 return GetCode(kind(), Code::FAST, name); |
| 2928 } | 2633 } |
| 2929 | 2634 |
| 2930 | 2635 |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3177 // ----------------------------------- | 2882 // ----------------------------------- |
| 3178 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 2883 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
| 3179 } | 2884 } |
| 3180 | 2885 |
| 3181 | 2886 |
| 3182 #undef __ | 2887 #undef __ |
| 3183 | 2888 |
| 3184 } } // namespace v8::internal | 2889 } } // namespace v8::internal |
| 3185 | 2890 |
| 3186 #endif // V8_TARGET_ARCH_MIPS | 2891 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |