| 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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 | 161 |
| 162 info->set_prologue_offset(masm_->pc_offset()); | 162 info->set_prologue_offset(masm_->pc_offset()); |
| 163 __ Prologue(BUILD_FUNCTION_FRAME); | 163 __ Prologue(BUILD_FUNCTION_FRAME); |
| 164 info->AddNoFrameRange(0, masm_->pc_offset()); | 164 info->AddNoFrameRange(0, masm_->pc_offset()); |
| 165 | 165 |
| 166 { Comment cmnt(masm_, "[ Allocate locals"); | 166 { Comment cmnt(masm_, "[ Allocate locals"); |
| 167 int locals_count = info->scope()->num_stack_slots(); | 167 int locals_count = info->scope()->num_stack_slots(); |
| 168 // Generators allocate locals, if any, in context slots. | 168 // Generators allocate locals, if any, in context slots. |
| 169 ASSERT(!info->function()->is_generator() || locals_count == 0); | 169 ASSERT(!info->function()->is_generator() || locals_count == 0); |
| 170 if (locals_count > 0) { | 170 if (locals_count > 0) { |
| 171 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 171 // Emit a loop to initialize stack cells for locals when optimizing for |
| 172 for (int i = 0; i < locals_count; i++) { | 172 // size. Otherwise, unroll the loop for maximum performance. |
| 173 __ 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 } |
| 174 } | 185 } |
| 175 } | 186 } |
| 176 } | 187 } |
| 177 | 188 |
| 178 bool function_in_register = true; | 189 bool function_in_register = true; |
| 179 | 190 |
| 180 // Possibly allocate a local context. | 191 // Possibly allocate a local context. |
| 181 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; |
| 182 if (heap_slots > 0) { | 193 if (heap_slots > 0) { |
| 183 // 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 Loading... |
| 606 __ bind(&done); | 617 __ bind(&done); |
| 607 } | 618 } |
| 608 | 619 |
| 609 | 620 |
| 610 void FullCodeGenerator::StackValueContext::Plug( | 621 void FullCodeGenerator::StackValueContext::Plug( |
| 611 Label* materialize_true, | 622 Label* materialize_true, |
| 612 Label* materialize_false) const { | 623 Label* materialize_false) const { |
| 613 Label done; | 624 Label done; |
| 614 __ bind(materialize_true); | 625 __ bind(materialize_true); |
| 615 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 626 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 616 __ push(ip); | |
| 617 __ jmp(&done); | 627 __ jmp(&done); |
| 618 __ bind(materialize_false); | 628 __ bind(materialize_false); |
| 619 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 629 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
| 630 __ bind(&done); |
| 620 __ push(ip); | 631 __ push(ip); |
| 621 __ bind(&done); | |
| 622 } | 632 } |
| 623 | 633 |
| 624 | 634 |
| 625 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, | 635 void FullCodeGenerator::TestContext::Plug(Label* materialize_true, |
| 626 Label* materialize_false) const { | 636 Label* materialize_false) const { |
| 627 ASSERT(materialize_true == true_label_); | 637 ASSERT(materialize_true == true_label_); |
| 628 ASSERT(materialize_false == false_label_); | 638 ASSERT(materialize_false == false_label_); |
| 629 } | 639 } |
| 630 | 640 |
| 631 | 641 |
| (...skipping 958 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1590 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); | 1600 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); |
| 1591 __ mov(r5, r0); | 1601 __ mov(r5, r0); |
| 1592 | 1602 |
| 1593 __ bind(&materialized); | 1603 __ bind(&materialized); |
| 1594 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 1604 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
| 1595 Label allocated, runtime_allocate; | 1605 Label allocated, runtime_allocate; |
| 1596 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); | 1606 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); |
| 1597 __ jmp(&allocated); | 1607 __ jmp(&allocated); |
| 1598 | 1608 |
| 1599 __ bind(&runtime_allocate); | 1609 __ bind(&runtime_allocate); |
| 1600 __ push(r5); | |
| 1601 __ mov(r0, Operand(Smi::FromInt(size))); | 1610 __ mov(r0, Operand(Smi::FromInt(size))); |
| 1602 __ push(r0); | 1611 __ Push(r5, r0); |
| 1603 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); | 1612 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 1604 __ pop(r5); | 1613 __ pop(r5); |
| 1605 | 1614 |
| 1606 __ bind(&allocated); | 1615 __ bind(&allocated); |
| 1607 // After this, registers are used as follows: | 1616 // After this, registers are used as follows: |
| 1608 // r0: Newly allocated regexp. | 1617 // r0: Newly allocated regexp. |
| 1609 // r5: Materialized regexp. | 1618 // r5: Materialized regexp. |
| 1610 // r2: temp. | 1619 // r2: temp. |
| 1611 __ CopyFields(r0, r5, d0, size / kPointerSize); | 1620 __ CopyFields(r0, r5, d0, size / kPointerSize); |
| 1612 context()->Plug(r0); | 1621 context()->Plug(r0); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1774 __ mov(r1, Operand(constant_elements)); | 1783 __ mov(r1, Operand(constant_elements)); |
| 1775 if (has_fast_elements && constant_elements_values->map() == | 1784 if (has_fast_elements && constant_elements_values->map() == |
| 1776 isolate()->heap()->fixed_cow_array_map()) { | 1785 isolate()->heap()->fixed_cow_array_map()) { |
| 1777 FastCloneShallowArrayStub stub( | 1786 FastCloneShallowArrayStub stub( |
| 1778 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, | 1787 FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, |
| 1779 DONT_TRACK_ALLOCATION_SITE, | 1788 DONT_TRACK_ALLOCATION_SITE, |
| 1780 length); | 1789 length); |
| 1781 __ CallStub(&stub); | 1790 __ CallStub(&stub); |
| 1782 __ IncrementCounter( | 1791 __ IncrementCounter( |
| 1783 isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2); | 1792 isolate()->counters()->cow_arrays_created_stub(), 1, r1, r2); |
| 1784 } else if (expr->depth() > 1) { | 1793 } else if (expr->depth() > 1 || |
| 1794 Serializer::enabled() || |
| 1795 length > FastCloneShallowArrayStub::kMaximumClonedLength) { |
| 1785 __ Push(r3, r2, r1); | 1796 __ Push(r3, r2, r1); |
| 1786 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); | 1797 __ CallRuntime(Runtime::kCreateArrayLiteral, 3); |
| 1787 } else if (Serializer::enabled() || | |
| 1788 length > FastCloneShallowArrayStub::kMaximumClonedLength) { | |
| 1789 __ Push(r3, r2, r1); | |
| 1790 __ CallRuntime(Runtime::kCreateArrayLiteralShallow, 3); | |
| 1791 } else { | 1798 } else { |
| 1792 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || | 1799 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind) || |
| 1793 FLAG_smi_only_arrays); | 1800 FLAG_smi_only_arrays); |
| 1794 FastCloneShallowArrayStub::Mode mode = | 1801 FastCloneShallowArrayStub::Mode mode = |
| 1795 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; | 1802 FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS; |
| 1796 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites | 1803 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites |
| 1797 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE; | 1804 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE; |
| 1798 | 1805 |
| 1799 if (has_fast_elements) { | 1806 if (has_fast_elements) { |
| 1800 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; | 1807 mode = FastCloneShallowArrayStub::CLONE_ELEMENTS; |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2029 Label l_next, l_call, l_loop; | 2036 Label l_next, l_call, l_loop; |
| 2030 // Initial send value is undefined. | 2037 // Initial send value is undefined. |
| 2031 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 2038 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
| 2032 __ b(&l_next); | 2039 __ b(&l_next); |
| 2033 | 2040 |
| 2034 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 2041 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
| 2035 __ bind(&l_catch); | 2042 __ bind(&l_catch); |
| 2036 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 2043 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
| 2037 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw" | 2044 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw" |
| 2038 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2045 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
| 2039 __ push(r3); // iter | 2046 __ Push(r3, r0); // iter, exception |
| 2040 __ push(r0); // exception | |
| 2041 __ jmp(&l_call); | 2047 __ jmp(&l_call); |
| 2042 | 2048 |
| 2043 // try { received = %yield result } | 2049 // try { received = %yield result } |
| 2044 // Shuffle the received result above a try handler and yield it without | 2050 // Shuffle the received result above a try handler and yield it without |
| 2045 // re-boxing. | 2051 // re-boxing. |
| 2046 __ bind(&l_try); | 2052 __ bind(&l_try); |
| 2047 __ pop(r0); // result | 2053 __ pop(r0); // result |
| 2048 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2054 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
| 2049 const int handler_size = StackHandlerConstants::kSize; | 2055 const int handler_size = StackHandlerConstants::kSize; |
| 2050 __ push(r0); // result | 2056 __ push(r0); // result |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2066 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2072 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2067 __ pop(r0); // result | 2073 __ pop(r0); // result |
| 2068 EmitReturnSequence(); | 2074 EmitReturnSequence(); |
| 2069 __ bind(&l_resume); // received in r0 | 2075 __ bind(&l_resume); // received in r0 |
| 2070 __ PopTryHandler(); | 2076 __ PopTryHandler(); |
| 2071 | 2077 |
| 2072 // receiver = iter; f = 'next'; arg = received; | 2078 // receiver = iter; f = 'next'; arg = received; |
| 2073 __ bind(&l_next); | 2079 __ bind(&l_next); |
| 2074 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" | 2080 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" |
| 2075 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2081 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
| 2076 __ push(r3); // iter | 2082 __ Push(r3, r0); // iter, received |
| 2077 __ push(r0); // received | |
| 2078 | 2083 |
| 2079 // result = receiver[f](arg); | 2084 // result = receiver[f](arg); |
| 2080 __ bind(&l_call); | 2085 __ bind(&l_call); |
| 2081 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); | 2086 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); |
| 2082 CallIC(ic); | 2087 CallIC(ic); |
| 2083 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2088 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2084 | 2089 |
| 2085 // if (!result.done) goto l_try; | 2090 // if (!result.done) goto l_try; |
| 2086 __ bind(&l_loop); | 2091 __ bind(&l_loop); |
| 2087 __ push(r0); // save result | 2092 __ push(r0); // save result |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2143 __ push(r2); | 2148 __ push(r2); |
| 2144 __ jmp(&push_argument_holes); | 2149 __ jmp(&push_argument_holes); |
| 2145 | 2150 |
| 2146 // Enter a new JavaScript frame, and initialize its slots as they were when | 2151 // Enter a new JavaScript frame, and initialize its slots as they were when |
| 2147 // the generator was suspended. | 2152 // the generator was suspended. |
| 2148 Label resume_frame; | 2153 Label resume_frame; |
| 2149 __ bind(&push_frame); | 2154 __ bind(&push_frame); |
| 2150 __ bl(&resume_frame); | 2155 __ bl(&resume_frame); |
| 2151 __ jmp(&done); | 2156 __ jmp(&done); |
| 2152 __ bind(&resume_frame); | 2157 __ bind(&resume_frame); |
| 2153 __ push(lr); // Return address. | 2158 // lr = return address. |
| 2154 __ push(fp); // Caller's frame pointer. | 2159 // fp = caller's frame pointer. |
| 2155 __ mov(fp, sp); | 2160 // cp = callee's context, |
| 2156 __ push(cp); // Callee's context. | 2161 // r4 = callee's JS function. |
| 2157 __ push(r4); // Callee's JS Function. | 2162 __ Push(lr, fp, cp, r4); |
| 2163 // Adjust FP to point to saved FP. |
| 2164 __ add(fp, sp, Operand(2 * kPointerSize)); |
| 2158 | 2165 |
| 2159 // Load the operand stack size. | 2166 // Load the operand stack size. |
| 2160 __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset)); | 2167 __ ldr(r3, FieldMemOperand(r1, JSGeneratorObject::kOperandStackOffset)); |
| 2161 __ ldr(r3, FieldMemOperand(r3, FixedArray::kLengthOffset)); | 2168 __ ldr(r3, FieldMemOperand(r3, FixedArray::kLengthOffset)); |
| 2162 __ SmiUntag(r3); | 2169 __ SmiUntag(r3); |
| 2163 | 2170 |
| 2164 // If we are sending a value and there is no operand stack, we can jump back | 2171 // If we are sending a value and there is no operand stack, we can jump back |
| 2165 // in directly. | 2172 // in directly. |
| 2166 if (resume_mode == JSGeneratorObject::NEXT) { | 2173 if (resume_mode == JSGeneratorObject::NEXT) { |
| 2167 Label slow_resume; | 2174 Label slow_resume; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2179 | 2186 |
| 2180 // Otherwise, we push holes for the operand stack and call the runtime to fix | 2187 // Otherwise, we push holes for the operand stack and call the runtime to fix |
| 2181 // up the stack and the handlers. | 2188 // up the stack and the handlers. |
| 2182 Label push_operand_holes, call_resume; | 2189 Label push_operand_holes, call_resume; |
| 2183 __ bind(&push_operand_holes); | 2190 __ bind(&push_operand_holes); |
| 2184 __ sub(r3, r3, Operand(1), SetCC); | 2191 __ sub(r3, r3, Operand(1), SetCC); |
| 2185 __ b(mi, &call_resume); | 2192 __ b(mi, &call_resume); |
| 2186 __ push(r2); | 2193 __ push(r2); |
| 2187 __ b(&push_operand_holes); | 2194 __ b(&push_operand_holes); |
| 2188 __ bind(&call_resume); | 2195 __ bind(&call_resume); |
| 2189 __ push(r1); | 2196 ASSERT(!result_register().is(r1)); |
| 2190 __ push(result_register()); | 2197 __ Push(r1, result_register()); |
| 2191 __ Push(Smi::FromInt(resume_mode)); | 2198 __ Push(Smi::FromInt(resume_mode)); |
| 2192 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); | 2199 __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3); |
| 2193 // Not reached: the runtime call returns elsewhere. | 2200 // Not reached: the runtime call returns elsewhere. |
| 2194 __ stop("not-reached"); | 2201 __ stop("not-reached"); |
| 2195 | 2202 |
| 2196 // Throw error if we attempt to operate on a running generator. | 2203 // Throw error if we attempt to operate on a running generator. |
| 2197 __ bind(&wrong_state); | 2204 __ bind(&wrong_state); |
| 2198 __ push(r1); | 2205 __ push(r1); |
| 2199 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); | 2206 __ CallRuntime(Runtime::kThrowGeneratorStateError, 1); |
| 2200 | 2207 |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2402 ? isolate()->builtins()->StoreIC_Initialize() | 2409 ? isolate()->builtins()->StoreIC_Initialize() |
| 2403 : isolate()->builtins()->StoreIC_Initialize_Strict(); | 2410 : isolate()->builtins()->StoreIC_Initialize_Strict(); |
| 2404 CallIC(ic); | 2411 CallIC(ic); |
| 2405 break; | 2412 break; |
| 2406 } | 2413 } |
| 2407 case KEYED_PROPERTY: { | 2414 case KEYED_PROPERTY: { |
| 2408 __ push(r0); // Preserve value. | 2415 __ push(r0); // Preserve value. |
| 2409 VisitForStackValue(prop->obj()); | 2416 VisitForStackValue(prop->obj()); |
| 2410 VisitForAccumulatorValue(prop->key()); | 2417 VisitForAccumulatorValue(prop->key()); |
| 2411 __ mov(r1, r0); | 2418 __ mov(r1, r0); |
| 2412 __ pop(r2); | 2419 __ Pop(r0, r2); // r0 = restored value. |
| 2413 __ pop(r0); // Restore value. | |
| 2414 Handle<Code> ic = is_classic_mode() | 2420 Handle<Code> ic = is_classic_mode() |
| 2415 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2421 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2416 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2422 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2417 CallIC(ic); | 2423 CallIC(ic); |
| 2418 break; | 2424 break; |
| 2419 } | 2425 } |
| 2420 } | 2426 } |
| 2421 context()->Plug(r0); | 2427 context()->Plug(r0); |
| 2422 } | 2428 } |
| 2423 | 2429 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2537 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2543 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2538 context()->Plug(r0); | 2544 context()->Plug(r0); |
| 2539 } | 2545 } |
| 2540 | 2546 |
| 2541 | 2547 |
| 2542 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { | 2548 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { |
| 2543 // Assignment to a property, using a keyed store IC. | 2549 // Assignment to a property, using a keyed store IC. |
| 2544 | 2550 |
| 2545 // Record source code position before IC call. | 2551 // Record source code position before IC call. |
| 2546 SetSourcePosition(expr->position()); | 2552 SetSourcePosition(expr->position()); |
| 2547 __ pop(r1); // Key. | 2553 __ Pop(r2, r1); // r1 = key. |
| 2548 __ pop(r2); | |
| 2549 | 2554 |
| 2550 Handle<Code> ic = is_classic_mode() | 2555 Handle<Code> ic = is_classic_mode() |
| 2551 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 2556 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 2552 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 2557 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 2553 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); | 2558 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); |
| 2554 | 2559 |
| 2555 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 2560 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 2556 context()->Plug(r0); | 2561 context()->Plug(r0); |
| 2557 } | 2562 } |
| 2558 | 2563 |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2667 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); | 2672 __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize)); |
| 2668 __ CallStub(&stub, expr->CallFeedbackId()); | 2673 __ CallStub(&stub, expr->CallFeedbackId()); |
| 2669 RecordJSReturnSite(expr); | 2674 RecordJSReturnSite(expr); |
| 2670 // Restore context register. | 2675 // Restore context register. |
| 2671 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2676 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| 2672 context()->DropAndPlug(1, r0); | 2677 context()->DropAndPlug(1, r0); |
| 2673 } | 2678 } |
| 2674 | 2679 |
| 2675 | 2680 |
| 2676 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { | 2681 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { |
| 2677 // Push copy of the first argument or undefined if it doesn't exist. | 2682 // r4: copy of the first argument or undefined if it doesn't exist. |
| 2678 if (arg_count > 0) { | 2683 if (arg_count > 0) { |
| 2679 __ ldr(r1, MemOperand(sp, arg_count * kPointerSize)); | 2684 __ ldr(r4, MemOperand(sp, arg_count * kPointerSize)); |
| 2680 } else { | 2685 } else { |
| 2681 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); | 2686 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); |
| 2682 } | 2687 } |
| 2683 __ push(r1); | |
| 2684 | 2688 |
| 2685 // Push the receiver of the enclosing function. | 2689 // r3: the receiver of the enclosing function. |
| 2686 int receiver_offset = 2 + info_->scope()->num_parameters(); | 2690 int receiver_offset = 2 + info_->scope()->num_parameters(); |
| 2687 __ ldr(r1, MemOperand(fp, receiver_offset * kPointerSize)); | 2691 __ ldr(r3, MemOperand(fp, receiver_offset * kPointerSize)); |
| 2688 __ push(r1); | |
| 2689 // Push the language mode. | |
| 2690 __ mov(r1, Operand(Smi::FromInt(language_mode()))); | |
| 2691 __ push(r1); | |
| 2692 | 2692 |
| 2693 // Push the start position of the scope the calls resides in. | 2693 // r2: the language mode. |
| 2694 __ mov(r2, Operand(Smi::FromInt(language_mode()))); |
| 2695 |
| 2696 // r1: the start position of the scope the calls resides in. |
| 2694 __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); | 2697 __ mov(r1, Operand(Smi::FromInt(scope()->start_position()))); |
| 2695 __ push(r1); | |
| 2696 | 2698 |
| 2697 // Do the runtime call. | 2699 // Do the runtime call. |
| 2700 __ Push(r4, r3, r2, r1); |
| 2698 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); | 2701 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 5); |
| 2699 } | 2702 } |
| 2700 | 2703 |
| 2701 | 2704 |
| 2702 void FullCodeGenerator::VisitCall(Call* expr) { | 2705 void FullCodeGenerator::VisitCall(Call* expr) { |
| 2703 #ifdef DEBUG | 2706 #ifdef DEBUG |
| 2704 // We want to verify that RecordJSReturnSite gets called on all paths | 2707 // We want to verify that RecordJSReturnSite gets called on all paths |
| 2705 // through this function. Avoid early returns. | 2708 // through this function. Avoid early returns. |
| 2706 expr->return_is_recorded_ = false; | 2709 expr->return_is_recorded_ = false; |
| 2707 #endif | 2710 #endif |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2761 | 2764 |
| 2762 { PreservePositionScope scope(masm()->positions_recorder()); | 2765 { PreservePositionScope scope(masm()->positions_recorder()); |
| 2763 // Generate code for loading from variables potentially shadowed | 2766 // Generate code for loading from variables potentially shadowed |
| 2764 // by eval-introduced variables. | 2767 // by eval-introduced variables. |
| 2765 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); | 2768 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); |
| 2766 } | 2769 } |
| 2767 | 2770 |
| 2768 __ bind(&slow); | 2771 __ bind(&slow); |
| 2769 // Call the runtime to find the function to call (returned in r0) | 2772 // Call the runtime to find the function to call (returned in r0) |
| 2770 // and the object holding it (returned in edx). | 2773 // and the object holding it (returned in edx). |
| 2771 __ push(context_register()); | 2774 ASSERT(!context_register().is(r2)); |
| 2772 __ mov(r2, Operand(proxy->name())); | 2775 __ mov(r2, Operand(proxy->name())); |
| 2773 __ push(r2); | 2776 __ Push(context_register(), r2); |
| 2774 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 2777 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
| 2775 __ Push(r0, r1); // Function, receiver. | 2778 __ Push(r0, r1); // Function, receiver. |
| 2776 | 2779 |
| 2777 // If fast case code has been generated, emit code to push the | 2780 // If fast case code has been generated, emit code to push the |
| 2778 // function and receiver and have the slow path jump around this | 2781 // function and receiver and have the slow path jump around this |
| 2779 // code. | 2782 // code. |
| 2780 if (done.is_linked()) { | 2783 if (done.is_linked()) { |
| 2781 Label call; | 2784 Label call; |
| 2782 __ b(&call); | 2785 __ b(&call); |
| 2783 __ bind(&done); | 2786 __ bind(&done); |
| (...skipping 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3480 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { | 3483 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { |
| 3481 ZoneList<Expression*>* args = expr->arguments(); | 3484 ZoneList<Expression*>* args = expr->arguments(); |
| 3482 ASSERT_EQ(3, args->length()); | 3485 ASSERT_EQ(3, args->length()); |
| 3483 | 3486 |
| 3484 Register string = r0; | 3487 Register string = r0; |
| 3485 Register index = r1; | 3488 Register index = r1; |
| 3486 Register value = r2; | 3489 Register value = r2; |
| 3487 | 3490 |
| 3488 VisitForStackValue(args->at(1)); // index | 3491 VisitForStackValue(args->at(1)); // index |
| 3489 VisitForStackValue(args->at(2)); // value | 3492 VisitForStackValue(args->at(2)); // value |
| 3490 __ pop(value); | 3493 __ Pop(index, value); |
| 3491 __ pop(index); | |
| 3492 VisitForAccumulatorValue(args->at(0)); // string | 3494 VisitForAccumulatorValue(args->at(0)); // string |
| 3493 | 3495 |
| 3494 if (FLAG_debug_code) { | 3496 if (FLAG_debug_code) { |
| 3495 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; | 3497 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
| 3496 EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); | 3498 EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); |
| 3497 } | 3499 } |
| 3498 | 3500 |
| 3499 __ SmiUntag(value, value); | 3501 __ SmiUntag(value, value); |
| 3500 __ add(ip, | 3502 __ add(ip, |
| 3501 string, | 3503 string, |
| 3502 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 3504 Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
| 3503 __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize)); | 3505 __ strb(value, MemOperand(ip, index, LSR, kSmiTagSize)); |
| 3504 context()->Plug(string); | 3506 context()->Plug(string); |
| 3505 } | 3507 } |
| 3506 | 3508 |
| 3507 | 3509 |
| 3508 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { | 3510 void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) { |
| 3509 ZoneList<Expression*>* args = expr->arguments(); | 3511 ZoneList<Expression*>* args = expr->arguments(); |
| 3510 ASSERT_EQ(3, args->length()); | 3512 ASSERT_EQ(3, args->length()); |
| 3511 | 3513 |
| 3512 Register string = r0; | 3514 Register string = r0; |
| 3513 Register index = r1; | 3515 Register index = r1; |
| 3514 Register value = r2; | 3516 Register value = r2; |
| 3515 | 3517 |
| 3516 VisitForStackValue(args->at(1)); // index | 3518 VisitForStackValue(args->at(1)); // index |
| 3517 VisitForStackValue(args->at(2)); // value | 3519 VisitForStackValue(args->at(2)); // value |
| 3518 __ pop(value); | 3520 __ Pop(index, value); |
| 3519 __ pop(index); | |
| 3520 VisitForAccumulatorValue(args->at(0)); // string | 3521 VisitForAccumulatorValue(args->at(0)); // string |
| 3521 | 3522 |
| 3522 if (FLAG_debug_code) { | 3523 if (FLAG_debug_code) { |
| 3523 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; | 3524 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
| 3524 EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); | 3525 EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); |
| 3525 } | 3526 } |
| 3526 | 3527 |
| 3527 __ SmiUntag(value, value); | 3528 __ SmiUntag(value, value); |
| 3528 __ add(ip, | 3529 __ add(ip, |
| 3529 string, | 3530 string, |
| (...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4253 __ Push(r2, r1, r0); | 4254 __ Push(r2, r1, r0); |
| 4254 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); | 4255 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); |
| 4255 context()->Plug(r0); | 4256 context()->Plug(r0); |
| 4256 } else if (var->IsStackAllocated() || var->IsContextSlot()) { | 4257 } else if (var->IsStackAllocated() || var->IsContextSlot()) { |
| 4257 // Result of deleting non-global, non-dynamic variables is false. | 4258 // Result of deleting non-global, non-dynamic variables is false. |
| 4258 // The subexpression does not have side effects. | 4259 // The subexpression does not have side effects. |
| 4259 context()->Plug(var->is_this()); | 4260 context()->Plug(var->is_this()); |
| 4260 } else { | 4261 } else { |
| 4261 // Non-global variable. Call the runtime to try to delete from the | 4262 // Non-global variable. Call the runtime to try to delete from the |
| 4262 // context where the variable was introduced. | 4263 // context where the variable was introduced. |
| 4263 __ push(context_register()); | 4264 ASSERT(!context_register().is(r2)); |
| 4264 __ mov(r2, Operand(var->name())); | 4265 __ mov(r2, Operand(var->name())); |
| 4265 __ push(r2); | 4266 __ Push(context_register(), r2); |
| 4266 __ CallRuntime(Runtime::kDeleteContextSlot, 2); | 4267 __ CallRuntime(Runtime::kDeleteContextSlot, 2); |
| 4267 context()->Plug(r0); | 4268 context()->Plug(r0); |
| 4268 } | 4269 } |
| 4269 } else { | 4270 } else { |
| 4270 // Result of deleting non-property, non-variable reference is true. | 4271 // Result of deleting non-property, non-variable reference is true. |
| 4271 // The subexpression may have side effects. | 4272 // The subexpression may have side effects. |
| 4272 VisitForEffect(expr->expression()); | 4273 VisitForEffect(expr->expression()); |
| 4273 context()->Plug(true); | 4274 context()->Plug(true); |
| 4274 } | 4275 } |
| 4275 break; | 4276 break; |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4485 if (expr->is_postfix()) { | 4486 if (expr->is_postfix()) { |
| 4486 if (!context()->IsEffect()) { | 4487 if (!context()->IsEffect()) { |
| 4487 context()->PlugTOS(); | 4488 context()->PlugTOS(); |
| 4488 } | 4489 } |
| 4489 } else { | 4490 } else { |
| 4490 context()->Plug(r0); | 4491 context()->Plug(r0); |
| 4491 } | 4492 } |
| 4492 break; | 4493 break; |
| 4493 } | 4494 } |
| 4494 case KEYED_PROPERTY: { | 4495 case KEYED_PROPERTY: { |
| 4495 __ pop(r1); // Key. | 4496 __ Pop(r2, r1); // r1 = key. r2 = receiver. |
| 4496 __ pop(r2); // Receiver. | |
| 4497 Handle<Code> ic = is_classic_mode() | 4497 Handle<Code> ic = is_classic_mode() |
| 4498 ? isolate()->builtins()->KeyedStoreIC_Initialize() | 4498 ? isolate()->builtins()->KeyedStoreIC_Initialize() |
| 4499 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); | 4499 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); |
| 4500 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); | 4500 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); |
| 4501 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); | 4501 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); |
| 4502 if (expr->is_postfix()) { | 4502 if (expr->is_postfix()) { |
| 4503 if (!context()->IsEffect()) { | 4503 if (!context()->IsEffect()) { |
| 4504 context()->PlugTOS(); | 4504 context()->PlugTOS(); |
| 4505 } | 4505 } |
| 4506 } else { | 4506 } else { |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4959 ASSERT(Memory::uint32_at(interrupt_address_pointer) == | 4959 ASSERT(Memory::uint32_at(interrupt_address_pointer) == |
| 4960 reinterpret_cast<uint32_t>( | 4960 reinterpret_cast<uint32_t>( |
| 4961 isolate->builtins()->OsrAfterStackCheck()->entry())); | 4961 isolate->builtins()->OsrAfterStackCheck()->entry())); |
| 4962 return OSR_AFTER_STACK_CHECK; | 4962 return OSR_AFTER_STACK_CHECK; |
| 4963 } | 4963 } |
| 4964 | 4964 |
| 4965 | 4965 |
| 4966 } } // namespace v8::internal | 4966 } } // namespace v8::internal |
| 4967 | 4967 |
| 4968 #endif // V8_TARGET_ARCH_ARM | 4968 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |