Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/arm/full-codegen-arm.cc

Issue 71163006: Merge bleeding_edge r17376:17693. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Fix all.gyp Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/deoptimizer-arm.cc ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 141 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
142 __ stop("stop-at"); 142 __ stop("stop-at");
143 } 143 }
144 #endif 144 #endif
145 145
146 // Strict mode functions and builtins need to replace the receiver 146 // Strict mode functions and builtins need to replace the receiver
147 // with undefined when called as functions (without an explicit 147 // with undefined when called as functions (without an explicit
148 // receiver object). r5 is zero for method calls and non-zero for 148 // receiver object). r5 is zero for method calls and non-zero for
149 // function calls. 149 // function calls.
150 if (!info->is_classic_mode() || info->is_native()) { 150 if (!info->is_classic_mode() || info->is_native()) {
151 Label ok;
152 __ cmp(r5, Operand::Zero()); 151 __ cmp(r5, Operand::Zero());
153 __ b(eq, &ok);
154 int receiver_offset = info->scope()->num_parameters() * kPointerSize; 152 int receiver_offset = info->scope()->num_parameters() * kPointerSize;
155 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 153 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
156 __ str(r2, MemOperand(sp, receiver_offset)); 154 __ str(r2, MemOperand(sp, receiver_offset), ne);
157 __ bind(&ok);
158 } 155 }
159 156
160 // Open a frame scope to indicate that there is a frame on the stack. The 157 // Open a frame scope to indicate that there is a frame on the stack. The
161 // MANUAL indicates that the scope shouldn't actually generate code to set up 158 // MANUAL indicates that the scope shouldn't actually generate code to set up
162 // the frame (that is done below). 159 // the frame (that is done below).
163 FrameScope frame_scope(masm_, StackFrame::MANUAL); 160 FrameScope frame_scope(masm_, StackFrame::MANUAL);
164 161
165 info->set_prologue_offset(masm_->pc_offset()); 162 info->set_prologue_offset(masm_->pc_offset());
166 __ Prologue(BUILD_FUNCTION_FRAME); 163 __ Prologue(BUILD_FUNCTION_FRAME);
167 info->AddNoFrameRange(0, masm_->pc_offset()); 164 info->AddNoFrameRange(0, masm_->pc_offset());
168 165
169 { Comment cmnt(masm_, "[ Allocate locals"); 166 { Comment cmnt(masm_, "[ Allocate locals");
170 int locals_count = info->scope()->num_stack_slots(); 167 int locals_count = info->scope()->num_stack_slots();
171 // Generators allocate locals, if any, in context slots. 168 // Generators allocate locals, if any, in context slots.
172 ASSERT(!info->function()->is_generator() || locals_count == 0); 169 ASSERT(!info->function()->is_generator() || locals_count == 0);
173 if (locals_count > 0) { 170 if (locals_count > 0) {
174 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 171 // Emit a loop to initialize stack cells for locals when optimizing for
175 for (int i = 0; i < locals_count; i++) { 172 // size. Otherwise, unroll the loop for maximum performance.
176 __ push(ip); 173 __ LoadRoot(r9, Heap::kUndefinedValueRootIndex);
174 if (FLAG_optimize_for_size && locals_count > 4) {
175 Label loop;
176 __ mov(r2, Operand(locals_count));
177 __ bind(&loop);
178 __ sub(r2, r2, Operand(1), SetCC);
179 __ push(r9);
180 __ b(&loop, ne);
181 } else {
182 for (int i = 0; i < locals_count; i++) {
183 __ push(r9);
184 }
177 } 185 }
178 } 186 }
179 } 187 }
180 188
181 bool function_in_register = true; 189 bool function_in_register = true;
182 190
183 // Possibly allocate a local context. 191 // Possibly allocate a local context.
184 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 192 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
185 if (heap_slots > 0) { 193 if (heap_slots > 0) {
186 // Argument to NewContext is the function, which is still in r1. 194 // Argument to NewContext is the function, which is still in r1.
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 __ bind(&done); 617 __ bind(&done);
610 } 618 }
611 619
612 620
613 void FullCodeGenerator::StackValueContext::Plug( 621 void FullCodeGenerator::StackValueContext::Plug(
614 Label* materialize_true, 622 Label* materialize_true,
615 Label* materialize_false) const { 623 Label* materialize_false) const {
616 Label done; 624 Label done;
617 __ bind(materialize_true); 625 __ bind(materialize_true);
618 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 626 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
619 __ push(ip);
620 __ jmp(&done); 627 __ jmp(&done);
621 __ bind(materialize_false); 628 __ bind(materialize_false);
622 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 629 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
630 __ bind(&done);
623 __ push(ip); 631 __ push(ip);
624 __ bind(&done);
625 } 632 }
626 633
627 634
628 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, 635 void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
629 Label* materialize_false) const { 636 Label* materialize_false) const {
630 ASSERT(materialize_true == true_label_); 637 ASSERT(materialize_true == true_label_);
631 ASSERT(materialize_false == false_label_); 638 ASSERT(materialize_false == false_label_);
632 } 639 }
633 640
634 641
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 __ jmp(&exit); 1158 __ jmp(&exit);
1152 1159
1153 // We got a fixed array in register r0. Iterate through that. 1160 // We got a fixed array in register r0. Iterate through that.
1154 Label non_proxy; 1161 Label non_proxy;
1155 __ bind(&fixed_array); 1162 __ bind(&fixed_array);
1156 1163
1157 Handle<Cell> cell = isolate()->factory()->NewCell( 1164 Handle<Cell> cell = isolate()->factory()->NewCell(
1158 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker), 1165 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
1159 isolate())); 1166 isolate()));
1160 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell); 1167 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
1161 __ LoadHeapObject(r1, cell); 1168 __ Move(r1, cell);
1162 __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); 1169 __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
1163 __ str(r2, FieldMemOperand(r1, Cell::kValueOffset)); 1170 __ str(r2, FieldMemOperand(r1, Cell::kValueOffset));
1164 1171
1165 __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check 1172 __ mov(r1, Operand(Smi::FromInt(1))); // Smi indicates slow check
1166 __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object 1173 __ ldr(r2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object
1167 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1174 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1168 __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE); 1175 __ CompareObjectType(r2, r3, r3, LAST_JS_PROXY_TYPE);
1169 __ b(gt, &non_proxy); 1176 __ b(gt, &non_proxy);
1170 __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy 1177 __ mov(r1, Operand(Smi::FromInt(0))); // Zero indicates proxy
1171 __ bind(&non_proxy); 1178 __ bind(&non_proxy);
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
1593 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 1600 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1594 __ mov(r5, r0); 1601 __ mov(r5, r0);
1595 1602
1596 __ bind(&materialized); 1603 __ bind(&materialized);
1597 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; 1604 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
1598 Label allocated, runtime_allocate; 1605 Label allocated, runtime_allocate;
1599 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); 1606 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT);
1600 __ jmp(&allocated); 1607 __ jmp(&allocated);
1601 1608
1602 __ bind(&runtime_allocate); 1609 __ bind(&runtime_allocate);
1603 __ push(r5);
1604 __ mov(r0, Operand(Smi::FromInt(size))); 1610 __ mov(r0, Operand(Smi::FromInt(size)));
1605 __ push(r0); 1611 __ Push(r5, r0);
1606 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); 1612 __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
1607 __ pop(r5); 1613 __ pop(r5);
1608 1614
1609 __ bind(&allocated); 1615 __ bind(&allocated);
1610 // After this, registers are used as follows: 1616 // After this, registers are used as follows:
1611 // r0: Newly allocated regexp. 1617 // r0: Newly allocated regexp.
1612 // r5: Materialized regexp. 1618 // r5: Materialized regexp.
1613 // r2: temp. 1619 // r2: temp.
1614 __ CopyFields(r0, r5, d0, size / kPointerSize); 1620 __ CopyFields(r0, r5, d0, size / kPointerSize);
1615 context()->Plug(r0); 1621 context()->Plug(r0);
1616 } 1622 }
1617 1623
1618 1624
1619 void FullCodeGenerator::EmitAccessor(Expression* expression) { 1625 void FullCodeGenerator::EmitAccessor(Expression* expression) {
1620 if (expression == NULL) { 1626 if (expression == NULL) {
1621 __ LoadRoot(r1, Heap::kNullValueRootIndex); 1627 __ LoadRoot(r1, Heap::kNullValueRootIndex);
1622 __ push(r1); 1628 __ push(r1);
1623 } else { 1629 } else {
1624 VisitForStackValue(expression); 1630 VisitForStackValue(expression);
1625 } 1631 }
1626 } 1632 }
1627 1633
1628 1634
1629 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 1635 void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1630 Comment cmnt(masm_, "[ ObjectLiteral"); 1636 Comment cmnt(masm_, "[ ObjectLiteral");
1637
1638 int depth = 1;
1639 expr->BuildConstantProperties(isolate(), &depth);
1631 Handle<FixedArray> constant_properties = expr->constant_properties(); 1640 Handle<FixedArray> constant_properties = expr->constant_properties();
1632 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1641 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1633 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 1642 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
1634 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 1643 __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
1635 __ mov(r1, Operand(constant_properties)); 1644 __ mov(r1, Operand(constant_properties));
1636 int flags = expr->fast_elements() 1645 int flags = expr->fast_elements()
1637 ? ObjectLiteral::kFastElements 1646 ? ObjectLiteral::kFastElements
1638 : ObjectLiteral::kNoFlags; 1647 : ObjectLiteral::kNoFlags;
1639 flags |= expr->has_function() 1648 flags |= expr->has_function()
1640 ? ObjectLiteral::kHasFunction 1649 ? ObjectLiteral::kHasFunction
1641 : ObjectLiteral::kNoFlags; 1650 : ObjectLiteral::kNoFlags;
1642 __ mov(r0, Operand(Smi::FromInt(flags))); 1651 __ mov(r0, Operand(Smi::FromInt(flags)));
1643 int properties_count = constant_properties->length() / 2; 1652 int properties_count = constant_properties->length() / 2;
1644 if ((FLAG_track_double_fields && expr->may_store_doubles()) || 1653 if ((FLAG_track_double_fields && expr->may_store_doubles()) ||
1645 expr->depth() > 1 || Serializer::enabled() || 1654 depth > 1 || Serializer::enabled() ||
1646 flags != ObjectLiteral::kFastElements || 1655 flags != ObjectLiteral::kFastElements ||
1647 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) { 1656 properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
1648 __ Push(r3, r2, r1, r0); 1657 __ Push(r3, r2, r1, r0);
1649 __ CallRuntime(Runtime::kCreateObjectLiteral, 4); 1658 __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
1650 } else { 1659 } else {
1651 FastCloneShallowObjectStub stub(properties_count); 1660 FastCloneShallowObjectStub stub(properties_count);
1652 __ CallStub(&stub); 1661 __ CallStub(&stub);
1653 } 1662 }
1654 1663
1655 // If result_saved is true the result is on top of the stack. If 1664 // 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
1754 context()->PlugTOS(); 1763 context()->PlugTOS();
1755 } else { 1764 } else {
1756 context()->Plug(r0); 1765 context()->Plug(r0);
1757 } 1766 }
1758 } 1767 }
1759 1768
1760 1769
1761 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 1770 void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1762 Comment cmnt(masm_, "[ ArrayLiteral"); 1771 Comment cmnt(masm_, "[ ArrayLiteral");
1763 1772
1773 int depth = 1;
1774 expr->BuildConstantElements(isolate(), &depth);
1764 ZoneList<Expression*>* subexprs = expr->values(); 1775 ZoneList<Expression*>* subexprs = expr->values();
1765 int length = subexprs->length(); 1776 int length = subexprs->length();
1766 Handle<FixedArray> constant_elements = expr->constant_elements(); 1777 Handle<FixedArray> constant_elements = expr->constant_elements();
1767 ASSERT_EQ(2, constant_elements->length()); 1778 ASSERT_EQ(2, constant_elements->length());
1768 ElementsKind constant_elements_kind = 1779 ElementsKind constant_elements_kind =
1769 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); 1780 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1770 bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind); 1781 bool has_fast_elements = IsFastObjectElementsKind(constant_elements_kind);
1771 Handle<FixedArrayBase> constant_elements_values( 1782 Handle<FixedArrayBase> constant_elements_values(
1772 FixedArrayBase::cast(constant_elements->get(1))); 1783 FixedArrayBase::cast(constant_elements->get(1)));
1773 1784
1774 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 1785 __ ldr(r3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
1775 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset)); 1786 __ ldr(r3, FieldMemOperand(r3, JSFunction::kLiteralsOffset));
1776 __ mov(r2, Operand(Smi::FromInt(expr->literal_index()))); 1787 __ mov(r2, Operand(Smi::FromInt(expr->literal_index())));
1777 __ mov(r1, Operand(constant_elements)); 1788 __ mov(r1, Operand(constant_elements));
1778 if (has_fast_elements && constant_elements_values->map() == 1789 if (has_fast_elements && constant_elements_values->map() ==
1779 isolate()->heap()->fixed_cow_array_map()) { 1790 isolate()->heap()->fixed_cow_array_map()) {
1780 FastCloneShallowArrayStub stub( 1791 FastCloneShallowArrayStub stub(
1781 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, 1792 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS,
1782 DONT_TRACK_ALLOCATION_SITE, 1793 DONT_TRACK_ALLOCATION_SITE,
1783 length); 1794 length);
1784 __ CallStub(&stub); 1795 __ CallStub(&stub);
1785 __ IncrementCounter( 1796 __ IncrementCounter(
1786 isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2); 1797 isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2);
1787 } else if (expr->depth() > 1) { 1798 } else if (depth > 1 || Serializer::enabled() ||
1799 length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1788 __ Push(r3, r2, r1); 1800 __ Push(r3, r2, r1);
1789 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); 1801 __ CallRuntime(Runtime::kCreateArrayLiteral, 3);
1790 } else if (Serializer::enabled() ||
1791 length > FastCloneShallowArrayStub::kMaximumClonedLength) {
1792 __ Push(r3, r2, r1);
1793 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3);
1794 } else { 1802 } else {
1795 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || 1803 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) ||
1796 FLAG_smi_only_arrays); 1804 FLAG_smi_only_arrays);
1797 FastCloneShallowArrayStub::Mode mode = 1805 FastCloneShallowArrayStub::Mode mode =
1798 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; 1806 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
1799 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites 1807 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites
1800 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE; 1808 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE;
1801 1809
1802 if (has_fast_elements) { 1810 if (has_fast_elements) {
1803 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; 1811 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS;
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
2032 Label l_next, l_call, l_loop; 2040 Label l_next, l_call, l_loop;
2033 // Initial send value is undefined. 2041 // Initial send value is undefined.
2034 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); 2042 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
2035 __ b(&l_next); 2043 __ b(&l_next);
2036 2044
2037 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } 2045 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
2038 __ bind(&l_catch); 2046 __ bind(&l_catch);
2039 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 2047 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
2040 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw" 2048 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw"
2041 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter 2049 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
2042 __ push(r3); // iter 2050 __ Push(r3, r0); // iter, exception
2043 __ push(r0); // exception
2044 __ jmp(&l_call); 2051 __ jmp(&l_call);
2045 2052
2046 // try { received = %yield result } 2053 // try { received = %yield result }
2047 // Shuffle the received result above a try handler and yield it without 2054 // Shuffle the received result above a try handler and yield it without
2048 // re-boxing. 2055 // re-boxing.
2049 __ bind(&l_try); 2056 __ bind(&l_try);
2050 __ pop(r0); // result 2057 __ pop(r0); // result
2051 __ PushTryHandler(StackHandler::CATCH, expr->index()); 2058 __ PushTryHandler(StackHandler::CATCH, expr->index());
2052 const int handler_size = StackHandlerConstants::kSize; 2059 const int handler_size = StackHandlerConstants::kSize;
2053 __ push(r0); // result 2060 __ push(r0); // result
(...skipping 15 matching lines...) Expand all
2069 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2076 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2070 __ pop(r0); // result 2077 __ pop(r0); // result
2071 EmitReturnSequence(); 2078 EmitReturnSequence();
2072 __ bind(&l_resume); // received in r0 2079 __ bind(&l_resume); // received in r0
2073 __ PopTryHandler(); 2080 __ PopTryHandler();
2074 2081
2075 // receiver = iter; f = 'next'; arg = received; 2082 // receiver = iter; f = 'next'; arg = received;
2076 __ bind(&l_next); 2083 __ bind(&l_next);
2077 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" 2084 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next"
2078 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter 2085 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter
2079 __ push(r3); // iter 2086 __ Push(r3, r0); // iter, received
2080 __ push(r0); // received
2081 2087
2082 // result = receiver[f](arg); 2088 // result = receiver[f](arg);
2083 __ bind(&l_call); 2089 __ bind(&l_call);
2084 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); 2090 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1);
2085 CallIC(ic); 2091 CallIC(ic);
2086 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2092 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2087 2093
2088 // if (!result.done) goto l_try; 2094 // if (!result.done) goto l_try;
2089 __ bind(&l_loop); 2095 __ bind(&l_loop);
2090 __ push(r0); // save result 2096 __ push(r0); // save result
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2146 __ push(r2); 2152 __ push(r2);
2147 __ jmp(&push_argument_holes); 2153 __ jmp(&push_argument_holes);
2148 2154
2149 // Enter a new JavaScript frame, and initialize its slots as they were when 2155 // Enter a new JavaScript frame, and initialize its slots as they were when
2150 // the generator was suspended. 2156 // the generator was suspended.
2151 Label resume_frame; 2157 Label resume_frame;
2152 __ bind(&push_frame); 2158 __ bind(&push_frame);
2153 __ bl(&resume_frame); 2159 __ bl(&resume_frame);
2154 __ jmp(&done); 2160 __ jmp(&done);
2155 __ bind(&resume_frame); 2161 __ bind(&resume_frame);
2156 __ push(lr); // Return address. 2162 // lr = return address.
2157 __ push(fp); // Caller's frame pointer. 2163 // fp = caller's frame pointer.
2158 __ mov(fp, sp); 2164 // cp = callee's context,
2159 __ push(cp); // Callee's context. 2165 // r4 = callee's JS function.
2160 __ push(r4); // Callee's JS Function. 2166 __ Push(lr, fp, cp, r4);
2167 // Adjust FP to point to saved FP.
2168 __ add(fp, sp, Operand(2 * kPointerSize));
2161 2169
2162 // Load the operand stack size. 2170 // Load the operand stack size.
2163 __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset)); 2171 __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset));
2164 __ ldr(r3, FieldMemOperand(r3, FixedArray::kLengthOffset)); 2172 __ ldr(r3, FieldMemOperand(r3, FixedArray::kLengthOffset));
2165 __ SmiUntag(r3); 2173 __ SmiUntag(r3);
2166 2174
2167 // If we are sending a value and there is no operand stack, we can jump back 2175 // If we are sending a value and there is no operand stack, we can jump back
2168 // in directly. 2176 // in directly.
2169 if (resume_mode == JSGeneratorObject::NEXT) { 2177 if (resume_mode == JSGeneratorObject::NEXT) {
2170 Label slow_resume; 2178 Label slow_resume;
(...skipping 11 matching lines...) Expand all
2182 2190
2183 // Otherwise, we push holes for the operand stack and call the runtime to fix 2191 // Otherwise, we push holes for the operand stack and call the runtime to fix
2184 // up the stack and the handlers. 2192 // up the stack and the handlers.
2185 Label push_operand_holes, call_resume; 2193 Label push_operand_holes, call_resume;
2186 __ bind(&push_operand_holes); 2194 __ bind(&push_operand_holes);
2187 __ sub(r3, r3, Operand(1), SetCC); 2195 __ sub(r3, r3, Operand(1), SetCC);
2188 __ b(mi, &call_resume); 2196 __ b(mi, &call_resume);
2189 __ push(r2); 2197 __ push(r2);
2190 __ b(&push_operand_holes); 2198 __ b(&push_operand_holes);
2191 __ bind(&call_resume); 2199 __ bind(&call_resume);
2192 __ push(r1); 2200 ASSERT(!result_register().is(r1));
2193 __ push(result_register()); 2201 __ Push(r1, result_register());
2194 __ Push(Smi::FromInt(resume_mode)); 2202 __ Push(Smi::FromInt(resume_mode));
2195 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); 2203 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
2196 // Not reached: the runtime call returns elsewhere. 2204 // Not reached: the runtime call returns elsewhere.
2197 __ stop("not-reached"); 2205 __ stop("not-reached");
2198 2206
2199 // Throw error if we attempt to operate on a running generator. 2207 // Throw error if we attempt to operate on a running generator.
2200 __ bind(&wrong_state); 2208 __ bind(&wrong_state);
2201 __ push(r1); 2209 __ push(r1);
2202 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); 2210 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
2203 2211
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
2405 ? isolate()->builtins()->StoreIC_Initialize() 2413 ? isolate()->builtins()->StoreIC_Initialize()
2406 : isolate()->builtins()->StoreIC_Initialize_Strict(); 2414 : isolate()->builtins()->StoreIC_Initialize_Strict();
2407 CallIC(ic); 2415 CallIC(ic);
2408 break; 2416 break;
2409 } 2417 }
2410 case KEYED_PROPERTY: { 2418 case KEYED_PROPERTY: {
2411 __ push(r0); // Preserve value. 2419 __ push(r0); // Preserve value.
2412 VisitForStackValue(prop->obj()); 2420 VisitForStackValue(prop->obj());
2413 VisitForAccumulatorValue(prop->key()); 2421 VisitForAccumulatorValue(prop->key());
2414 __ mov(r1, r0); 2422 __ mov(r1, r0);
2415 __ pop(r2); 2423 __ Pop(r0, r2); // r0 = restored value.
2416 __ pop(r0); // Restore value.
2417 Handle<Code> ic = is_classic_mode() 2424 Handle<Code> ic = is_classic_mode()
2418 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2425 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2419 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2426 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2420 CallIC(ic); 2427 CallIC(ic);
2421 break; 2428 break;
2422 } 2429 }
2423 } 2430 }
2424 context()->Plug(r0); 2431 context()->Plug(r0);
2425 } 2432 }
2426 2433
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
2540 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2547 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2541 context()->Plug(r0); 2548 context()->Plug(r0);
2542 } 2549 }
2543 2550
2544 2551
2545 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2552 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2546 // Assignment to a property, using a keyed store IC. 2553 // Assignment to a property, using a keyed store IC.
2547 2554
2548 // Record source code position before IC call. 2555 // Record source code position before IC call.
2549 SetSourcePosition(expr->position()); 2556 SetSourcePosition(expr->position());
2550 __ pop(r1); // Key. 2557 __ Pop(r2, r1); // r1 = key.
2551 __ pop(r2);
2552 2558
2553 Handle<Code> ic = is_classic_mode() 2559 Handle<Code> ic = is_classic_mode()
2554 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2560 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2555 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2561 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2556 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); 2562 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
2557 2563
2558 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2564 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2559 context()->Plug(r0); 2565 context()->Plug(r0);
2560 } 2566 }
2561 2567
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
2670 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2676 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2671 __ CallStub(&stub, expr->CallFeedbackId()); 2677 __ CallStub(&stub, expr->CallFeedbackId());
2672 RecordJSReturnSite(expr); 2678 RecordJSReturnSite(expr);
2673 // Restore context register. 2679 // Restore context register.
2674 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2680 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2675 context()->DropAndPlug(1, r0); 2681 context()->DropAndPlug(1, r0);
2676 } 2682 }
2677 2683
2678 2684
2679 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2685 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2680 // Push copy of the first argument or undefined if it doesn't exist. 2686 // r4: copy of the first argument or undefined if it doesn't exist.
2681 if (arg_count > 0) { 2687 if (arg_count > 0) {
2682 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); 2688 __ ldr(r4, MemOperand(sp, arg_count * kPointerSize));
2683 } else { 2689 } else {
2684 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); 2690 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex);
2685 } 2691 }
2686 __ push(r1);
2687 2692
2688 // Push the receiver of the enclosing function. 2693 // r3: the receiver of the enclosing function.
2689 int receiver_offset = 2 + info_->scope()->num_parameters(); 2694 int receiver_offset = 2 + info_->scope()->num_parameters();
2690 __ ldr(r1, MemOperand(fp, receiver_offset * kPointerSize)); 2695 __ ldr(r3, MemOperand(fp, receiver_offset * kPointerSize));
2691 __ push(r1);
2692 // Push the language mode.
2693 __ mov(r1, Operand(Smi::FromInt(language_mode())));
2694 __ push(r1);
2695 2696
2696 // Push the start position of the scope the calls resides in. 2697 // r2: the language mode.
2698 __ mov(r2, Operand(Smi::FromInt(language_mode())));
2699
2700 // r1: the start position of the scope the calls resides in.
2697 __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); 2701 __ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
2698 __ push(r1);
2699 2702
2700 // Do the runtime call. 2703 // Do the runtime call.
2704 __ Push(r4, r3, r2, r1);
2701 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); 2705 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2702 } 2706 }
2703 2707
2704 2708
2705 void FullCodeGenerator::VisitCall(Call* expr) { 2709 void FullCodeGenerator::VisitCall(Call* expr) {
2706 #ifdef DEBUG 2710 #ifdef DEBUG
2707 // We want to verify that RecordJSReturnSite gets called on all paths 2711 // We want to verify that RecordJSReturnSite gets called on all paths
2708 // through this function. Avoid early returns. 2712 // through this function. Avoid early returns.
2709 expr->return_is_recorded_ = false; 2713 expr->return_is_recorded_ = false;
2710 #endif 2714 #endif
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2764 2768
2765 { PreservePositionScope scope(masm()->positions_recorder()); 2769 { PreservePositionScope scope(masm()->positions_recorder());
2766 // Generate code for loading from variables potentially shadowed 2770 // Generate code for loading from variables potentially shadowed
2767 // by eval-introduced variables. 2771 // by eval-introduced variables.
2768 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 2772 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2769 } 2773 }
2770 2774
2771 __ bind(&slow); 2775 __ bind(&slow);
2772 // Call the runtime to find the function to call (returned in r0) 2776 // Call the runtime to find the function to call (returned in r0)
2773 // and the object holding it (returned in edx). 2777 // and the object holding it (returned in edx).
2774 __ push(context_register()); 2778 ASSERT(!context_register().is(r2));
2775 __ mov(r2, Operand(proxy->name())); 2779 __ mov(r2, Operand(proxy->name()));
2776 __ push(r2); 2780 __ Push(context_register(), r2);
2777 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2781 __ CallRuntime(Runtime::kLoadContextSlot, 2);
2778 __ Push(r0, r1); // Function, receiver. 2782 __ Push(r0, r1); // Function, receiver.
2779 2783
2780 // If fast case code has been generated, emit code to push the 2784 // If fast case code has been generated, emit code to push the
2781 // function and receiver and have the slow path jump around this 2785 // function and receiver and have the slow path jump around this
2782 // code. 2786 // code.
2783 if (done.is_linked()) { 2787 if (done.is_linked()) {
2784 Label call; 2788 Label call;
2785 __ b(&call); 2789 __ b(&call);
2786 __ bind(&done); 2790 __ bind(&done);
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
3093 3097
3094 __ JumpIfSmi(r0, if_false); 3098 __ JumpIfSmi(r0, if_false);
3095 __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE); 3099 __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
3096 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 3100 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3097 Split(eq, if_true, if_false, fall_through); 3101 Split(eq, if_true, if_false, fall_through);
3098 3102
3099 context()->Plug(if_true, if_false); 3103 context()->Plug(if_true, if_false);
3100 } 3104 }
3101 3105
3102 3106
3107 void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
3108 ZoneList<Expression*>* args = expr->arguments();
3109 ASSERT(args->length() == 1);
3110
3111 VisitForAccumulatorValue(args->at(0));
3112
3113 Label materialize_true, materialize_false;
3114 Label* if_true = NULL;
3115 Label* if_false = NULL;
3116 Label* fall_through = NULL;
3117 context()->PrepareTest(&materialize_true, &materialize_false,
3118 &if_true, &if_false, &fall_through);
3119
3120 __ CheckMap(r0, r1, Heap::kHeapNumberMapRootIndex, if_false, DO_SMI_CHECK);
3121 __ ldr(r2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
3122 __ ldr(r1, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
3123 __ cmp(r2, Operand(0x80000000));
3124 __ cmp(r1, Operand(0x00000000), eq);
3125
3126 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3127 Split(eq, if_true, if_false, fall_through);
3128
3129 context()->Plug(if_true, if_false);
3130 }
3131
3132
3103 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) { 3133 void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
3104 ZoneList<Expression*>* args = expr->arguments(); 3134 ZoneList<Expression*>* args = expr->arguments();
3105 ASSERT(args->length() == 1); 3135 ASSERT(args->length() == 1);
3106 3136
3107 VisitForAccumulatorValue(args->at(0)); 3137 VisitForAccumulatorValue(args->at(0));
3108 3138
3109 Label materialize_true, materialize_false; 3139 Label materialize_true, materialize_false;
3110 Label* if_true = NULL; 3140 Label* if_true = NULL;
3111 Label* if_false = NULL; 3141 Label* if_false = NULL;
3112 Label* fall_through = NULL; 3142 Label* fall_through = NULL;
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
3483 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { 3513 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3484 ZoneList<Expression*>* args = expr->arguments(); 3514 ZoneList<Expression*>* args = expr->arguments();
3485 ASSERT_EQ(3, args->length()); 3515 ASSERT_EQ(3, args->length());
3486 3516
3487 Register string = r0; 3517 Register string = r0;
3488 Register index = r1; 3518 Register index = r1;
3489 Register value = r2; 3519 Register value = r2;
3490 3520
3491 VisitForStackValue(args->at(1)); // index 3521 VisitForStackValue(args->at(1)); // index
3492 VisitForStackValue(args->at(2)); // value 3522 VisitForStackValue(args->at(2)); // value
3493 __ pop(value); 3523 __ Pop(index, value);
3494 __ pop(index);
3495 VisitForAccumulatorValue(args->at(0)); // string 3524 VisitForAccumulatorValue(args->at(0)); // string
3496 3525
3497 if (FLAG_debug_code) { 3526 if (FLAG_debug_code) {
3498 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 3527 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
3499 EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); 3528 EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
3500 } 3529 }
3501 3530
3502 __ SmiUntag(value, value); 3531 __ SmiUntag(value, value);
3503 __ add(ip, 3532 __ add(ip,
3504 string, 3533 string,
3505 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 3534 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
3506 __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize)); 3535 __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize));
3507 context()->Plug(string); 3536 context()->Plug(string);
3508 } 3537 }
3509 3538
3510 3539
3511 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { 3540 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
3512 ZoneList<Expression*>* args = expr->arguments(); 3541 ZoneList<Expression*>* args = expr->arguments();
3513 ASSERT_EQ(3, args->length()); 3542 ASSERT_EQ(3, args->length());
3514 3543
3515 Register string = r0; 3544 Register string = r0;
3516 Register index = r1; 3545 Register index = r1;
3517 Register value = r2; 3546 Register value = r2;
3518 3547
3519 VisitForStackValue(args->at(1)); // index 3548 VisitForStackValue(args->at(1)); // index
3520 VisitForStackValue(args->at(2)); // value 3549 VisitForStackValue(args->at(2)); // value
3521 __ pop(value); 3550 __ Pop(index, value);
3522 __ pop(index);
3523 VisitForAccumulatorValue(args->at(0)); // string 3551 VisitForAccumulatorValue(args->at(0)); // string
3524 3552
3525 if (FLAG_debug_code) { 3553 if (FLAG_debug_code) {
3526 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 3554 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
3527 EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); 3555 EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
3528 } 3556 }
3529 3557
3530 __ SmiUntag(value, value); 3558 __ SmiUntag(value, value);
3531 __ add(ip, 3559 __ add(ip,
3532 string, 3560 string,
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
3696 generator.GenerateSlow(masm_, call_helper); 3724 generator.GenerateSlow(masm_, call_helper);
3697 3725
3698 __ bind(&done); 3726 __ bind(&done);
3699 context()->Plug(result); 3727 context()->Plug(result);
3700 } 3728 }
3701 3729
3702 3730
3703 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 3731 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3704 ZoneList<Expression*>* args = expr->arguments(); 3732 ZoneList<Expression*>* args = expr->arguments();
3705 ASSERT_EQ(2, args->length()); 3733 ASSERT_EQ(2, args->length());
3706 VisitForStackValue(args->at(0));
3707 VisitForStackValue(args->at(1));
3708 3734
3709 StringAddStub stub(STRING_ADD_CHECK_BOTH); 3735 if (FLAG_new_string_add) {
3710 __ CallStub(&stub); 3736 VisitForStackValue(args->at(0));
3737 VisitForAccumulatorValue(args->at(1));
3738
3739 __ pop(r1);
3740 NewStringAddStub stub(STRING_ADD_CHECK_BOTH, NOT_TENURED);
3741 __ CallStub(&stub);
3742 } else {
3743 VisitForStackValue(args->at(0));
3744 VisitForStackValue(args->at(1));
3745
3746 StringAddStub stub(STRING_ADD_CHECK_BOTH);
3747 __ CallStub(&stub);
3748 }
3711 context()->Plug(r0); 3749 context()->Plug(r0);
3712 } 3750 }
3713 3751
3714 3752
3715 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 3753 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3716 ZoneList<Expression*>* args = expr->arguments(); 3754 ZoneList<Expression*>* args = expr->arguments();
3717 ASSERT_EQ(2, args->length()); 3755 ASSERT_EQ(2, args->length());
3718 VisitForStackValue(args->at(0)); 3756 VisitForStackValue(args->at(0));
3719 VisitForStackValue(args->at(1)); 3757 VisitForStackValue(args->at(1));
3720 3758
3721 StringCompareStub stub; 3759 StringCompareStub stub;
3722 __ CallStub(&stub); 3760 __ CallStub(&stub);
3723 context()->Plug(r0); 3761 context()->Plug(r0);
3724 } 3762 }
3725 3763
3726 3764
3727 void FullCodeGenerator::EmitMathSin(CallRuntime* expr) {
3728 // Load the argument on the stack and call the stub.
3729 TranscendentalCacheStub stub(TranscendentalCache::SIN,
3730 TranscendentalCacheStub::TAGGED);
3731 ZoneList<Expression*>* args = expr->arguments();
3732 ASSERT(args->length() == 1);
3733 VisitForStackValue(args->at(0));
3734 __ CallStub(&stub);
3735 context()->Plug(r0);
3736 }
3737
3738
3739 void FullCodeGenerator::EmitMathCos(CallRuntime* expr) {
3740 // Load the argument on the stack and call the stub.
3741 TranscendentalCacheStub stub(TranscendentalCache::COS,
3742 TranscendentalCacheStub::TAGGED);
3743 ZoneList<Expression*>* args = expr->arguments();
3744 ASSERT(args->length() == 1);
3745 VisitForStackValue(args->at(0));
3746 __ CallStub(&stub);
3747 context()->Plug(r0);
3748 }
3749
3750
3751 void FullCodeGenerator::EmitMathTan(CallRuntime* expr) {
3752 // Load the argument on the stack and call the stub.
3753 TranscendentalCacheStub stub(TranscendentalCache::TAN,
3754 TranscendentalCacheStub::TAGGED);
3755 ZoneList<Expression*>* args = expr->arguments();
3756 ASSERT(args->length() == 1);
3757 VisitForStackValue(args->at(0));
3758 __ CallStub(&stub);
3759 context()->Plug(r0);
3760 }
3761
3762
3763 void FullCodeGenerator::EmitMathLog(CallRuntime* expr) { 3765 void FullCodeGenerator::EmitMathLog(CallRuntime* expr) {
3764 // Load the argument on the stack and call the stub. 3766 // Load the argument on the stack and call the stub.
3765 TranscendentalCacheStub stub(TranscendentalCache::LOG, 3767 TranscendentalCacheStub stub(TranscendentalCache::LOG,
3766 TranscendentalCacheStub::TAGGED); 3768 TranscendentalCacheStub::TAGGED);
3767 ZoneList<Expression*>* args = expr->arguments(); 3769 ZoneList<Expression*>* args = expr->arguments();
3768 ASSERT(args->length() == 1); 3770 ASSERT(args->length() == 1);
3769 VisitForStackValue(args->at(0)); 3771 VisitForStackValue(args->at(0));
3770 __ CallStub(&stub); 3772 __ CallStub(&stub);
3771 context()->Plug(r0); 3773 context()->Plug(r0);
3772 } 3774 }
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
4256 __ Push(r2, r1, r0); 4258 __ Push(r2, r1, r0);
4257 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 4259 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
4258 context()->Plug(r0); 4260 context()->Plug(r0);
4259 } else if (var->IsStackAllocated() || var->IsContextSlot()) { 4261 } else if (var->IsStackAllocated() || var->IsContextSlot()) {
4260 // Result of deleting non-global, non-dynamic variables is false. 4262 // Result of deleting non-global, non-dynamic variables is false.
4261 // The subexpression does not have side effects. 4263 // The subexpression does not have side effects.
4262 context()->Plug(var->is_this()); 4264 context()->Plug(var->is_this());
4263 } else { 4265 } else {
4264 // Non-global variable. Call the runtime to try to delete from the 4266 // Non-global variable. Call the runtime to try to delete from the
4265 // context where the variable was introduced. 4267 // context where the variable was introduced.
4266 __ push(context_register()); 4268 ASSERT(!context_register().is(r2));
4267 __ mov(r2, Operand(var->name())); 4269 __ mov(r2, Operand(var->name()));
4268 __ push(r2); 4270 __ Push(context_register(), r2);
4269 __ CallRuntime(Runtime::kDeleteContextSlot, 2); 4271 __ CallRuntime(Runtime::kDeleteContextSlot, 2);
4270 context()->Plug(r0); 4272 context()->Plug(r0);
4271 } 4273 }
4272 } else { 4274 } else {
4273 // Result of deleting non-property, non-variable reference is true. 4275 // Result of deleting non-property, non-variable reference is true.
4274 // The subexpression may have side effects. 4276 // The subexpression may have side effects.
4275 VisitForEffect(expr->expression()); 4277 VisitForEffect(expr->expression());
4276 context()->Plug(true); 4278 context()->Plug(true);
4277 } 4279 }
4278 break; 4280 break;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
4389 } 4391 }
4390 4392
4391 // We need a second deoptimization point after loading the value 4393 // We need a second deoptimization point after loading the value
4392 // in case evaluating the property load my have a side effect. 4394 // in case evaluating the property load my have a side effect.
4393 if (assign_type == VARIABLE) { 4395 if (assign_type == VARIABLE) {
4394 PrepareForBailout(expr->expression(), TOS_REG); 4396 PrepareForBailout(expr->expression(), TOS_REG);
4395 } else { 4397 } else {
4396 PrepareForBailoutForId(prop->LoadId(), TOS_REG); 4398 PrepareForBailoutForId(prop->LoadId(), TOS_REG);
4397 } 4399 }
4398 4400
4399 // Call ToNumber only if operand is not a smi. 4401 // Inline smi case if we are in a loop.
4400 Label no_conversion; 4402 Label stub_call, done;
4403 JumpPatchSite patch_site(masm_);
4404
4405 int count_value = expr->op() == Token::INC ? 1 : -1;
4401 if (ShouldInlineSmiCase(expr->op())) { 4406 if (ShouldInlineSmiCase(expr->op())) {
4402 __ JumpIfSmi(r0, &no_conversion); 4407 Label slow;
4408 patch_site.EmitJumpIfNotSmi(r0, &slow);
4409
4410 // Save result for postfix expressions.
4411 if (expr->is_postfix()) {
4412 if (!context()->IsEffect()) {
4413 // Save the result on the stack. If we have a named or keyed property
4414 // we store the result under the receiver that is currently on top
4415 // of the stack.
4416 switch (assign_type) {
4417 case VARIABLE:
4418 __ push(r0);
4419 break;
4420 case NAMED_PROPERTY:
4421 __ str(r0, MemOperand(sp, kPointerSize));
4422 break;
4423 case KEYED_PROPERTY:
4424 __ str(r0, MemOperand(sp, 2 * kPointerSize));
4425 break;
4426 }
4427 }
4428 }
4429
4430 __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
4431 __ b(vc, &done);
4432 // Call stub. Undo operation first.
4433 __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
4434 __ jmp(&stub_call);
4435 __ bind(&slow);
4403 } 4436 }
4404 ToNumberStub convert_stub; 4437 ToNumberStub convert_stub;
4405 __ CallStub(&convert_stub); 4438 __ CallStub(&convert_stub);
4406 __ bind(&no_conversion);
4407 4439
4408 // Save result for postfix expressions. 4440 // Save result for postfix expressions.
4409 if (expr->is_postfix()) { 4441 if (expr->is_postfix()) {
4410 if (!context()->IsEffect()) { 4442 if (!context()->IsEffect()) {
4411 // Save the result on the stack. If we have a named or keyed property 4443 // Save the result on the stack. If we have a named or keyed property
4412 // we store the result under the receiver that is currently on top 4444 // we store the result under the receiver that is currently on top
4413 // of the stack. 4445 // of the stack.
4414 switch (assign_type) { 4446 switch (assign_type) {
4415 case VARIABLE: 4447 case VARIABLE:
4416 __ push(r0); 4448 __ push(r0);
4417 break; 4449 break;
4418 case NAMED_PROPERTY: 4450 case NAMED_PROPERTY:
4419 __ str(r0, MemOperand(sp, kPointerSize)); 4451 __ str(r0, MemOperand(sp, kPointerSize));
4420 break; 4452 break;
4421 case KEYED_PROPERTY: 4453 case KEYED_PROPERTY:
4422 __ str(r0, MemOperand(sp, 2 * kPointerSize)); 4454 __ str(r0, MemOperand(sp, 2 * kPointerSize));
4423 break; 4455 break;
4424 } 4456 }
4425 } 4457 }
4426 } 4458 }
4427 4459
4428 4460
4429 // Inline smi case if we are in a loop. 4461 __ bind(&stub_call);
4430 Label stub_call, done;
4431 JumpPatchSite patch_site(masm_);
4432
4433 int count_value = expr->op() == Token::INC ? 1 : -1;
4434 if (ShouldInlineSmiCase(expr->op())) {
4435 __ add(r0, r0, Operand(Smi::FromInt(count_value)), SetCC);
4436 __ b(vs, &stub_call);
4437 // We could eliminate this smi check if we split the code at
4438 // the first smi check before calling ToNumber.
4439 patch_site.EmitJumpIfSmi(r0, &done);
4440
4441 __ bind(&stub_call);
4442 // Call stub. Undo operation first.
4443 __ sub(r0, r0, Operand(Smi::FromInt(count_value)));
4444 }
4445 __ mov(r1, r0); 4462 __ mov(r1, r0);
4446 __ mov(r0, Operand(Smi::FromInt(count_value))); 4463 __ mov(r0, Operand(Smi::FromInt(count_value)));
4447 4464
4448 // Record position before stub call. 4465 // Record position before stub call.
4449 SetSourcePosition(expr->position()); 4466 SetSourcePosition(expr->position());
4450 4467
4451 BinaryOpStub stub(Token::ADD, NO_OVERWRITE); 4468 BinaryOpStub stub(Token::ADD, NO_OVERWRITE);
4452 CallIC(stub.GetCode(isolate()), 4469 CallIC(stub.GetCode(isolate()),
4453 RelocInfo::CODE_TARGET, 4470 RelocInfo::CODE_TARGET,
4454 expr->CountBinOpFeedbackId()); 4471 expr->CountBinOpFeedbackId());
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4488 if (expr->is_postfix()) { 4505 if (expr->is_postfix()) {
4489 if (!context()->IsEffect()) { 4506 if (!context()->IsEffect()) {
4490 context()->PlugTOS(); 4507 context()->PlugTOS();
4491 } 4508 }
4492 } else { 4509 } else {
4493 context()->Plug(r0); 4510 context()->Plug(r0);
4494 } 4511 }
4495 break; 4512 break;
4496 } 4513 }
4497 case KEYED_PROPERTY: { 4514 case KEYED_PROPERTY: {
4498 __ pop(r1); // Key. 4515 __ Pop(r2, r1); // r1 = key. r2 = receiver.
4499 __ pop(r2); // Receiver.
4500 Handle<Code> ic = is_classic_mode() 4516 Handle<Code> ic = is_classic_mode()
4501 ? isolate()->builtins()->KeyedStoreIC_Initialize() 4517 ? isolate()->builtins()->KeyedStoreIC_Initialize()
4502 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 4518 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
4503 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); 4519 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
4504 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4520 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4505 if (expr->is_postfix()) { 4521 if (expr->is_postfix()) {
4506 if (!context()->IsEffect()) { 4522 if (!context()->IsEffect()) {
4507 context()->PlugTOS(); 4523 context()->PlugTOS();
4508 } 4524 }
4509 } else { 4525 } else {
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
4962 ASSERT(Memory::uint32_at(interrupt_address_pointer) == 4978 ASSERT(Memory::uint32_at(interrupt_address_pointer) ==
4963 reinterpret_cast<uint32_t>( 4979 reinterpret_cast<uint32_t>(
4964 isolate->builtins()->OsrAfterStackCheck()->entry())); 4980 isolate->builtins()->OsrAfterStackCheck()->entry()));
4965 return OSR_AFTER_STACK_CHECK; 4981 return OSR_AFTER_STACK_CHECK;
4966 } 4982 }
4967 4983
4968 4984
4969 } } // namespace v8::internal 4985 } } // namespace v8::internal
4970 4986
4971 #endif // V8_TARGET_ARCH_ARM 4987 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/deoptimizer-arm.cc ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698