| 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 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 info->set_prologue_offset(masm_->pc_offset()); | 173 info->set_prologue_offset(masm_->pc_offset()); |
| 174 __ Prologue(BUILD_FUNCTION_FRAME); | 174 __ Prologue(BUILD_FUNCTION_FRAME); |
| 175 info->AddNoFrameRange(0, masm_->pc_offset()); | 175 info->AddNoFrameRange(0, masm_->pc_offset()); |
| 176 | 176 |
| 177 { Comment cmnt(masm_, "[ Allocate locals"); | 177 { Comment cmnt(masm_, "[ Allocate locals"); |
| 178 int locals_count = info->scope()->num_stack_slots(); | 178 int locals_count = info->scope()->num_stack_slots(); |
| 179 // Generators allocate locals, if any, in context slots. | 179 // Generators allocate locals, if any, in context slots. |
| 180 ASSERT(!info->function()->is_generator() || locals_count == 0); | 180 ASSERT(!info->function()->is_generator() || locals_count == 0); |
| 181 if (locals_count > 0) { | 181 if (locals_count > 0) { |
| 182 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 182 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 183 for (int i = 0; i < locals_count; i++) { | 183 // Emit a loop to initialize stack cells for locals when optimizing for |
| 184 __ push(at); | 184 // size. Otherwise, unroll the loop for maximum performance. |
| 185 __ LoadRoot(t5, Heap::kUndefinedValueRootIndex); |
| 186 if (FLAG_optimize_for_size && locals_count > 4) { |
| 187 Label loop; |
| 188 __ li(a2, Operand(locals_count)); |
| 189 __ bind(&loop); |
| 190 __ Subu(a2, a2, 1); |
| 191 __ push(t5); |
| 192 __ Branch(&loop, gt, a2, Operand(zero_reg)); |
| 193 } else { |
| 194 for (int i = 0; i < locals_count; i++) { |
| 195 __ push(t5); |
| 196 } |
| 185 } | 197 } |
| 186 } | 198 } |
| 187 } | 199 } |
| 188 | 200 |
| 189 bool function_in_register = true; | 201 bool function_in_register = true; |
| 190 | 202 |
| 191 // Possibly allocate a local context. | 203 // Possibly allocate a local context. |
| 192 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 204 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 193 if (heap_slots > 0) { | 205 if (heap_slots > 0) { |
| 194 Comment cmnt(masm_, "[ Allocate context"); | 206 Comment cmnt(masm_, "[ Allocate context"); |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 __ bind(&done); | 624 __ bind(&done); |
| 613 } | 625 } |
| 614 | 626 |
| 615 | 627 |
| 616 void FullCodeGenerator::StackValueContext::Plug( | 628 void FullCodeGenerator::StackValueContext::Plug( |
| 617 Label* materialize_true, | 629 Label* materialize_true, |
| 618 Label* materialize_false) const { | 630 Label* materialize_false) const { |
| 619 Label done; | 631 Label done; |
| 620 __ bind(materialize_true); | 632 __ bind(materialize_true); |
| 621 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 633 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
| 622 __ push(at); | |
| 623 __ Branch(&done); | 634 __ Branch(&done); |
| 624 __ bind(materialize_false); | 635 __ bind(materialize_false); |
| 625 __ LoadRoot(at, Heap::kFalseValueRootIndex); | 636 __ LoadRoot(at, Heap::kFalseValueRootIndex); |
| 637 __ bind(&done); |
| 626 __ push(at); | 638 __ push(at); |
| 627 __ bind(&done); | |
| 628 } | 639 } |
| 629 | 640 |
| 630 | 641 |
| 631 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 642 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
| 632 Label* materialize_false) const { | 643 Label* materialize_false) const { |
| 633 ASSERT(materialize_true == true_label_); | 644 ASSERT(materialize_true == true_label_); |
| 634 ASSERT(materialize_false == false_label_); | 645 ASSERT(materialize_false == false_label_); |
| 635 } | 646 } |
| 636 | 647 |
| 637 | 648 |
| (...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 __ jmp(&exit); | 1166 __ jmp(&exit); |
| 1156 | 1167 |
| 1157 // We got a fixed array in register v0. Iterate through that. | 1168 // We got a fixed array in register v0. Iterate through that. |
| 1158 Label non_proxy; | 1169 Label non_proxy; |
| 1159 __ bind(&fixed_array); | 1170 __ bind(&fixed_array); |
| 1160 | 1171 |
| 1161 Handle<Cell> cell = isolate()->factory()->NewCell( | 1172 Handle<Cell> cell = isolate()->factory()->NewCell( |
| 1162 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker), | 1173 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker), |
| 1163 isolate())); | 1174 isolate())); |
| 1164 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell); | 1175 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell); |
| 1165 __ LoadHeapObject(a1, cell); | 1176 __ li(a1, cell); |
| 1166 __ li(a2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); | 1177 __ li(a2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); |
| 1167 __ sw(a2, FieldMemOperand(a1, Cell::kValueOffset)); | 1178 __ sw(a2, FieldMemOperand(a1, Cell::kValueOffset)); |
| 1168 | 1179 |
| 1169 __ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check | 1180 __ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check |
| 1170 __ lw(a2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object | 1181 __ lw(a2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object |
| 1171 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 1182 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
| 1172 __ GetObjectType(a2, a3, a3); | 1183 __ GetObjectType(a2, a3, a3); |
| 1173 __ Branch(&non_proxy, gt, a3, Operand(LAST_JS_PROXY_TYPE)); | 1184 __ Branch(&non_proxy, gt, a3, Operand(LAST_JS_PROXY_TYPE)); |
| 1174 __ li(a1, Operand(Smi::FromInt(0))); // Zero indicates proxy | 1185 __ li(a1, Operand(Smi::FromInt(0))); // Zero indicates proxy |
| 1175 __ bind(&non_proxy); | 1186 __ bind(&non_proxy); |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1598 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 1609 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 1599 __ mov(t1, v0); | 1610 __ mov(t1, v0); |
| 1600 | 1611 |
| 1601 __ bind(&materialized); | 1612 __ bind(&materialized); |
| 1602 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 1613 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
| 1603 Label allocated, runtime_allocate; | 1614 Label allocated, runtime_allocate; |
| 1604 __ Allocate(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT); | 1615 __ Allocate(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT); |
| 1605 __ jmp(&allocated); | 1616 __ jmp(&allocated); |
| 1606 | 1617 |
| 1607 __ bind(&runtime_allocate); | 1618 __ bind(&runtime_allocate); |
| 1608 __ push(t1); | |
| 1609 __ li(a0, Operand(Smi::FromInt(size))); | 1619 __ li(a0, Operand(Smi::FromInt(size))); |
| 1610 __ push(a0); | 1620 __ Push(t1, a0); |
| 1611 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 1621 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 1612 __ pop(t1); | 1622 __ pop(t1); |
| 1613 | 1623 |
| 1614 __ bind(&allocated); | 1624 __ bind(&allocated); |
| 1615 | 1625 |
| 1616 // After this, registers are used as follows: | 1626 // After this, registers are used as follows: |
| 1617 // v0: Newly allocated regexp. | 1627 // v0: Newly allocated regexp. |
| 1618 // t1: Materialized regexp. | 1628 // t1: Materialized regexp. |
| 1619 // a2: temp. | 1629 // a2: temp. |
| 1620 __ CopyFields(v0, t1, a2.bit(), size / kPointerSize); | 1630 __ CopyFields(v0, t1, a2.bit(), size / kPointerSize); |
| 1621 context()->Plug(v0); | 1631 context()->Plug(v0); |
| 1622 } | 1632 } |
| 1623 | 1633 |
| 1624 | 1634 |
| 1625 void FullCodeGenerator::EmitAccessor(Expression* expression) { | 1635 void FullCodeGenerator::EmitAccessor(Expression* expression) { |
| 1626 if (expression == NULL) { | 1636 if (expression == NULL) { |
| 1627 __ LoadRoot(a1, Heap::kNullValueRootIndex); | 1637 __ LoadRoot(a1, Heap::kNullValueRootIndex); |
| 1628 __ push(a1); | 1638 __ push(a1); |
| 1629 } else { | 1639 } else { |
| 1630 VisitForStackValue(expression); | 1640 VisitForStackValue(expression); |
| 1631 } | 1641 } |
| 1632 } | 1642 } |
| 1633 | 1643 |
| 1634 | 1644 |
| 1635 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 1645 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 1636 Comment cmnt(masm_, "[ ObjectLiteral"); | 1646 Comment cmnt(masm_, "[ ObjectLiteral"); |
| 1647 |
| 1648 int depth = 1; |
| 1649 expr->BuildConstantProperties(isolate(), &depth); |
| 1637 Handle<FixedArray> constant_properties = expr->constant_properties(); | 1650 Handle<FixedArray> constant_properties = expr->constant_properties(); |
| 1638 __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1651 __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1639 __ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset)); | 1652 __ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset)); |
| 1640 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); | 1653 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); |
| 1641 __ li(a1, Operand(constant_properties)); | 1654 __ li(a1, Operand(constant_properties)); |
| 1642 int flags = expr->fast_elements() | 1655 int flags = expr->fast_elements() |
| 1643 ? ObjectLiteral::kFastElements | 1656 ? ObjectLiteral::kFastElements |
| 1644 : ObjectLiteral::kNoFlags; | 1657 : ObjectLiteral::kNoFlags; |
| 1645 flags |= expr->has_function() | 1658 flags |= expr->has_function() |
| 1646 ? ObjectLiteral::kHasFunction | 1659 ? ObjectLiteral::kHasFunction |
| 1647 : ObjectLiteral::kNoFlags; | 1660 : ObjectLiteral::kNoFlags; |
| 1648 __ li(a0, Operand(Smi::FromInt(flags))); | 1661 __ li(a0, Operand(Smi::FromInt(flags))); |
| 1649 int properties_count = constant_properties->length() / 2; | 1662 int properties_count = constant_properties->length() / 2; |
| 1650 if ((FLAG_track_double_fields && expr->may_store_doubles()) || | 1663 if ((FLAG_track_double_fields && expr->may_store_doubles()) || |
| 1651 expr->depth() > 1 || Serializer::enabled() || | 1664 depth > 1 || Serializer::enabled() || |
| 1652 flags != ObjectLiteral::kFastElements || | 1665 flags != ObjectLiteral::kFastElements || |
| 1653 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { | 1666 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { |
| 1654 __ Push(a3, a2, a1, a0); | 1667 __ Push(a3, a2, a1, a0); |
| 1655 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); | 1668 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); |
| 1656 } else { | 1669 } else { |
| 1657 FastCloneShallowObjectStub stub(properties_count); | 1670 FastCloneShallowObjectStub stub(properties_count); |
| 1658 __ CallStub(&stub); | 1671 __ CallStub(&stub); |
| 1659 } | 1672 } |
| 1660 | 1673 |
| 1661 // If result_saved is true the result is on top of the stack. If | 1674 // If result_saved is true the result is on top of the stack. If |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1760 context()->PlugTOS(); | 1773 context()->PlugTOS(); |
| 1761 } else { | 1774 } else { |
| 1762 context()->Plug(v0); | 1775 context()->Plug(v0); |
| 1763 } | 1776 } |
| 1764 } | 1777 } |
| 1765 | 1778 |
| 1766 | 1779 |
| 1767 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1780 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 1768 Comment cmnt(masm_, "[ ArrayLiteral"); | 1781 Comment cmnt(masm_, "[ ArrayLiteral"); |
| 1769 | 1782 |
| 1783 int depth = 1; |
| 1784 expr->BuildConstantElements(isolate(), &depth); |
| 1770 ZoneList<Expression*>* subexprs = expr->values(); | 1785 ZoneList<Expression*>* subexprs = expr->values(); |
| 1771 int length = subexprs->length(); | 1786 int length = subexprs->length(); |
| 1772 | 1787 |
| 1773 Handle<FixedArray> constant_elements = expr->constant_elements(); | 1788 Handle<FixedArray> constant_elements = expr->constant_elements(); |
| 1774 ASSERT_EQ(2, constant_elements->length()); | 1789 ASSERT_EQ(2, constant_elements->length()); |
| 1775 ElementsKind constant_elements_kind = | 1790 ElementsKind constant_elements_kind = |
| 1776 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); | 1791 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); |
| 1777 bool has_fast_elements = | 1792 bool has_fast_elements = |
| 1778 IsFastObjectElementsKind(constant_elements_kind); | 1793 IsFastObjectElementsKind(constant_elements_kind); |
| 1779 Handle<FixedArrayBase> constant_elements_values( | 1794 Handle<FixedArrayBase> constant_elements_values( |
| 1780 FixedArrayBase::cast(constant_elements->get(1))); | 1795 FixedArrayBase::cast(constant_elements->get(1))); |
| 1781 | 1796 |
| 1782 __ mov(a0, result_register()); | 1797 __ mov(a0, result_register()); |
| 1783 __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1798 __ lw(a3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1784 __ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset)); | 1799 __ lw(a3, FieldMemOperand(a3, JSFunction::kLiteralsOffset)); |
| 1785 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); | 1800 __ li(a2, Operand(Smi::FromInt(expr->literal_index()))); |
| 1786 __ li(a1, Operand(constant_elements)); | 1801 __ li(a1, Operand(constant_elements)); |
| 1787 if (has_fast_elements && constant_elements_values->map() == | 1802 if (has_fast_elements && constant_elements_values->map() == |
| 1788 isolate()->heap()->fixed_cow_array_map()) { | 1803 isolate()->heap()->fixed_cow_array_map()) { |
| 1789 FastCloneShallowArrayStub stub( | 1804 FastCloneShallowArrayStub stub( |
| 1790 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, | 1805 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, |
| 1791 DONT_TRACK_ALLOCATION_SITE, | 1806 DONT_TRACK_ALLOCATION_SITE, |
| 1792 length); | 1807 length); |
| 1793 __ CallStub(&stub); | 1808 __ CallStub(&stub); |
| 1794 __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), | 1809 __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), |
| 1795 1, a1, a2); | 1810 1, a1, a2); |
| 1796 } else if (expr->depth() > 1) { | 1811 } else if (depth > 1 || Serializer::enabled() || |
| 1812 length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
| 1797 __ Push(a3, a2, a1); | 1813 __ Push(a3, a2, a1); |
| 1798 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 1814 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); |
| 1799 } else if (Serializer::enabled() || | |
| 1800 length > FastCloneShallowArrayStub::kMaximumClonedLength) { | |
| 1801 __ Push(a3, a2, a1); | |
| 1802 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | |
| 1803 } else { | 1815 } else { |
| 1804 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || | 1816 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || |
| 1805 FLAG_smi_only_arrays); | 1817 FLAG_smi_only_arrays); |
| 1806 FastCloneShallowArrayStub::Mode mode = | 1818 FastCloneShallowArrayStub::Mode mode = |
| 1807 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; | 1819 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; |
| 1808 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites | 1820 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites |
| 1809 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE; | 1821 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE; |
| 1810 | 1822 |
| 1811 if (has_fast_elements) { | 1823 if (has_fast_elements) { |
| 1812 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; | 1824 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2043 // Initial send value is undefined. | 2055 // Initial send value is undefined. |
| 2044 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 2056 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
| 2045 __ Branch(&l_next); | 2057 __ Branch(&l_next); |
| 2046 | 2058 |
| 2047 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 2059 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
| 2048 __ bind(&l_catch); | 2060 __ bind(&l_catch); |
| 2049 __ mov(a0, v0); | 2061 __ mov(a0, v0); |
| 2050 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 2062 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
| 2051 __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw" | 2063 __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw" |
| 2052 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter | 2064 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter |
| 2053 __ push(a3); // iter | 2065 __ Push(a3, a0); // iter, exception |
| 2054 __ push(a0); // exception | |
| 2055 __ jmp(&l_call); | 2066 __ jmp(&l_call); |
| 2056 | 2067 |
| 2057 // try { received = %yield result } | 2068 // try { received = %yield result } |
| 2058 // Shuffle the received result above a try handler and yield it without | 2069 // Shuffle the received result above a try handler and yield it without |
| 2059 // re-boxing. | 2070 // re-boxing. |
| 2060 __ bind(&l_try); | 2071 __ bind(&l_try); |
| 2061 __ pop(a0); // result | 2072 __ pop(a0); // result |
| 2062 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2073 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
| 2063 const int handler_size = StackHandlerConstants::kSize; | 2074 const int handler_size = StackHandlerConstants::kSize; |
| 2064 __ push(a0); // result | 2075 __ push(a0); // result |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2082 __ pop(v0); // result | 2093 __ pop(v0); // result |
| 2083 EmitReturnSequence(); | 2094 EmitReturnSequence(); |
| 2084 __ mov(a0, v0); | 2095 __ mov(a0, v0); |
| 2085 __ bind(&l_resume); // received in a0 | 2096 __ bind(&l_resume); // received in a0 |
| 2086 __ PopTryHandler(); | 2097 __ PopTryHandler(); |
| 2087 | 2098 |
| 2088 // receiver = iter; f = 'next'; arg = received; | 2099 // receiver = iter; f = 'next'; arg = received; |
| 2089 __ bind(&l_next); | 2100 __ bind(&l_next); |
| 2090 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" | 2101 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" |
| 2091 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter | 2102 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter |
| 2092 __ push(a3); // iter | 2103 __ Push(a3, a0); // iter, received |
| 2093 __ push(a0); // received | |
| 2094 | 2104 |
| 2095 // result = receiver[f](arg); | 2105 // result = receiver[f](arg); |
| 2096 __ bind(&l_call); | 2106 __ bind(&l_call); |
| 2097 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2107 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); |
| 2098 CallIC(ic); | 2108 CallIC(ic); |
| 2099 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2109 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2100 | 2110 |
| 2101 // if (!result.done) goto l_try; | 2111 // if (!result.done) goto l_try; |
| 2102 __ bind(&l_loop); | 2112 __ bind(&l_loop); |
| 2103 __ mov(a0, v0); | 2113 __ mov(a0, v0); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2159 __ push(a2); | 2169 __ push(a2); |
| 2160 __ jmp(&push_argument_holes); | 2170 __ jmp(&push_argument_holes); |
| 2161 | 2171 |
| 2162 // Enter a new JavaScript frame, and initialize its slots as they were when | 2172 // Enter a new JavaScript frame, and initialize its slots as they were when |
| 2163 // the generator was suspended. | 2173 // the generator was suspended. |
| 2164 Label resume_frame; | 2174 Label resume_frame; |
| 2165 __ bind(&push_frame); | 2175 __ bind(&push_frame); |
| 2166 __ Call(&resume_frame); | 2176 __ Call(&resume_frame); |
| 2167 __ jmp(&done); | 2177 __ jmp(&done); |
| 2168 __ bind(&resume_frame); | 2178 __ bind(&resume_frame); |
| 2169 __ push(ra); // Return address. | 2179 // ra = return address. |
| 2170 __ push(fp); // Caller's frame pointer. | 2180 // fp = caller's frame pointer. |
| 2171 __ mov(fp, sp); | 2181 // cp = callee's context, |
| 2172 __ push(cp); // Callee's context. | 2182 // t0 = callee's JS function. |
| 2173 __ push(t0); // Callee's JS Function. | 2183 __ Push(ra, fp, cp, t0); |
| 2184 // Adjust FP to point to saved FP. |
| 2185 __ Addu(fp, sp, 2 * kPointerSize); |
| 2174 | 2186 |
| 2175 // Load the operand stack size. | 2187 // Load the operand stack size. |
| 2176 __ lw(a3, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset)); | 2188 __ lw(a3, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset)); |
| 2177 __ lw(a3, FieldMemOperand(a3, FixedArray::kLengthOffset)); | 2189 __ lw(a3, FieldMemOperand(a3, FixedArray::kLengthOffset)); |
| 2178 __ SmiUntag(a3); | 2190 __ SmiUntag(a3); |
| 2179 | 2191 |
| 2180 // If we are sending a value and there is no operand stack, we can jump back | 2192 // If we are sending a value and there is no operand stack, we can jump back |
| 2181 // in directly. | 2193 // in directly. |
| 2182 if (resume_mode == JSGeneratorObject::NEXT) { | 2194 if (resume_mode == JSGeneratorObject::NEXT) { |
| 2183 Label slow_resume; | 2195 Label slow_resume; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2194 | 2206 |
| 2195 // Otherwise, we push holes for the operand stack and call the runtime to fix | 2207 // Otherwise, we push holes for the operand stack and call the runtime to fix |
| 2196 // up the stack and the handlers. | 2208 // up the stack and the handlers. |
| 2197 Label push_operand_holes, call_resume; | 2209 Label push_operand_holes, call_resume; |
| 2198 __ bind(&push_operand_holes); | 2210 __ bind(&push_operand_holes); |
| 2199 __ Subu(a3, a3, Operand(1)); | 2211 __ Subu(a3, a3, Operand(1)); |
| 2200 __ Branch(&call_resume, lt, a3, Operand(zero_reg)); | 2212 __ Branch(&call_resume, lt, a3, Operand(zero_reg)); |
| 2201 __ push(a2); | 2213 __ push(a2); |
| 2202 __ Branch(&push_operand_holes); | 2214 __ Branch(&push_operand_holes); |
| 2203 __ bind(&call_resume); | 2215 __ bind(&call_resume); |
| 2204 __ push(a1); | 2216 ASSERT(!result_register().is(a1)); |
| 2205 __ push(result_register()); | 2217 __ Push(a1, result_register()); |
| 2206 __ Push(Smi::FromInt(resume_mode)); | 2218 __ Push(Smi::FromInt(resume_mode)); |
| 2207 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2219 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
| 2208 // Not reached: the runtime call returns elsewhere. | 2220 // Not reached: the runtime call returns elsewhere. |
| 2209 __ stop("not-reached"); | 2221 __ stop("not-reached"); |
| 2210 | 2222 |
| 2211 // Throw error if we attempt to operate on a running generator. | 2223 // Throw error if we attempt to operate on a running generator. |
| 2212 __ bind(&wrong_state); | 2224 __ bind(&wrong_state); |
| 2213 __ push(a1); | 2225 __ push(a1); |
| 2214 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); | 2226 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
| 2215 | 2227 |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2425 ? isolate()->builtins()->StoreIC_Initialize() | 2437 ? isolate()->builtins()->StoreIC_Initialize() |
| 2426 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2438 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
| 2427 CallIC(ic); | 2439 CallIC(ic); |
| 2428 break; | 2440 break; |
| 2429 } | 2441 } |
| 2430 case KEYED_PROPERTY: { | 2442 case KEYED_PROPERTY: { |
| 2431 __ push(result_register()); // Preserve value. | 2443 __ push(result_register()); // Preserve value. |
| 2432 VisitForStackValue(prop->obj()); | 2444 VisitForStackValue(prop->obj()); |
| 2433 VisitForAccumulatorValue(prop->key()); | 2445 VisitForAccumulatorValue(prop->key()); |
| 2434 __ mov(a1, result_register()); | 2446 __ mov(a1, result_register()); |
| 2435 __ pop(a2); | 2447 __ Pop(a0, a2); // a0 = restored value. |
| 2436 __ pop(a0); // Restore value. | |
| 2437 Handle<Code> ic = is_classic_mode() | 2448 Handle<Code> ic = is_classic_mode() |
| 2438 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2449 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2439 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2450 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2440 CallIC(ic); | 2451 CallIC(ic); |
| 2441 break; | 2452 break; |
| 2442 } | 2453 } |
| 2443 } | 2454 } |
| 2444 context()->Plug(v0); | 2455 context()->Plug(v0); |
| 2445 } | 2456 } |
| 2446 | 2457 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2568 // Assignment to a property, using a keyed store IC. | 2579 // Assignment to a property, using a keyed store IC. |
| 2569 | 2580 |
| 2570 // Record source code position before IC call. | 2581 // Record source code position before IC call. |
| 2571 SetSourcePosition(expr->position()); | 2582 SetSourcePosition(expr->position()); |
| 2572 // Call keyed store IC. | 2583 // Call keyed store IC. |
| 2573 // The arguments are: | 2584 // The arguments are: |
| 2574 // - a0 is the value, | 2585 // - a0 is the value, |
| 2575 // - a1 is the key, | 2586 // - a1 is the key, |
| 2576 // - a2 is the receiver. | 2587 // - a2 is the receiver. |
| 2577 __ mov(a0, result_register()); | 2588 __ mov(a0, result_register()); |
| 2578 __ pop(a1); // Key. | 2589 __ Pop(a2, a1); // a1 = key. |
| 2579 __ pop(a2); | |
| 2580 | 2590 |
| 2581 Handle<Code> ic = is_classic_mode() | 2591 Handle<Code> ic = is_classic_mode() |
| 2582 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2592 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2583 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2593 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2584 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2594 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); |
| 2585 | 2595 |
| 2586 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2596 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2587 context()->Plug(v0); | 2597 context()->Plug(v0); |
| 2588 } | 2598 } |
| 2589 | 2599 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2697 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2707 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2698 __ CallStub(&stub, expr->CallFeedbackId()); | 2708 __ CallStub(&stub, expr->CallFeedbackId()); |
| 2699 RecordJSReturnSite(expr); | 2709 RecordJSReturnSite(expr); |
| 2700 // Restore context register. | 2710 // Restore context register. |
| 2701 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2711 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2702 context()->DropAndPlug(1, v0); | 2712 context()->DropAndPlug(1, v0); |
| 2703 } | 2713 } |
| 2704 | 2714 |
| 2705 | 2715 |
| 2706 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 2716 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
| 2707 // Push copy of the first argument or undefined if it doesn't exist. | 2717 // t2: copy of the first argument or undefined if it doesn't exist. |
| 2708 if (arg_count > 0) { | 2718 if (arg_count > 0) { |
| 2709 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); | 2719 __ lw(t2, MemOperand(sp, arg_count * kPointerSize)); |
| 2710 } else { | 2720 } else { |
| 2711 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); | 2721 __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); |
| 2712 } | 2722 } |
| 2713 __ push(a1); | |
| 2714 | 2723 |
| 2715 // Push the receiver of the enclosing function. | 2724 // t1: the receiver of the enclosing function. |
| 2716 int receiver_offset = 2 + info_->scope()->num_parameters(); | 2725 int receiver_offset = 2 + info_->scope()->num_parameters(); |
| 2717 __ lw(a1, MemOperand(fp, receiver_offset * kPointerSize)); | 2726 __ lw(t1, MemOperand(fp, receiver_offset * kPointerSize)); |
| 2718 __ push(a1); | |
| 2719 // Push the language mode. | |
| 2720 __ li(a1, Operand(Smi::FromInt(language_mode()))); | |
| 2721 __ push(a1); | |
| 2722 | 2727 |
| 2723 // Push the start position of the scope the calls resides in. | 2728 // t0: the language mode. |
| 2729 __ li(t0, Operand(Smi::FromInt(language_mode()))); |
| 2730 |
| 2731 // a1: the start position of the scope the calls resides in. |
| 2724 __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); | 2732 __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); |
| 2725 __ push(a1); | |
| 2726 | 2733 |
| 2727 // Do the runtime call. | 2734 // Do the runtime call. |
| 2735 __ Push(t2, t1, t0, a1); |
| 2728 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2736 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
| 2729 } | 2737 } |
| 2730 | 2738 |
| 2731 | 2739 |
| 2732 void FullCodeGenerator::VisitCall(Call* expr) { | 2740 void FullCodeGenerator::VisitCall(Call* expr) { |
| 2733 #ifdef DEBUG | 2741 #ifdef DEBUG |
| 2734 // We want to verify that RecordJSReturnSite gets called on all paths | 2742 // We want to verify that RecordJSReturnSite gets called on all paths |
| 2735 // through this function. Avoid early returns. | 2743 // through this function. Avoid early returns. |
| 2736 expr->return_is_recorded_ = false; | 2744 expr->return_is_recorded_ = false; |
| 2737 #endif | 2745 #endif |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2790 | 2798 |
| 2791 { PreservePositionScope scope(masm()->positions_recorder()); | 2799 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2792 // Generate code for loading from variables potentially shadowed | 2800 // Generate code for loading from variables potentially shadowed |
| 2793 // by eval-introduced variables. | 2801 // by eval-introduced variables. |
| 2794 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2802 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2795 } | 2803 } |
| 2796 | 2804 |
| 2797 __ bind(&slow); | 2805 __ bind(&slow); |
| 2798 // Call the runtime to find the function to call (returned in v0) | 2806 // Call the runtime to find the function to call (returned in v0) |
| 2799 // and the object holding it (returned in v1). | 2807 // and the object holding it (returned in v1). |
| 2800 __ push(context_register()); | 2808 ASSERT(!context_register().is(a2)); |
| 2801 __ li(a2, Operand(proxy->name())); | 2809 __ li(a2, Operand(proxy->name())); |
| 2802 __ push(a2); | 2810 __ Push(context_register(), a2); |
| 2803 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 2811 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 2804 __ Push(v0, v1); // Function, receiver. | 2812 __ Push(v0, v1); // Function, receiver. |
| 2805 | 2813 |
| 2806 // If fast case code has been generated, emit code to push the | 2814 // If fast case code has been generated, emit code to push the |
| 2807 // function and receiver and have the slow path jump around this | 2815 // function and receiver and have the slow path jump around this |
| 2808 // code. | 2816 // code. |
| 2809 if (done.is_linked()) { | 2817 if (done.is_linked()) { |
| 2810 Label call; | 2818 Label call; |
| 2811 __ Branch(&call); | 2819 __ Branch(&call); |
| 2812 __ bind(&done); | 2820 __ bind(&done); |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3118 __ JumpIfSmi(v0, if_false); | 3126 __ JumpIfSmi(v0, if_false); |
| 3119 __ GetObjectType(v0, a1, a2); | 3127 __ GetObjectType(v0, a1, a2); |
| 3120 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); | 3128 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 3121 __ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE)); | 3129 __ Branch(if_true, eq, a2, Operand(JS_FUNCTION_TYPE)); |
| 3122 __ Branch(if_false); | 3130 __ Branch(if_false); |
| 3123 | 3131 |
| 3124 context()->Plug(if_true, if_false); | 3132 context()->Plug(if_true, if_false); |
| 3125 } | 3133 } |
| 3126 | 3134 |
| 3127 | 3135 |
| 3136 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) { |
| 3137 ZoneList<Expression*>* args = expr->arguments(); |
| 3138 ASSERT(args->length() == 1); |
| 3139 |
| 3140 VisitForAccumulatorValue(args->at(0)); |
| 3141 |
| 3142 Label materialize_true, materialize_false; |
| 3143 Label* if_true = NULL; |
| 3144 Label* if_false = NULL; |
| 3145 Label* fall_through = NULL; |
| 3146 context()->PrepareTest(&materialize_true, &materialize_false, |
| 3147 &if_true, &if_false, &fall_through); |
| 3148 |
| 3149 __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK); |
| 3150 __ lw(a2, FieldMemOperand(v0, HeapNumber::kExponentOffset)); |
| 3151 __ lw(a1, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); |
| 3152 __ li(t0, 0x80000000); |
| 3153 Label not_nan; |
| 3154 __ Branch(¬_nan, ne, a2, Operand(t0)); |
| 3155 __ mov(t0, zero_reg); |
| 3156 __ mov(a2, a1); |
| 3157 __ bind(¬_nan); |
| 3158 |
| 3159 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); |
| 3160 Split(eq, a2, Operand(t0), if_true, if_false, fall_through); |
| 3161 |
| 3162 context()->Plug(if_true, if_false); |
| 3163 } |
| 3164 |
| 3165 |
| 3128 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { | 3166 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { |
| 3129 ZoneList<Expression*>* args = expr->arguments(); | 3167 ZoneList<Expression*>* args = expr->arguments(); |
| 3130 ASSERT(args->length() == 1); | 3168 ASSERT(args->length() == 1); |
| 3131 | 3169 |
| 3132 VisitForAccumulatorValue(args->at(0)); | 3170 VisitForAccumulatorValue(args->at(0)); |
| 3133 | 3171 |
| 3134 Label materialize_true, materialize_false; | 3172 Label materialize_true, materialize_false; |
| 3135 Label* if_true = NULL; | 3173 Label* if_true = NULL; |
| 3136 Label* if_false = NULL; | 3174 Label* if_false = NULL; |
| 3137 Label* fall_through = NULL; | 3175 Label* fall_through = NULL; |
| (...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3504 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3542 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
| 3505 ZoneList<Expression*>* args = expr->arguments(); | 3543 ZoneList<Expression*>* args = expr->arguments(); |
| 3506 ASSERT_EQ(3, args->length()); | 3544 ASSERT_EQ(3, args->length()); |
| 3507 | 3545 |
| 3508 Register string = v0; | 3546 Register string = v0; |
| 3509 Register index = a1; | 3547 Register index = a1; |
| 3510 Register value = a2; | 3548 Register value = a2; |
| 3511 | 3549 |
| 3512 VisitForStackValue(args->at(1)); // index | 3550 VisitForStackValue(args->at(1)); // index |
| 3513 VisitForStackValue(args->at(2)); // value | 3551 VisitForStackValue(args->at(2)); // value |
| 3514 __ pop(value); | 3552 __ Pop(index, value); |
| 3515 __ pop(index); | |
| 3516 VisitForAccumulatorValue(args->at(0)); // string | 3553 VisitForAccumulatorValue(args->at(0)); // string |
| 3517 | 3554 |
| 3518 if (FLAG_debug_code) { | 3555 if (FLAG_debug_code) { |
| 3519 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 3556 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
| 3520 EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); | 3557 EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); |
| 3521 } | 3558 } |
| 3522 | 3559 |
| 3523 __ SmiUntag(value, value); | 3560 __ SmiUntag(value, value); |
| 3524 __ Addu(at, | 3561 __ Addu(at, |
| 3525 string, | 3562 string, |
| 3526 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3563 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
| 3527 __ SmiUntag(index); | 3564 __ SmiUntag(index); |
| 3528 __ Addu(at, at, index); | 3565 __ Addu(at, at, index); |
| 3529 __ sb(value, MemOperand(at)); | 3566 __ sb(value, MemOperand(at)); |
| 3530 context()->Plug(string); | 3567 context()->Plug(string); |
| 3531 } | 3568 } |
| 3532 | 3569 |
| 3533 | 3570 |
| 3534 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { | 3571 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { |
| 3535 ZoneList<Expression*>* args = expr->arguments(); | 3572 ZoneList<Expression*>* args = expr->arguments(); |
| 3536 ASSERT_EQ(3, args->length()); | 3573 ASSERT_EQ(3, args->length()); |
| 3537 | 3574 |
| 3538 Register string = v0; | 3575 Register string = v0; |
| 3539 Register index = a1; | 3576 Register index = a1; |
| 3540 Register value = a2; | 3577 Register value = a2; |
| 3541 | 3578 |
| 3542 VisitForStackValue(args->at(1)); // index | 3579 VisitForStackValue(args->at(1)); // index |
| 3543 VisitForStackValue(args->at(2)); // value | 3580 VisitForStackValue(args->at(2)); // value |
| 3544 __ pop(value); | 3581 __ Pop(index, value); |
| 3545 __ pop(index); | |
| 3546 VisitForAccumulatorValue(args->at(0)); // string | 3582 VisitForAccumulatorValue(args->at(0)); // string |
| 3547 | 3583 |
| 3548 if (FLAG_debug_code) { | 3584 if (FLAG_debug_code) { |
| 3549 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 3585 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
| 3550 EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); | 3586 EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); |
| 3551 } | 3587 } |
| 3552 | 3588 |
| 3553 __ SmiUntag(value, value); | 3589 __ SmiUntag(value, value); |
| 3554 __ Addu(at, | 3590 __ Addu(at, |
| 3555 string, | 3591 string, |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3727 generator.GenerateSlow(masm_, call_helper); | 3763 generator.GenerateSlow(masm_, call_helper); |
| 3728 | 3764 |
| 3729 __ bind(&done); | 3765 __ bind(&done); |
| 3730 context()->Plug(result); | 3766 context()->Plug(result); |
| 3731 } | 3767 } |
| 3732 | 3768 |
| 3733 | 3769 |
| 3734 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { | 3770 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { |
| 3735 ZoneList<Expression*>* args = expr->arguments(); | 3771 ZoneList<Expression*>* args = expr->arguments(); |
| 3736 ASSERT_EQ(2, args->length()); | 3772 ASSERT_EQ(2, args->length()); |
| 3737 VisitForStackValue(args->at(0)); | 3773 if (FLAG_new_string_add) { |
| 3738 VisitForStackValue(args->at(1)); | 3774 VisitForStackValue(args->at(0)); |
| 3775 VisitForAccumulatorValue(args->at(1)); |
| 3739 | 3776 |
| 3740 StringAddStub stub(STRING_ADD_CHECK_BOTH); | 3777 __ pop(a1); |
| 3741 __ CallStub(&stub); | 3778 NewStringAddStub stub(STRING_ADD_CHECK_BOTH, NOT_TENURED); |
| 3779 __ CallStub(&stub); |
| 3780 } else { |
| 3781 VisitForStackValue(args->at(0)); |
| 3782 VisitForStackValue(args->at(1)); |
| 3783 |
| 3784 StringAddStub stub(STRING_ADD_CHECK_BOTH); |
| 3785 __ CallStub(&stub); |
| 3786 } |
| 3742 context()->Plug(v0); | 3787 context()->Plug(v0); |
| 3743 } | 3788 } |
| 3744 | 3789 |
| 3745 | 3790 |
| 3746 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { | 3791 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { |
| 3747 ZoneList<Expression*>* args = expr->arguments(); | 3792 ZoneList<Expression*>* args = expr->arguments(); |
| 3748 ASSERT_EQ(2, args->length()); | 3793 ASSERT_EQ(2, args->length()); |
| 3749 | 3794 |
| 3750 VisitForStackValue(args->at(0)); | 3795 VisitForStackValue(args->at(0)); |
| 3751 VisitForStackValue(args->at(1)); | 3796 VisitForStackValue(args->at(1)); |
| 3752 | 3797 |
| 3753 StringCompareStub stub; | 3798 StringCompareStub stub; |
| 3754 __ CallStub(&stub); | 3799 __ CallStub(&stub); |
| 3755 context()->Plug(v0); | 3800 context()->Plug(v0); |
| 3756 } | 3801 } |
| 3757 | 3802 |
| 3758 | 3803 |
| 3759 void FullCodeGenerator::EmitMathSin(CallRuntime* expr) { | |
| 3760 // Load the argument on the stack and call the stub. | |
| 3761 TranscendentalCacheStub stub(TranscendentalCache::SIN, | |
| 3762 TranscendentalCacheStub::TAGGED); | |
| 3763 ZoneList<Expression*>* args = expr->arguments(); | |
| 3764 ASSERT(args->length() == 1); | |
| 3765 VisitForStackValue(args->at(0)); | |
| 3766 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. | |
| 3767 __ CallStub(&stub); | |
| 3768 context()->Plug(v0); | |
| 3769 } | |
| 3770 | |
| 3771 | |
| 3772 void FullCodeGenerator::EmitMathCos(CallRuntime* expr) { | |
| 3773 // Load the argument on the stack and call the stub. | |
| 3774 TranscendentalCacheStub stub(TranscendentalCache::COS, | |
| 3775 TranscendentalCacheStub::TAGGED); | |
| 3776 ZoneList<Expression*>* args = expr->arguments(); | |
| 3777 ASSERT(args->length() == 1); | |
| 3778 VisitForStackValue(args->at(0)); | |
| 3779 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. | |
| 3780 __ CallStub(&stub); | |
| 3781 context()->Plug(v0); | |
| 3782 } | |
| 3783 | |
| 3784 | |
| 3785 void FullCodeGenerator::EmitMathTan(CallRuntime* expr) { | |
| 3786 // Load the argument on the stack and call the stub. | |
| 3787 TranscendentalCacheStub stub(TranscendentalCache::TAN, | |
| 3788 TranscendentalCacheStub::TAGGED); | |
| 3789 ZoneList<Expression*>* args = expr->arguments(); | |
| 3790 ASSERT(args->length() == 1); | |
| 3791 VisitForStackValue(args->at(0)); | |
| 3792 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. | |
| 3793 __ CallStub(&stub); | |
| 3794 context()->Plug(v0); | |
| 3795 } | |
| 3796 | |
| 3797 | |
| 3798 void FullCodeGenerator::EmitMathLog(CallRuntime* expr) { | 3804 void FullCodeGenerator::EmitMathLog(CallRuntime* expr) { |
| 3799 // Load the argument on the stack and call the stub. | 3805 // Load the argument on the stack and call the stub. |
| 3800 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 3806 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
| 3801 TranscendentalCacheStub::TAGGED); | 3807 TranscendentalCacheStub::TAGGED); |
| 3802 ZoneList<Expression*>* args = expr->arguments(); | 3808 ZoneList<Expression*>* args = expr->arguments(); |
| 3803 ASSERT(args->length() == 1); | 3809 ASSERT(args->length() == 1); |
| 3804 VisitForStackValue(args->at(0)); | 3810 VisitForStackValue(args->at(0)); |
| 3805 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. | 3811 __ mov(a0, result_register()); // Stub requires parameter in a0 and on tos. |
| 3806 __ CallStub(&stub); | 3812 __ CallStub(&stub); |
| 3807 context()->Plug(v0); | 3813 context()->Plug(v0); |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4296 __ Push(a2, a1, a0); | 4302 __ Push(a2, a1, a0); |
| 4297 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4303 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4298 context()->Plug(v0); | 4304 context()->Plug(v0); |
| 4299 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4305 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4300 // Result of deleting non-global, non-dynamic variables is false. | 4306 // Result of deleting non-global, non-dynamic variables is false. |
| 4301 // The subexpression does not have side effects. | 4307 // The subexpression does not have side effects. |
| 4302 context()->Plug(var->is_this()); | 4308 context()->Plug(var->is_this()); |
| 4303 } else { | 4309 } else { |
| 4304 // Non-global variable. Call the runtime to try to delete from the | 4310 // Non-global variable. Call the runtime to try to delete from the |
| 4305 // context where the variable was introduced. | 4311 // context where the variable was introduced. |
| 4306 __ push(context_register()); | 4312 ASSERT(!context_register().is(a2)); |
| 4307 __ li(a2, Operand(var->name())); | 4313 __ li(a2, Operand(var->name())); |
| 4308 __ push(a2); | 4314 __ Push(context_register(), a2); |
| 4309 __ CallRuntime(Runtime::kDeleteContextSlot, 2); | 4315 __ CallRuntime(Runtime::kDeleteContextSlot, 2); |
| 4310 context()->Plug(v0); | 4316 context()->Plug(v0); |
| 4311 } | 4317 } |
| 4312 } else { | 4318 } else { |
| 4313 // Result of deleting non-property, non-variable reference is true. | 4319 // Result of deleting non-property, non-variable reference is true. |
| 4314 // The subexpression may have side effects. | 4320 // The subexpression may have side effects. |
| 4315 VisitForEffect(expr->expression()); | 4321 VisitForEffect(expr->expression()); |
| 4316 context()->Plug(true); | 4322 context()->Plug(true); |
| 4317 } | 4323 } |
| 4318 break; | 4324 break; |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4429 } | 4435 } |
| 4430 | 4436 |
| 4431 // We need a second deoptimization point after loading the value | 4437 // We need a second deoptimization point after loading the value |
| 4432 // in case evaluating the property load my have a side effect. | 4438 // in case evaluating the property load my have a side effect. |
| 4433 if (assign_type == VARIABLE) { | 4439 if (assign_type == VARIABLE) { |
| 4434 PrepareForBailout(expr->expression(), TOS_REG); | 4440 PrepareForBailout(expr->expression(), TOS_REG); |
| 4435 } else { | 4441 } else { |
| 4436 PrepareForBailoutForId(prop->LoadId(), TOS_REG); | 4442 PrepareForBailoutForId(prop->LoadId(), TOS_REG); |
| 4437 } | 4443 } |
| 4438 | 4444 |
| 4439 // Call ToNumber only if operand is not a smi. | 4445 // Inline smi case if we are in a loop. |
| 4440 Label no_conversion; | 4446 Label stub_call, done; |
| 4447 JumpPatchSite patch_site(masm_); |
| 4448 |
| 4449 int count_value = expr->op() == Token::INC ? 1 : -1; |
| 4450 __ mov(a0, v0); |
| 4441 if (ShouldInlineSmiCase(expr->op())) { | 4451 if (ShouldInlineSmiCase(expr->op())) { |
| 4442 __ JumpIfSmi(v0, &no_conversion); | 4452 Label slow; |
| 4453 patch_site.EmitJumpIfNotSmi(v0, &slow); |
| 4454 |
| 4455 // Save result for postfix expressions. |
| 4456 if (expr->is_postfix()) { |
| 4457 if (!context()->IsEffect()) { |
| 4458 // Save the result on the stack. If we have a named or keyed property |
| 4459 // we store the result under the receiver that is currently on top |
| 4460 // of the stack. |
| 4461 switch (assign_type) { |
| 4462 case VARIABLE: |
| 4463 __ push(v0); |
| 4464 break; |
| 4465 case NAMED_PROPERTY: |
| 4466 __ sw(v0, MemOperand(sp, kPointerSize)); |
| 4467 break; |
| 4468 case KEYED_PROPERTY: |
| 4469 __ sw(v0, MemOperand(sp, 2 * kPointerSize)); |
| 4470 break; |
| 4471 } |
| 4472 } |
| 4473 } |
| 4474 |
| 4475 Register scratch1 = a1; |
| 4476 Register scratch2 = t0; |
| 4477 __ li(scratch1, Operand(Smi::FromInt(count_value))); |
| 4478 __ AdduAndCheckForOverflow(v0, v0, scratch1, scratch2); |
| 4479 __ BranchOnNoOverflow(&done, scratch2); |
| 4480 // Call stub. Undo operation first. |
| 4481 __ Move(v0, a0); |
| 4482 __ jmp(&stub_call); |
| 4483 __ bind(&slow); |
| 4443 } | 4484 } |
| 4444 __ mov(a0, v0); | |
| 4445 ToNumberStub convert_stub; | 4485 ToNumberStub convert_stub; |
| 4446 __ CallStub(&convert_stub); | 4486 __ CallStub(&convert_stub); |
| 4447 __ bind(&no_conversion); | |
| 4448 | 4487 |
| 4449 // Save result for postfix expressions. | 4488 // Save result for postfix expressions. |
| 4450 if (expr->is_postfix()) { | 4489 if (expr->is_postfix()) { |
| 4451 if (!context()->IsEffect()) { | 4490 if (!context()->IsEffect()) { |
| 4452 // Save the result on the stack. If we have a named or keyed property | 4491 // Save the result on the stack. If we have a named or keyed property |
| 4453 // we store the result under the receiver that is currently on top | 4492 // we store the result under the receiver that is currently on top |
| 4454 // of the stack. | 4493 // of the stack. |
| 4455 switch (assign_type) { | 4494 switch (assign_type) { |
| 4456 case VARIABLE: | 4495 case VARIABLE: |
| 4457 __ push(v0); | 4496 __ push(v0); |
| 4458 break; | 4497 break; |
| 4459 case NAMED_PROPERTY: | 4498 case NAMED_PROPERTY: |
| 4460 __ sw(v0, MemOperand(sp, kPointerSize)); | 4499 __ sw(v0, MemOperand(sp, kPointerSize)); |
| 4461 break; | 4500 break; |
| 4462 case KEYED_PROPERTY: | 4501 case KEYED_PROPERTY: |
| 4463 __ sw(v0, MemOperand(sp, 2 * kPointerSize)); | 4502 __ sw(v0, MemOperand(sp, 2 * kPointerSize)); |
| 4464 break; | 4503 break; |
| 4465 } | 4504 } |
| 4466 } | 4505 } |
| 4467 } | 4506 } |
| 4468 __ mov(a0, result_register()); | |
| 4469 | 4507 |
| 4470 // Inline smi case if we are in a loop. | 4508 __ bind(&stub_call); |
| 4471 Label stub_call, done; | 4509 __ mov(a1, v0); |
| 4472 JumpPatchSite patch_site(masm_); | |
| 4473 | |
| 4474 int count_value = expr->op() == Token::INC ? 1 : -1; | |
| 4475 if (ShouldInlineSmiCase(expr->op())) { | |
| 4476 __ li(a1, Operand(Smi::FromInt(count_value))); | |
| 4477 __ AdduAndCheckForOverflow(v0, a0, a1, t0); | |
| 4478 __ BranchOnOverflow(&stub_call, t0); // Do stub on overflow. | |
| 4479 | |
| 4480 // We could eliminate this smi check if we split the code at | |
| 4481 // the first smi check before calling ToNumber. | |
| 4482 patch_site.EmitJumpIfSmi(v0, &done); | |
| 4483 __ bind(&stub_call); | |
| 4484 } | |
| 4485 __ mov(a1, a0); | |
| 4486 __ li(a0, Operand(Smi::FromInt(count_value))); | 4510 __ li(a0, Operand(Smi::FromInt(count_value))); |
| 4487 | 4511 |
| 4488 // Record position before stub call. | 4512 // Record position before stub call. |
| 4489 SetSourcePosition(expr->position()); | 4513 SetSourcePosition(expr->position()); |
| 4490 | 4514 |
| 4491 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); | 4515 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); |
| 4492 CallIC(stub.GetCode(isolate()), | 4516 CallIC(stub.GetCode(isolate()), |
| 4493 RelocInfo::CODE_TARGET, | 4517 RelocInfo::CODE_TARGET, |
| 4494 expr->CountBinOpFeedbackId()); | 4518 expr->CountBinOpFeedbackId()); |
| 4495 patch_site.EmitPatchInfo(); | 4519 patch_site.EmitPatchInfo(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4530 if (!context()->IsEffect()) { | 4554 if (!context()->IsEffect()) { |
| 4531 context()->PlugTOS(); | 4555 context()->PlugTOS(); |
| 4532 } | 4556 } |
| 4533 } else { | 4557 } else { |
| 4534 context()->Plug(v0); | 4558 context()->Plug(v0); |
| 4535 } | 4559 } |
| 4536 break; | 4560 break; |
| 4537 } | 4561 } |
| 4538 case KEYED_PROPERTY: { | 4562 case KEYED_PROPERTY: { |
| 4539 __ mov(a0, result_register()); // Value. | 4563 __ mov(a0, result_register()); // Value. |
| 4540 __ pop(a1); // Key. | 4564 __ Pop(a2, a1); // a1 = key, a2 = receiver. |
| 4541 __ pop(a2); // Receiver. | |
| 4542 Handle<Code> ic = is_classic_mode() | 4565 Handle<Code> ic = is_classic_mode() |
| 4543 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4566 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4544 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4567 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4545 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | 4568 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); |
| 4546 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4569 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4547 if (expr->is_postfix()) { | 4570 if (expr->is_postfix()) { |
| 4548 if (!context()->IsEffect()) { | 4571 if (!context()->IsEffect()) { |
| 4549 context()->PlugTOS(); | 4572 context()->PlugTOS(); |
| 4550 } | 4573 } |
| 4551 } else { | 4574 } else { |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4993 Assembler::target_address_at(pc_immediate_load_address)) == | 5016 Assembler::target_address_at(pc_immediate_load_address)) == |
| 4994 reinterpret_cast<uint32_t>( | 5017 reinterpret_cast<uint32_t>( |
| 4995 isolate->builtins()->OsrAfterStackCheck()->entry())); | 5018 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4996 return OSR_AFTER_STACK_CHECK; | 5019 return OSR_AFTER_STACK_CHECK; |
| 4997 } | 5020 } |
| 4998 | 5021 |
| 4999 | 5022 |
| 5000 } } // namespace v8::internal | 5023 } } // namespace v8::internal |
| 5001 | 5024 |
| 5002 #endif // V8_TARGET_ARCH_MIPS | 5025 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |