| 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); |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1786 __ li(a1, Operand(constant_elements)); | 1796 __ li(a1, Operand(constant_elements)); |
| 1787 if (has_fast_elements && constant_elements_values->map() == | 1797 if (has_fast_elements && constant_elements_values->map() == |
| 1788 isolate()->heap()->fixed_cow_array_map()) { | 1798 isolate()->heap()->fixed_cow_array_map()) { |
| 1789 FastCloneShallowArrayStub stub( | 1799 FastCloneShallowArrayStub stub( |
| 1790 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, | 1800 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, |
| 1791 DONT_TRACK_ALLOCATION_SITE, | 1801 DONT_TRACK_ALLOCATION_SITE, |
| 1792 length); | 1802 length); |
| 1793 __ CallStub(&stub); | 1803 __ CallStub(&stub); |
| 1794 __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), | 1804 __ IncrementCounter(isolate()->counters()->cow_arrays_created_stub(), |
| 1795 1, a1, a2); | 1805 1, a1, a2); |
| 1796 } else if (expr->depth() > 1) { | 1806 } else if (expr->depth() > 1 || |
| 1807 Serializer::enabled() || |
| 1808 length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
| 1797 __ Push(a3, a2, a1); | 1809 __ Push(a3, a2, a1); |
| 1798 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 1810 __ 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 { | 1811 } else { |
| 1804 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || | 1812 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || |
| 1805 FLAG_smi_only_arrays); | 1813 FLAG_smi_only_arrays); |
| 1806 FastCloneShallowArrayStub::Mode mode = | 1814 FastCloneShallowArrayStub::Mode mode = |
| 1807 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; | 1815 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; |
| 1808 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites | 1816 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites |
| 1809 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE; | 1817 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE; |
| 1810 | 1818 |
| 1811 if (has_fast_elements) { | 1819 if (has_fast_elements) { |
| 1812 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; | 1820 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2043 // Initial send value is undefined. | 2051 // Initial send value is undefined. |
| 2044 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 2052 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); |
| 2045 __ Branch(&l_next); | 2053 __ Branch(&l_next); |
| 2046 | 2054 |
| 2047 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 2055 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
| 2048 __ bind(&l_catch); | 2056 __ bind(&l_catch); |
| 2049 __ mov(a0, v0); | 2057 __ mov(a0, v0); |
| 2050 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 2058 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
| 2051 __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw" | 2059 __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw" |
| 2052 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter | 2060 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter |
| 2053 __ push(a3); // iter | 2061 __ Push(a3, a0); // iter, exception |
| 2054 __ push(a0); // exception | |
| 2055 __ jmp(&l_call); | 2062 __ jmp(&l_call); |
| 2056 | 2063 |
| 2057 // try { received = %yield result } | 2064 // try { received = %yield result } |
| 2058 // Shuffle the received result above a try handler and yield it without | 2065 // Shuffle the received result above a try handler and yield it without |
| 2059 // re-boxing. | 2066 // re-boxing. |
| 2060 __ bind(&l_try); | 2067 __ bind(&l_try); |
| 2061 __ pop(a0); // result | 2068 __ pop(a0); // result |
| 2062 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2069 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
| 2063 const int handler_size = StackHandlerConstants::kSize; | 2070 const int handler_size = StackHandlerConstants::kSize; |
| 2064 __ push(a0); // result | 2071 __ push(a0); // result |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2082 __ pop(v0); // result | 2089 __ pop(v0); // result |
| 2083 EmitReturnSequence(); | 2090 EmitReturnSequence(); |
| 2084 __ mov(a0, v0); | 2091 __ mov(a0, v0); |
| 2085 __ bind(&l_resume); // received in a0 | 2092 __ bind(&l_resume); // received in a0 |
| 2086 __ PopTryHandler(); | 2093 __ PopTryHandler(); |
| 2087 | 2094 |
| 2088 // receiver = iter; f = 'next'; arg = received; | 2095 // receiver = iter; f = 'next'; arg = received; |
| 2089 __ bind(&l_next); | 2096 __ bind(&l_next); |
| 2090 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" | 2097 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" |
| 2091 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter | 2098 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter |
| 2092 __ push(a3); // iter | 2099 __ Push(a3, a0); // iter, received |
| 2093 __ push(a0); // received | |
| 2094 | 2100 |
| 2095 // result = receiver[f](arg); | 2101 // result = receiver[f](arg); |
| 2096 __ bind(&l_call); | 2102 __ bind(&l_call); |
| 2097 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2103 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); |
| 2098 CallIC(ic); | 2104 CallIC(ic); |
| 2099 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2105 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2100 | 2106 |
| 2101 // if (!result.done) goto l_try; | 2107 // if (!result.done) goto l_try; |
| 2102 __ bind(&l_loop); | 2108 __ bind(&l_loop); |
| 2103 __ mov(a0, v0); | 2109 __ mov(a0, v0); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2159 __ push(a2); | 2165 __ push(a2); |
| 2160 __ jmp(&push_argument_holes); | 2166 __ jmp(&push_argument_holes); |
| 2161 | 2167 |
| 2162 // Enter a new JavaScript frame, and initialize its slots as they were when | 2168 // Enter a new JavaScript frame, and initialize its slots as they were when |
| 2163 // the generator was suspended. | 2169 // the generator was suspended. |
| 2164 Label resume_frame; | 2170 Label resume_frame; |
| 2165 __ bind(&push_frame); | 2171 __ bind(&push_frame); |
| 2166 __ Call(&resume_frame); | 2172 __ Call(&resume_frame); |
| 2167 __ jmp(&done); | 2173 __ jmp(&done); |
| 2168 __ bind(&resume_frame); | 2174 __ bind(&resume_frame); |
| 2169 __ push(ra); // Return address. | 2175 // ra = return address. |
| 2170 __ push(fp); // Caller's frame pointer. | 2176 // fp = caller's frame pointer. |
| 2171 __ mov(fp, sp); | 2177 // cp = callee's context, |
| 2172 __ push(cp); // Callee's context. | 2178 // t0 = callee's JS function. |
| 2173 __ push(t0); // Callee's JS Function. | 2179 __ Push(ra, fp, cp, t0); |
| 2180 // Adjust FP to point to saved FP. |
| 2181 __ Addu(fp, sp, 2 * kPointerSize); |
| 2174 | 2182 |
| 2175 // Load the operand stack size. | 2183 // Load the operand stack size. |
| 2176 __ lw(a3, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset)); | 2184 __ lw(a3, FieldMemOperand(a1, JSGeneratorObject::kOperandStackOffset)); |
| 2177 __ lw(a3, FieldMemOperand(a3, FixedArray::kLengthOffset)); | 2185 __ lw(a3, FieldMemOperand(a3, FixedArray::kLengthOffset)); |
| 2178 __ SmiUntag(a3); | 2186 __ SmiUntag(a3); |
| 2179 | 2187 |
| 2180 // If we are sending a value and there is no operand stack, we can jump back | 2188 // If we are sending a value and there is no operand stack, we can jump back |
| 2181 // in directly. | 2189 // in directly. |
| 2182 if (resume_mode == JSGeneratorObject::NEXT) { | 2190 if (resume_mode == JSGeneratorObject::NEXT) { |
| 2183 Label slow_resume; | 2191 Label slow_resume; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2194 | 2202 |
| 2195 // Otherwise, we push holes for the operand stack and call the runtime to fix | 2203 // Otherwise, we push holes for the operand stack and call the runtime to fix |
| 2196 // up the stack and the handlers. | 2204 // up the stack and the handlers. |
| 2197 Label push_operand_holes, call_resume; | 2205 Label push_operand_holes, call_resume; |
| 2198 __ bind(&push_operand_holes); | 2206 __ bind(&push_operand_holes); |
| 2199 __ Subu(a3, a3, Operand(1)); | 2207 __ Subu(a3, a3, Operand(1)); |
| 2200 __ Branch(&call_resume, lt, a3, Operand(zero_reg)); | 2208 __ Branch(&call_resume, lt, a3, Operand(zero_reg)); |
| 2201 __ push(a2); | 2209 __ push(a2); |
| 2202 __ Branch(&push_operand_holes); | 2210 __ Branch(&push_operand_holes); |
| 2203 __ bind(&call_resume); | 2211 __ bind(&call_resume); |
| 2204 __ push(a1); | 2212 ASSERT(!result_register().is(a1)); |
| 2205 __ push(result_register()); | 2213 __ Push(a1, result_register()); |
| 2206 __ Push(Smi::FromInt(resume_mode)); | 2214 __ Push(Smi::FromInt(resume_mode)); |
| 2207 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2215 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
| 2208 // Not reached: the runtime call returns elsewhere. | 2216 // Not reached: the runtime call returns elsewhere. |
| 2209 __ stop("not-reached"); | 2217 __ stop("not-reached"); |
| 2210 | 2218 |
| 2211 // Throw error if we attempt to operate on a running generator. | 2219 // Throw error if we attempt to operate on a running generator. |
| 2212 __ bind(&wrong_state); | 2220 __ bind(&wrong_state); |
| 2213 __ push(a1); | 2221 __ push(a1); |
| 2214 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); | 2222 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
| 2215 | 2223 |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2425 ? isolate()->builtins()->StoreIC_Initialize() | 2433 ? isolate()->builtins()->StoreIC_Initialize() |
| 2426 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2434 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
| 2427 CallIC(ic); | 2435 CallIC(ic); |
| 2428 break; | 2436 break; |
| 2429 } | 2437 } |
| 2430 case KEYED_PROPERTY: { | 2438 case KEYED_PROPERTY: { |
| 2431 __ push(result_register()); // Preserve value. | 2439 __ push(result_register()); // Preserve value. |
| 2432 VisitForStackValue(prop->obj()); | 2440 VisitForStackValue(prop->obj()); |
| 2433 VisitForAccumulatorValue(prop->key()); | 2441 VisitForAccumulatorValue(prop->key()); |
| 2434 __ mov(a1, result_register()); | 2442 __ mov(a1, result_register()); |
| 2435 __ pop(a2); | 2443 __ Pop(a0, a2); // a0 = restored value. |
| 2436 __ pop(a0); // Restore value. | |
| 2437 Handle<Code> ic = is_classic_mode() | 2444 Handle<Code> ic = is_classic_mode() |
| 2438 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2445 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2439 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2446 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2440 CallIC(ic); | 2447 CallIC(ic); |
| 2441 break; | 2448 break; |
| 2442 } | 2449 } |
| 2443 } | 2450 } |
| 2444 context()->Plug(v0); | 2451 context()->Plug(v0); |
| 2445 } | 2452 } |
| 2446 | 2453 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2568 // Assignment to a property, using a keyed store IC. | 2575 // Assignment to a property, using a keyed store IC. |
| 2569 | 2576 |
| 2570 // Record source code position before IC call. | 2577 // Record source code position before IC call. |
| 2571 SetSourcePosition(expr->position()); | 2578 SetSourcePosition(expr->position()); |
| 2572 // Call keyed store IC. | 2579 // Call keyed store IC. |
| 2573 // The arguments are: | 2580 // The arguments are: |
| 2574 // - a0 is the value, | 2581 // - a0 is the value, |
| 2575 // - a1 is the key, | 2582 // - a1 is the key, |
| 2576 // - a2 is the receiver. | 2583 // - a2 is the receiver. |
| 2577 __ mov(a0, result_register()); | 2584 __ mov(a0, result_register()); |
| 2578 __ pop(a1); // Key. | 2585 __ Pop(a2, a1); // a1 = key. |
| 2579 __ pop(a2); | |
| 2580 | 2586 |
| 2581 Handle<Code> ic = is_classic_mode() | 2587 Handle<Code> ic = is_classic_mode() |
| 2582 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2588 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2583 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2589 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2584 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2590 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); |
| 2585 | 2591 |
| 2586 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2592 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2587 context()->Plug(v0); | 2593 context()->Plug(v0); |
| 2588 } | 2594 } |
| 2589 | 2595 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2697 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2703 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2698 __ CallStub(&stub, expr->CallFeedbackId()); | 2704 __ CallStub(&stub, expr->CallFeedbackId()); |
| 2699 RecordJSReturnSite(expr); | 2705 RecordJSReturnSite(expr); |
| 2700 // Restore context register. | 2706 // Restore context register. |
| 2701 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2707 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2702 context()->DropAndPlug(1, v0); | 2708 context()->DropAndPlug(1, v0); |
| 2703 } | 2709 } |
| 2704 | 2710 |
| 2705 | 2711 |
| 2706 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 2712 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
| 2707 // Push copy of the first argument or undefined if it doesn't exist. | 2713 // t2: copy of the first argument or undefined if it doesn't exist. |
| 2708 if (arg_count > 0) { | 2714 if (arg_count > 0) { |
| 2709 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); | 2715 __ lw(t2, MemOperand(sp, arg_count * kPointerSize)); |
| 2710 } else { | 2716 } else { |
| 2711 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); | 2717 __ LoadRoot(t2, Heap::kUndefinedValueRootIndex); |
| 2712 } | 2718 } |
| 2713 __ push(a1); | |
| 2714 | 2719 |
| 2715 // Push the receiver of the enclosing function. | 2720 // t1: the receiver of the enclosing function. |
| 2716 int receiver_offset = 2 + info_->scope()->num_parameters(); | 2721 int receiver_offset = 2 + info_->scope()->num_parameters(); |
| 2717 __ lw(a1, MemOperand(fp, receiver_offset * kPointerSize)); | 2722 __ 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 | 2723 |
| 2723 // Push the start position of the scope the calls resides in. | 2724 // t0: the language mode. |
| 2725 __ li(t0, Operand(Smi::FromInt(language_mode()))); |
| 2726 |
| 2727 // a1: the start position of the scope the calls resides in. |
| 2724 __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); | 2728 __ li(a1, Operand(Smi::FromInt(scope()->start_position()))); |
| 2725 __ push(a1); | |
| 2726 | 2729 |
| 2727 // Do the runtime call. | 2730 // Do the runtime call. |
| 2731 __ Push(t2, t1, t0, a1); |
| 2728 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2732 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
| 2729 } | 2733 } |
| 2730 | 2734 |
| 2731 | 2735 |
| 2732 void FullCodeGenerator::VisitCall(Call* expr) { | 2736 void FullCodeGenerator::VisitCall(Call* expr) { |
| 2733 #ifdef DEBUG | 2737 #ifdef DEBUG |
| 2734 // We want to verify that RecordJSReturnSite gets called on all paths | 2738 // We want to verify that RecordJSReturnSite gets called on all paths |
| 2735 // through this function. Avoid early returns. | 2739 // through this function. Avoid early returns. |
| 2736 expr->return_is_recorded_ = false; | 2740 expr->return_is_recorded_ = false; |
| 2737 #endif | 2741 #endif |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2790 | 2794 |
| 2791 { PreservePositionScope scope(masm()->positions_recorder()); | 2795 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2792 // Generate code for loading from variables potentially shadowed | 2796 // Generate code for loading from variables potentially shadowed |
| 2793 // by eval-introduced variables. | 2797 // by eval-introduced variables. |
| 2794 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2798 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2795 } | 2799 } |
| 2796 | 2800 |
| 2797 __ bind(&slow); | 2801 __ bind(&slow); |
| 2798 // Call the runtime to find the function to call (returned in v0) | 2802 // Call the runtime to find the function to call (returned in v0) |
| 2799 // and the object holding it (returned in v1). | 2803 // and the object holding it (returned in v1). |
| 2800 __ push(context_register()); | 2804 ASSERT(!context_register().is(a2)); |
| 2801 __ li(a2, Operand(proxy->name())); | 2805 __ li(a2, Operand(proxy->name())); |
| 2802 __ push(a2); | 2806 __ Push(context_register(), a2); |
| 2803 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 2807 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 2804 __ Push(v0, v1); // Function, receiver. | 2808 __ Push(v0, v1); // Function, receiver. |
| 2805 | 2809 |
| 2806 // If fast case code has been generated, emit code to push the | 2810 // If fast case code has been generated, emit code to push the |
| 2807 // function and receiver and have the slow path jump around this | 2811 // function and receiver and have the slow path jump around this |
| 2808 // code. | 2812 // code. |
| 2809 if (done.is_linked()) { | 2813 if (done.is_linked()) { |
| 2810 Label call; | 2814 Label call; |
| 2811 __ Branch(&call); | 2815 __ Branch(&call); |
| 2812 __ bind(&done); | 2816 __ bind(&done); |
| (...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3504 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3508 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
| 3505 ZoneList<Expression*>* args = expr->arguments(); | 3509 ZoneList<Expression*>* args = expr->arguments(); |
| 3506 ASSERT_EQ(3, args->length()); | 3510 ASSERT_EQ(3, args->length()); |
| 3507 | 3511 |
| 3508 Register string = v0; | 3512 Register string = v0; |
| 3509 Register index = a1; | 3513 Register index = a1; |
| 3510 Register value = a2; | 3514 Register value = a2; |
| 3511 | 3515 |
| 3512 VisitForStackValue(args->at(1)); // index | 3516 VisitForStackValue(args->at(1)); // index |
| 3513 VisitForStackValue(args->at(2)); // value | 3517 VisitForStackValue(args->at(2)); // value |
| 3514 __ pop(value); | 3518 __ Pop(index, value); |
| 3515 __ pop(index); | |
| 3516 VisitForAccumulatorValue(args->at(0)); // string | 3519 VisitForAccumulatorValue(args->at(0)); // string |
| 3517 | 3520 |
| 3518 if (FLAG_debug_code) { | 3521 if (FLAG_debug_code) { |
| 3519 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 3522 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
| 3520 EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); | 3523 EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); |
| 3521 } | 3524 } |
| 3522 | 3525 |
| 3523 __ SmiUntag(value, value); | 3526 __ SmiUntag(value, value); |
| 3524 __ Addu(at, | 3527 __ Addu(at, |
| 3525 string, | 3528 string, |
| 3526 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3529 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
| 3527 __ SmiUntag(index); | 3530 __ SmiUntag(index); |
| 3528 __ Addu(at, at, index); | 3531 __ Addu(at, at, index); |
| 3529 __ sb(value, MemOperand(at)); | 3532 __ sb(value, MemOperand(at)); |
| 3530 context()->Plug(string); | 3533 context()->Plug(string); |
| 3531 } | 3534 } |
| 3532 | 3535 |
| 3533 | 3536 |
| 3534 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { | 3537 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { |
| 3535 ZoneList<Expression*>* args = expr->arguments(); | 3538 ZoneList<Expression*>* args = expr->arguments(); |
| 3536 ASSERT_EQ(3, args->length()); | 3539 ASSERT_EQ(3, args->length()); |
| 3537 | 3540 |
| 3538 Register string = v0; | 3541 Register string = v0; |
| 3539 Register index = a1; | 3542 Register index = a1; |
| 3540 Register value = a2; | 3543 Register value = a2; |
| 3541 | 3544 |
| 3542 VisitForStackValue(args->at(1)); // index | 3545 VisitForStackValue(args->at(1)); // index |
| 3543 VisitForStackValue(args->at(2)); // value | 3546 VisitForStackValue(args->at(2)); // value |
| 3544 __ pop(value); | 3547 __ Pop(index, value); |
| 3545 __ pop(index); | |
| 3546 VisitForAccumulatorValue(args->at(0)); // string | 3548 VisitForAccumulatorValue(args->at(0)); // string |
| 3547 | 3549 |
| 3548 if (FLAG_debug_code) { | 3550 if (FLAG_debug_code) { |
| 3549 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 3551 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
| 3550 EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); | 3552 EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); |
| 3551 } | 3553 } |
| 3552 | 3554 |
| 3553 __ SmiUntag(value, value); | 3555 __ SmiUntag(value, value); |
| 3554 __ Addu(at, | 3556 __ Addu(at, |
| 3555 string, | 3557 string, |
| (...skipping 740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4296 __ Push(a2, a1, a0); | 4298 __ Push(a2, a1, a0); |
| 4297 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4299 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4298 context()->Plug(v0); | 4300 context()->Plug(v0); |
| 4299 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4301 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4300 // Result of deleting non-global, non-dynamic variables is false. | 4302 // Result of deleting non-global, non-dynamic variables is false. |
| 4301 // The subexpression does not have side effects. | 4303 // The subexpression does not have side effects. |
| 4302 context()->Plug(var->is_this()); | 4304 context()->Plug(var->is_this()); |
| 4303 } else { | 4305 } else { |
| 4304 // Non-global variable. Call the runtime to try to delete from the | 4306 // Non-global variable. Call the runtime to try to delete from the |
| 4305 // context where the variable was introduced. | 4307 // context where the variable was introduced. |
| 4306 __ push(context_register()); | 4308 ASSERT(!context_register().is(a2)); |
| 4307 __ li(a2, Operand(var->name())); | 4309 __ li(a2, Operand(var->name())); |
| 4308 __ push(a2); | 4310 __ Push(context_register(), a2); |
| 4309 __ CallRuntime(Runtime::kDeleteContextSlot, 2); | 4311 __ CallRuntime(Runtime::kDeleteContextSlot, 2); |
| 4310 context()->Plug(v0); | 4312 context()->Plug(v0); |
| 4311 } | 4313 } |
| 4312 } else { | 4314 } else { |
| 4313 // Result of deleting non-property, non-variable reference is true. | 4315 // Result of deleting non-property, non-variable reference is true. |
| 4314 // The subexpression may have side effects. | 4316 // The subexpression may have side effects. |
| 4315 VisitForEffect(expr->expression()); | 4317 VisitForEffect(expr->expression()); |
| 4316 context()->Plug(true); | 4318 context()->Plug(true); |
| 4317 } | 4319 } |
| 4318 break; | 4320 break; |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4530 if (!context()->IsEffect()) { | 4532 if (!context()->IsEffect()) { |
| 4531 context()->PlugTOS(); | 4533 context()->PlugTOS(); |
| 4532 } | 4534 } |
| 4533 } else { | 4535 } else { |
| 4534 context()->Plug(v0); | 4536 context()->Plug(v0); |
| 4535 } | 4537 } |
| 4536 break; | 4538 break; |
| 4537 } | 4539 } |
| 4538 case KEYED_PROPERTY: { | 4540 case KEYED_PROPERTY: { |
| 4539 __ mov(a0, result_register()); // Value. | 4541 __ mov(a0, result_register()); // Value. |
| 4540 __ pop(a1); // Key. | 4542 __ Pop(a2, a1); // a1 = key, a2 = receiver. |
| 4541 __ pop(a2); // Receiver. | |
| 4542 Handle<Code> ic = is_classic_mode() | 4543 Handle<Code> ic = is_classic_mode() |
| 4543 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4544 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4544 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4545 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4545 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | 4546 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); |
| 4546 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4547 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4547 if (expr->is_postfix()) { | 4548 if (expr->is_postfix()) { |
| 4548 if (!context()->IsEffect()) { | 4549 if (!context()->IsEffect()) { |
| 4549 context()->PlugTOS(); | 4550 context()->PlugTOS(); |
| 4550 } | 4551 } |
| 4551 } else { | 4552 } else { |
| (...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4993 Assembler::target_address_at(pc_immediate_load_address)) == | 4994 Assembler::target_address_at(pc_immediate_load_address)) == |
| 4994 reinterpret_cast<uint32_t>( | 4995 reinterpret_cast<uint32_t>( |
| 4995 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4996 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4996 return OSR_AFTER_STACK_CHECK; | 4997 return OSR_AFTER_STACK_CHECK; |
| 4997 } | 4998 } |
| 4998 | 4999 |
| 4999 | 5000 |
| 5000 } } // namespace v8::internal | 5001 } } // namespace v8::internal |
| 5001 | 5002 |
| 5002 #endif // V8_TARGET_ARCH_MIPS | 5003 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |