OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 1839 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1850 : KEYED_PROPERTY; | 1850 : KEYED_PROPERTY; |
1851 } | 1851 } |
1852 | 1852 |
1853 // Evaluate LHS expression. | 1853 // Evaluate LHS expression. |
1854 switch (assign_type) { | 1854 switch (assign_type) { |
1855 case VARIABLE: | 1855 case VARIABLE: |
1856 // Nothing to do here. | 1856 // Nothing to do here. |
1857 break; | 1857 break; |
1858 case NAMED_PROPERTY: | 1858 case NAMED_PROPERTY: |
1859 if (expr->is_compound()) { | 1859 if (expr->is_compound()) { |
1860 // We need the receiver both on the stack and in the accumulator. | 1860 // We need the receiver both on the stack and in the register. |
1861 VisitForAccumulatorValue(property->obj()); | 1861 VisitForStackValue(property->obj()); |
1862 __ push(result_register()); | 1862 __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); |
1863 } else { | 1863 } else { |
1864 VisitForStackValue(property->obj()); | 1864 VisitForStackValue(property->obj()); |
1865 } | 1865 } |
1866 break; | 1866 break; |
1867 case KEYED_PROPERTY: | 1867 case KEYED_PROPERTY: |
1868 if (expr->is_compound()) { | 1868 if (expr->is_compound()) { |
1869 VisitForStackValue(property->obj()); | 1869 VisitForStackValue(property->obj()); |
1870 VisitForAccumulatorValue(property->key()); | 1870 VisitForStackValue(property->key()); |
1871 __ ldr(r1, MemOperand(sp, 0)); | 1871 __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize)); |
1872 __ push(r0); | 1872 __ ldr(LoadIC::NameRegister(), MemOperand(sp, 0)); |
1873 } else { | 1873 } else { |
1874 VisitForStackValue(property->obj()); | 1874 VisitForStackValue(property->obj()); |
1875 VisitForStackValue(property->key()); | 1875 VisitForStackValue(property->key()); |
1876 } | 1876 } |
1877 break; | 1877 break; |
1878 } | 1878 } |
1879 | 1879 |
1880 // For compound assignments we need another deoptimization point after the | 1880 // For compound assignments we need another deoptimization point after the |
1881 // variable/property load. | 1881 // variable/property load. |
1882 if (expr->is_compound()) { | 1882 if (expr->is_compound()) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2001 | 2001 |
2002 case Yield::DELEGATING: { | 2002 case Yield::DELEGATING: { |
2003 VisitForStackValue(expr->generator_object()); | 2003 VisitForStackValue(expr->generator_object()); |
2004 | 2004 |
2005 // Initial stack layout is as follows: | 2005 // Initial stack layout is as follows: |
2006 // [sp + 1 * kPointerSize] iter | 2006 // [sp + 1 * kPointerSize] iter |
2007 // [sp + 0 * kPointerSize] g | 2007 // [sp + 0 * kPointerSize] g |
2008 | 2008 |
2009 Label l_catch, l_try, l_suspend, l_continuation, l_resume; | 2009 Label l_catch, l_try, l_suspend, l_continuation, l_resume; |
2010 Label l_next, l_call, l_loop; | 2010 Label l_next, l_call, l_loop; |
| 2011 Register load_receiver = LoadIC::ReceiverRegister(); |
| 2012 Register load_name = LoadIC::NameRegister(); |
| 2013 |
2011 // Initial send value is undefined. | 2014 // Initial send value is undefined. |
2012 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); | 2015 __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
2013 __ b(&l_next); | 2016 __ b(&l_next); |
2014 | 2017 |
2015 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } | 2018 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } |
2016 __ bind(&l_catch); | 2019 __ bind(&l_catch); |
2017 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); | 2020 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); |
2018 __ LoadRoot(r2, Heap::kthrow_stringRootIndex); // "throw" | 2021 __ LoadRoot(load_name, Heap::kthrow_stringRootIndex); // "throw" |
2019 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2022 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
2020 __ Push(r2, r3, r0); // "throw", iter, except | 2023 __ Push(load_name, r3, r0); // "throw", iter, except |
2021 __ jmp(&l_call); | 2024 __ jmp(&l_call); |
2022 | 2025 |
2023 // try { received = %yield result } | 2026 // try { received = %yield result } |
2024 // Shuffle the received result above a try handler and yield it without | 2027 // Shuffle the received result above a try handler and yield it without |
2025 // re-boxing. | 2028 // re-boxing. |
2026 __ bind(&l_try); | 2029 __ bind(&l_try); |
2027 __ pop(r0); // result | 2030 __ pop(r0); // result |
2028 __ PushTryHandler(StackHandler::CATCH, expr->index()); | 2031 __ PushTryHandler(StackHandler::CATCH, expr->index()); |
2029 const int handler_size = StackHandlerConstants::kSize; | 2032 const int handler_size = StackHandlerConstants::kSize; |
2030 __ push(r0); // result | 2033 __ push(r0); // result |
(...skipping 13 matching lines...) Expand all Loading... |
2044 kLRHasBeenSaved, kDontSaveFPRegs); | 2047 kLRHasBeenSaved, kDontSaveFPRegs); |
2045 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); | 2048 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); |
2046 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2049 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2047 __ pop(r0); // result | 2050 __ pop(r0); // result |
2048 EmitReturnSequence(); | 2051 EmitReturnSequence(); |
2049 __ bind(&l_resume); // received in r0 | 2052 __ bind(&l_resume); // received in r0 |
2050 __ PopTryHandler(); | 2053 __ PopTryHandler(); |
2051 | 2054 |
2052 // receiver = iter; f = 'next'; arg = received; | 2055 // receiver = iter; f = 'next'; arg = received; |
2053 __ bind(&l_next); | 2056 __ bind(&l_next); |
2054 Register keyedload_receiver = KeyedLoadIC::ReceiverRegister(); | |
2055 Register keyedload_name = KeyedLoadIC::NameRegister(); | |
2056 ASSERT(keyedload_receiver.is(r1)); | |
2057 ASSERT(keyedload_name.is(r0)); | |
2058 | 2057 |
2059 __ LoadRoot(r2, Heap::knext_stringRootIndex); // "next" | 2058 __ LoadRoot(load_name, Heap::knext_stringRootIndex); // "next" |
2060 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter | 2059 __ ldr(r3, MemOperand(sp, 1 * kPointerSize)); // iter |
2061 __ Push(r2, r3, r0); // "next", iter, received | 2060 __ Push(load_name, r3, r0); // "next", iter, received |
2062 | 2061 |
2063 // result = receiver[f](arg); | 2062 // result = receiver[f](arg); |
2064 __ bind(&l_call); | 2063 __ bind(&l_call); |
2065 __ ldr(keyedload_receiver, MemOperand(sp, kPointerSize)); | 2064 __ ldr(load_receiver, MemOperand(sp, kPointerSize)); |
2066 __ ldr(keyedload_name, MemOperand(sp, 2 * kPointerSize)); | 2065 __ ldr(load_name, MemOperand(sp, 2 * kPointerSize)); |
2067 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 2066 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
2068 CallIC(ic, TypeFeedbackId::None()); | 2067 CallIC(ic, TypeFeedbackId::None()); |
2069 __ mov(r1, r0); | 2068 __ mov(r1, r0); |
2070 __ str(r1, MemOperand(sp, 2 * kPointerSize)); | 2069 __ str(r1, MemOperand(sp, 2 * kPointerSize)); |
2071 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); | 2070 CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD); |
2072 __ CallStub(&stub); | 2071 __ CallStub(&stub); |
2073 | 2072 |
2074 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 2073 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
2075 __ Drop(1); // The function is still on the stack; drop it. | 2074 __ Drop(1); // The function is still on the stack; drop it. |
2076 | 2075 |
2077 // if (!result.done) goto l_try; | 2076 // if (!result.done) goto l_try; |
2078 __ bind(&l_loop); | 2077 __ bind(&l_loop); |
2079 Register load_receiver = LoadIC::ReceiverRegister(); | 2078 __ Move(load_receiver, r0); |
2080 Register load_name = LoadIC::NameRegister(); | |
2081 ASSERT(load_receiver.is(r0)); | |
2082 ASSERT(load_name.is(r2)); | |
2083 | 2079 |
2084 __ push(load_receiver); // save result | 2080 __ push(load_receiver); // save result |
2085 __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" | 2081 __ LoadRoot(load_name, Heap::kdone_stringRootIndex); // "done" |
2086 CallLoadIC(NOT_CONTEXTUAL); // r0=result.done | 2082 CallLoadIC(NOT_CONTEXTUAL); // r0=result.done |
2087 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); | 2083 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); |
2088 CallIC(bool_ic); | 2084 CallIC(bool_ic); |
2089 __ cmp(r0, Operand(0)); | 2085 __ cmp(r0, Operand(0)); |
2090 __ b(eq, &l_try); | 2086 __ b(eq, &l_try); |
2091 | 2087 |
2092 // result.value | 2088 // result.value |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2556 context()->Plug(r0); | 2552 context()->Plug(r0); |
2557 } | 2553 } |
2558 | 2554 |
2559 | 2555 |
2560 void FullCodeGenerator::VisitProperty(Property* expr) { | 2556 void FullCodeGenerator::VisitProperty(Property* expr) { |
2561 Comment cmnt(masm_, "[ Property"); | 2557 Comment cmnt(masm_, "[ Property"); |
2562 Expression* key = expr->key(); | 2558 Expression* key = expr->key(); |
2563 | 2559 |
2564 if (key->IsPropertyName()) { | 2560 if (key->IsPropertyName()) { |
2565 VisitForAccumulatorValue(expr->obj()); | 2561 VisitForAccumulatorValue(expr->obj()); |
2566 ASSERT(r0.is(LoadIC::ReceiverRegister())); | 2562 __ Move(LoadIC::ReceiverRegister(), r0); |
2567 EmitNamedPropertyLoad(expr); | 2563 EmitNamedPropertyLoad(expr); |
2568 PrepareForBailoutForId(expr->LoadId(), TOS_REG); | 2564 PrepareForBailoutForId(expr->LoadId(), TOS_REG); |
2569 context()->Plug(r0); | 2565 context()->Plug(r0); |
2570 } else { | 2566 } else { |
2571 VisitForStackValue(expr->obj()); | 2567 VisitForStackValue(expr->obj()); |
2572 VisitForAccumulatorValue(expr->key()); | 2568 VisitForAccumulatorValue(expr->key()); |
2573 ASSERT(r0.is(KeyedLoadIC::NameRegister())); | 2569 __ Move(LoadIC::NameRegister(), r0); |
2574 __ pop(KeyedLoadIC::ReceiverRegister()); | 2570 __ pop(LoadIC::ReceiverRegister()); |
2575 EmitKeyedPropertyLoad(expr); | 2571 EmitKeyedPropertyLoad(expr); |
2576 context()->Plug(r0); | 2572 context()->Plug(r0); |
2577 } | 2573 } |
2578 } | 2574 } |
2579 | 2575 |
2580 | 2576 |
2581 void FullCodeGenerator::CallIC(Handle<Code> code, | 2577 void FullCodeGenerator::CallIC(Handle<Code> code, |
2582 TypeFeedbackId ast_id) { | 2578 TypeFeedbackId ast_id) { |
2583 ic_total_count_++; | 2579 ic_total_count_++; |
2584 // All calls must have a predictable size in full-codegen code to ensure that | 2580 // All calls must have a predictable size in full-codegen code to ensure that |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2619 | 2615 |
2620 EmitCall(expr, call_type); | 2616 EmitCall(expr, call_type); |
2621 } | 2617 } |
2622 | 2618 |
2623 | 2619 |
2624 // Code common for calls using the IC. | 2620 // Code common for calls using the IC. |
2625 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, | 2621 void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr, |
2626 Expression* key) { | 2622 Expression* key) { |
2627 // Load the key. | 2623 // Load the key. |
2628 VisitForAccumulatorValue(key); | 2624 VisitForAccumulatorValue(key); |
2629 ASSERT(r0.is(KeyedLoadIC::NameRegister())); | |
2630 | 2625 |
2631 Expression* callee = expr->expression(); | 2626 Expression* callee = expr->expression(); |
2632 | 2627 |
2633 // Load the function from the receiver. | 2628 // Load the function from the receiver. |
2634 ASSERT(callee->IsProperty()); | 2629 ASSERT(callee->IsProperty()); |
2635 __ ldr(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0)); | 2630 __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); |
| 2631 __ Move(LoadIC::NameRegister(), r0); |
2636 EmitKeyedPropertyLoad(callee->AsProperty()); | 2632 EmitKeyedPropertyLoad(callee->AsProperty()); |
2637 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); | 2633 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG); |
2638 | 2634 |
2639 // Push the target function under the receiver. | 2635 // Push the target function under the receiver. |
2640 __ ldr(ip, MemOperand(sp, 0)); | 2636 __ ldr(ip, MemOperand(sp, 0)); |
2641 __ push(ip); | 2637 __ push(ip); |
2642 __ str(r0, MemOperand(sp, kPointerSize)); | 2638 __ str(r0, MemOperand(sp, kPointerSize)); |
2643 | 2639 |
2644 EmitCall(expr, CallIC::METHOD); | 2640 EmitCall(expr, CallIC::METHOD); |
2645 } | 2641 } |
(...skipping 1392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4038 EmitInlineRuntimeCall(expr); | 4034 EmitInlineRuntimeCall(expr); |
4039 return; | 4035 return; |
4040 } | 4036 } |
4041 | 4037 |
4042 Comment cmnt(masm_, "[ CallRuntime"); | 4038 Comment cmnt(masm_, "[ CallRuntime"); |
4043 ZoneList<Expression*>* args = expr->arguments(); | 4039 ZoneList<Expression*>* args = expr->arguments(); |
4044 int arg_count = args->length(); | 4040 int arg_count = args->length(); |
4045 | 4041 |
4046 if (expr->is_jsruntime()) { | 4042 if (expr->is_jsruntime()) { |
4047 // Push the builtins object as the receiver. | 4043 // Push the builtins object as the receiver. |
4048 __ ldr(r0, GlobalObjectOperand()); | 4044 Register receiver = LoadIC::ReceiverRegister(); |
4049 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kBuiltinsOffset)); | 4045 __ ldr(receiver, GlobalObjectOperand()); |
4050 __ push(r0); | 4046 __ ldr(receiver, FieldMemOperand(receiver, GlobalObject::kBuiltinsOffset)); |
| 4047 __ push(receiver); |
4051 | 4048 |
4052 // Load the function from the receiver. | 4049 // Load the function from the receiver. |
4053 ASSERT(r0.is(LoadIC::ReceiverRegister())); | |
4054 __ mov(LoadIC::NameRegister(), Operand(expr->name())); | 4050 __ mov(LoadIC::NameRegister(), Operand(expr->name())); |
4055 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); | 4051 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); |
4056 | 4052 |
4057 // Push the target function under the receiver. | 4053 // Push the target function under the receiver. |
4058 __ ldr(ip, MemOperand(sp, 0)); | 4054 __ ldr(ip, MemOperand(sp, 0)); |
4059 __ push(ip); | 4055 __ push(ip); |
4060 __ str(r0, MemOperand(sp, kPointerSize)); | 4056 __ str(r0, MemOperand(sp, kPointerSize)); |
4061 | 4057 |
4062 // Push the arguments ("left-to-right"). | 4058 // Push the arguments ("left-to-right"). |
4063 int arg_count = args->length(); | 4059 int arg_count = args->length(); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4221 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); | 4217 ASSERT(expr->expression()->AsVariableProxy()->var() != NULL); |
4222 AccumulatorValueContext context(this); | 4218 AccumulatorValueContext context(this); |
4223 EmitVariableLoad(expr->expression()->AsVariableProxy()); | 4219 EmitVariableLoad(expr->expression()->AsVariableProxy()); |
4224 } else { | 4220 } else { |
4225 // Reserve space for result of postfix operation. | 4221 // Reserve space for result of postfix operation. |
4226 if (expr->is_postfix() && !context()->IsEffect()) { | 4222 if (expr->is_postfix() && !context()->IsEffect()) { |
4227 __ mov(ip, Operand(Smi::FromInt(0))); | 4223 __ mov(ip, Operand(Smi::FromInt(0))); |
4228 __ push(ip); | 4224 __ push(ip); |
4229 } | 4225 } |
4230 if (assign_type == NAMED_PROPERTY) { | 4226 if (assign_type == NAMED_PROPERTY) { |
4231 // Put the object both on the stack and in the accumulator. | 4227 // Put the object both on the stack and in the register. |
4232 VisitForAccumulatorValue(prop->obj()); | 4228 VisitForStackValue(prop->obj()); |
4233 ASSERT(r0.is(LoadIC::ReceiverRegister())); | 4229 __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 0)); |
4234 __ push(LoadIC::ReceiverRegister()); | |
4235 EmitNamedPropertyLoad(prop); | 4230 EmitNamedPropertyLoad(prop); |
4236 } else { | 4231 } else { |
4237 VisitForStackValue(prop->obj()); | 4232 VisitForStackValue(prop->obj()); |
4238 VisitForAccumulatorValue(prop->key()); | 4233 VisitForStackValue(prop->key()); |
4239 ASSERT(r0.is(KeyedLoadIC::NameRegister())); | 4234 __ ldr(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize)); |
4240 __ ldr(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0)); | 4235 __ ldr(LoadIC::NameRegister(), MemOperand(sp, 0)); |
4241 __ push(KeyedLoadIC::NameRegister()); | |
4242 EmitKeyedPropertyLoad(prop); | 4236 EmitKeyedPropertyLoad(prop); |
4243 } | 4237 } |
4244 } | 4238 } |
4245 | 4239 |
4246 // We need a second deoptimization point after loading the value | 4240 // We need a second deoptimization point after loading the value |
4247 // in case evaluating the property load my have a side effect. | 4241 // in case evaluating the property load my have a side effect. |
4248 if (assign_type == VARIABLE) { | 4242 if (assign_type == VARIABLE) { |
4249 PrepareForBailout(expr->expression(), TOS_REG); | 4243 PrepareForBailout(expr->expression(), TOS_REG); |
4250 } else { | 4244 } else { |
4251 PrepareForBailoutForId(prop->LoadId(), TOS_REG); | 4245 PrepareForBailoutForId(prop->LoadId(), TOS_REG); |
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4835 | 4829 |
4836 ASSERT(interrupt_address == | 4830 ASSERT(interrupt_address == |
4837 isolate->builtins()->OsrAfterStackCheck()->entry()); | 4831 isolate->builtins()->OsrAfterStackCheck()->entry()); |
4838 return OSR_AFTER_STACK_CHECK; | 4832 return OSR_AFTER_STACK_CHECK; |
4839 } | 4833 } |
4840 | 4834 |
4841 | 4835 |
4842 } } // namespace v8::internal | 4836 } } // namespace v8::internal |
4843 | 4837 |
4844 #endif // V8_TARGET_ARCH_ARM | 4838 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |