Index: src/arm/virtual-frame-arm.cc |
diff --git a/src/arm/virtual-frame-arm.cc b/src/arm/virtual-frame-arm.cc |
deleted file mode 100644 |
index a852d6eedf0e093fd2015fac533c570e4840d191..0000000000000000000000000000000000000000 |
--- a/src/arm/virtual-frame-arm.cc |
+++ /dev/null |
@@ -1,843 +0,0 @@ |
-// Copyright 2009 the V8 project authors. All rights reserved. |
-// Redistribution and use in source and binary forms, with or without |
-// modification, are permitted provided that the following conditions are |
-// met: |
-// |
-// * Redistributions of source code must retain the above copyright |
-// notice, this list of conditions and the following disclaimer. |
-// * Redistributions in binary form must reproduce the above |
-// copyright notice, this list of conditions and the following |
-// disclaimer in the documentation and/or other materials provided |
-// with the distribution. |
-// * Neither the name of Google Inc. nor the names of its |
-// contributors may be used to endorse or promote products derived |
-// from this software without specific prior written permission. |
-// |
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
- |
-#include "v8.h" |
- |
-#if defined(V8_TARGET_ARCH_ARM) |
- |
-#include "codegen-inl.h" |
-#include "register-allocator-inl.h" |
-#include "scopes.h" |
-#include "virtual-frame-inl.h" |
- |
-namespace v8 { |
-namespace internal { |
- |
-#define __ ACCESS_MASM(masm()) |
- |
-void VirtualFrame::PopToR1R0() { |
- // Shuffle things around so the top of stack is in r0 and r1. |
- MergeTOSTo(R0_R1_TOS); |
- // Pop the two registers off the stack so they are detached from the frame. |
- LowerHeight(2); |
- top_of_stack_state_ = NO_TOS_REGISTERS; |
-} |
- |
- |
-void VirtualFrame::PopToR1() { |
- // Shuffle things around so the top of stack is only in r1. |
- MergeTOSTo(R1_TOS); |
- // Pop the register off the stack so it is detached from the frame. |
- LowerHeight(1); |
- top_of_stack_state_ = NO_TOS_REGISTERS; |
-} |
- |
- |
-void VirtualFrame::PopToR0() { |
- // Shuffle things around so the top of stack only in r0. |
- MergeTOSTo(R0_TOS); |
- // Pop the register off the stack so it is detached from the frame. |
- LowerHeight(1); |
- top_of_stack_state_ = NO_TOS_REGISTERS; |
-} |
- |
- |
-void VirtualFrame::MergeTo(const VirtualFrame* expected, Condition cond) { |
- if (Equals(expected)) return; |
- ASSERT((expected->tos_known_smi_map_ & tos_known_smi_map_) == |
- expected->tos_known_smi_map_); |
- ASSERT(expected->IsCompatibleWith(this)); |
- MergeTOSTo(expected->top_of_stack_state_, cond); |
- ASSERT(register_allocation_map_ == expected->register_allocation_map_); |
-} |
- |
- |
-void VirtualFrame::MergeTo(VirtualFrame* expected, Condition cond) { |
- if (Equals(expected)) return; |
- tos_known_smi_map_ &= expected->tos_known_smi_map_; |
- MergeTOSTo(expected->top_of_stack_state_, cond); |
- ASSERT(register_allocation_map_ == expected->register_allocation_map_); |
-} |
- |
- |
-void VirtualFrame::MergeTOSTo( |
- VirtualFrame::TopOfStack expected_top_of_stack_state, Condition cond) { |
-#define CASE_NUMBER(a, b) ((a) * TOS_STATES + (b)) |
- switch (CASE_NUMBER(top_of_stack_state_, expected_top_of_stack_state)) { |
- case CASE_NUMBER(NO_TOS_REGISTERS, NO_TOS_REGISTERS): |
- break; |
- case CASE_NUMBER(NO_TOS_REGISTERS, R0_TOS): |
- __ pop(r0, cond); |
- break; |
- case CASE_NUMBER(NO_TOS_REGISTERS, R1_TOS): |
- __ pop(r1, cond); |
- break; |
- case CASE_NUMBER(NO_TOS_REGISTERS, R0_R1_TOS): |
- __ pop(r0, cond); |
- __ pop(r1, cond); |
- break; |
- case CASE_NUMBER(NO_TOS_REGISTERS, R1_R0_TOS): |
- __ pop(r1, cond); |
- __ pop(r0, cond); |
- break; |
- case CASE_NUMBER(R0_TOS, NO_TOS_REGISTERS): |
- __ push(r0, cond); |
- break; |
- case CASE_NUMBER(R0_TOS, R0_TOS): |
- break; |
- case CASE_NUMBER(R0_TOS, R1_TOS): |
- __ mov(r1, r0, LeaveCC, cond); |
- break; |
- case CASE_NUMBER(R0_TOS, R0_R1_TOS): |
- __ pop(r1, cond); |
- break; |
- case CASE_NUMBER(R0_TOS, R1_R0_TOS): |
- __ mov(r1, r0, LeaveCC, cond); |
- __ pop(r0, cond); |
- break; |
- case CASE_NUMBER(R1_TOS, NO_TOS_REGISTERS): |
- __ push(r1, cond); |
- break; |
- case CASE_NUMBER(R1_TOS, R0_TOS): |
- __ mov(r0, r1, LeaveCC, cond); |
- break; |
- case CASE_NUMBER(R1_TOS, R1_TOS): |
- break; |
- case CASE_NUMBER(R1_TOS, R0_R1_TOS): |
- __ mov(r0, r1, LeaveCC, cond); |
- __ pop(r1, cond); |
- break; |
- case CASE_NUMBER(R1_TOS, R1_R0_TOS): |
- __ pop(r0, cond); |
- break; |
- case CASE_NUMBER(R0_R1_TOS, NO_TOS_REGISTERS): |
- __ Push(r1, r0, cond); |
- break; |
- case CASE_NUMBER(R0_R1_TOS, R0_TOS): |
- __ push(r1, cond); |
- break; |
- case CASE_NUMBER(R0_R1_TOS, R1_TOS): |
- __ push(r1, cond); |
- __ mov(r1, r0, LeaveCC, cond); |
- break; |
- case CASE_NUMBER(R0_R1_TOS, R0_R1_TOS): |
- break; |
- case CASE_NUMBER(R0_R1_TOS, R1_R0_TOS): |
- __ Swap(r0, r1, ip, cond); |
- break; |
- case CASE_NUMBER(R1_R0_TOS, NO_TOS_REGISTERS): |
- __ Push(r0, r1, cond); |
- break; |
- case CASE_NUMBER(R1_R0_TOS, R0_TOS): |
- __ push(r0, cond); |
- __ mov(r0, r1, LeaveCC, cond); |
- break; |
- case CASE_NUMBER(R1_R0_TOS, R1_TOS): |
- __ push(r0, cond); |
- break; |
- case CASE_NUMBER(R1_R0_TOS, R0_R1_TOS): |
- __ Swap(r0, r1, ip, cond); |
- break; |
- case CASE_NUMBER(R1_R0_TOS, R1_R0_TOS): |
- break; |
- default: |
- UNREACHABLE(); |
-#undef CASE_NUMBER |
- } |
- // A conditional merge will be followed by a conditional branch and the |
- // fall-through code will have an unchanged virtual frame state. If the |
- // merge is unconditional ('al'ways) then it might be followed by a fall |
- // through. We need to update the virtual frame state to match the code we |
- // are falling into. The final case is an unconditional merge followed by an |
- // unconditional branch, in which case it doesn't matter what we do to the |
- // virtual frame state, because the virtual frame will be invalidated. |
- if (cond == al) { |
- top_of_stack_state_ = expected_top_of_stack_state; |
- } |
-} |
- |
- |
-void VirtualFrame::Enter() { |
- Comment cmnt(masm(), "[ Enter JS frame"); |
- |
-#ifdef DEBUG |
- // Verify that r1 contains a JS function. The following code relies |
- // on r2 being available for use. |
- if (FLAG_debug_code) { |
- Label map_check, done; |
- __ tst(r1, Operand(kSmiTagMask)); |
- __ b(ne, &map_check); |
- __ stop("VirtualFrame::Enter - r1 is not a function (smi check)."); |
- __ bind(&map_check); |
- __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
- __ b(eq, &done); |
- __ stop("VirtualFrame::Enter - r1 is not a function (map check)."); |
- __ bind(&done); |
- } |
-#endif // DEBUG |
- |
- // We are about to push four values to the frame. |
- Adjust(4); |
- __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
- // Adjust FP to point to saved FP. |
- __ add(fp, sp, Operand(2 * kPointerSize)); |
-} |
- |
- |
-void VirtualFrame::Exit() { |
- Comment cmnt(masm(), "[ Exit JS frame"); |
- // Record the location of the JS exit code for patching when setting |
- // break point. |
- __ RecordJSReturn(); |
- |
- // Drop the execution stack down to the frame pointer and restore the caller |
- // frame pointer and return address. |
- __ mov(sp, fp); |
- __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
-} |
- |
- |
-void VirtualFrame::AllocateStackSlots() { |
- int count = local_count(); |
- if (count > 0) { |
- Comment cmnt(masm(), "[ Allocate space for locals"); |
- Adjust(count); |
- // Initialize stack slots with 'undefined' value. |
- __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
- __ LoadRoot(r2, Heap::kStackLimitRootIndex); |
- if (count < kLocalVarBound) { |
- // For less locals the unrolled loop is more compact. |
- for (int i = 0; i < count; i++) { |
- __ push(ip); |
- } |
- } else { |
- // For more locals a loop in generated code is more compact. |
- Label alloc_locals_loop; |
- __ mov(r1, Operand(count)); |
- __ bind(&alloc_locals_loop); |
- __ push(ip); |
- __ sub(r1, r1, Operand(1), SetCC); |
- __ b(ne, &alloc_locals_loop); |
- } |
- } else { |
- __ LoadRoot(r2, Heap::kStackLimitRootIndex); |
- } |
- // Check the stack for overflow or a break request. |
- masm()->cmp(sp, Operand(r2)); |
- StackCheckStub stub; |
- // Call the stub if lower. |
- masm()->mov(ip, |
- Operand(reinterpret_cast<intptr_t>(stub.GetCode().location()), |
- RelocInfo::CODE_TARGET), |
- LeaveCC, |
- lo); |
- masm()->Call(ip, lo); |
-} |
- |
- |
- |
-void VirtualFrame::PushReceiverSlotAddress() { |
- UNIMPLEMENTED(); |
-} |
- |
- |
-void VirtualFrame::PushTryHandler(HandlerType type) { |
- // Grow the expression stack by handler size less one (the return |
- // address in lr is already counted by a call instruction). |
- Adjust(kHandlerSize - 1); |
- __ PushTryHandler(IN_JAVASCRIPT, type); |
-} |
- |
- |
-void VirtualFrame::CallJSFunction(int arg_count) { |
- // InvokeFunction requires function in r1. |
- PopToR1(); |
- SpillAll(); |
- |
- // +1 for receiver. |
- Forget(arg_count + 1); |
- ASSERT(cgen()->HasValidEntryRegisters()); |
- ParameterCount count(arg_count); |
- __ InvokeFunction(r1, count, CALL_FUNCTION); |
- // Restore the context. |
- __ ldr(cp, Context()); |
-} |
- |
- |
-void VirtualFrame::CallRuntime(const Runtime::Function* f, int arg_count) { |
- SpillAll(); |
- Forget(arg_count); |
- ASSERT(cgen()->HasValidEntryRegisters()); |
- __ CallRuntime(f, arg_count); |
-} |
- |
- |
-void VirtualFrame::CallRuntime(Runtime::FunctionId id, int arg_count) { |
- SpillAll(); |
- Forget(arg_count); |
- ASSERT(cgen()->HasValidEntryRegisters()); |
- __ CallRuntime(id, arg_count); |
-} |
- |
- |
-#ifdef ENABLE_DEBUGGER_SUPPORT |
-void VirtualFrame::DebugBreak() { |
- ASSERT(cgen()->HasValidEntryRegisters()); |
- __ DebugBreak(); |
-} |
-#endif |
- |
- |
-void VirtualFrame::InvokeBuiltin(Builtins::JavaScript id, |
- InvokeJSFlags flags, |
- int arg_count) { |
- Forget(arg_count); |
- __ InvokeBuiltin(id, flags); |
-} |
- |
- |
-void VirtualFrame::CallLoadIC(Handle<String> name, RelocInfo::Mode mode) { |
- Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
- Builtins::kLoadIC_Initialize)); |
- PopToR0(); |
- SpillAll(); |
- __ mov(r2, Operand(name)); |
- CallCodeObject(ic, mode, 0); |
-} |
- |
- |
-void VirtualFrame::CallStoreIC(Handle<String> name, |
- bool is_contextual, |
- StrictModeFlag strict_mode) { |
- Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
- (strict_mode == kStrictMode) ? Builtins::kStoreIC_Initialize_Strict |
- : Builtins::kStoreIC_Initialize)); |
- PopToR0(); |
- RelocInfo::Mode mode; |
- if (is_contextual) { |
- SpillAll(); |
- __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
- mode = RelocInfo::CODE_TARGET_CONTEXT; |
- } else { |
- EmitPop(r1); |
- SpillAll(); |
- mode = RelocInfo::CODE_TARGET; |
- } |
- __ mov(r2, Operand(name)); |
- CallCodeObject(ic, mode, 0); |
-} |
- |
- |
-void VirtualFrame::CallKeyedLoadIC() { |
- Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
- Builtins::kKeyedLoadIC_Initialize)); |
- PopToR1R0(); |
- SpillAll(); |
- CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); |
-} |
- |
- |
-void VirtualFrame::CallKeyedStoreIC(StrictModeFlag strict_mode) { |
- Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
- (strict_mode == kStrictMode) ? Builtins::kKeyedStoreIC_Initialize_Strict |
- : Builtins::kKeyedStoreIC_Initialize)); |
- PopToR1R0(); |
- SpillAll(); |
- EmitPop(r2); |
- CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); |
-} |
- |
- |
-void VirtualFrame::CallCodeObject(Handle<Code> code, |
- RelocInfo::Mode rmode, |
- int dropped_args) { |
- switch (code->kind()) { |
- case Code::CALL_IC: |
- case Code::KEYED_CALL_IC: |
- case Code::FUNCTION: |
- break; |
- case Code::KEYED_LOAD_IC: |
- case Code::LOAD_IC: |
- case Code::KEYED_STORE_IC: |
- case Code::STORE_IC: |
- ASSERT(dropped_args == 0); |
- break; |
- case Code::BUILTIN: |
- ASSERT(*code == Isolate::Current()->builtins()->builtin( |
- Builtins::kJSConstructCall)); |
- break; |
- default: |
- UNREACHABLE(); |
- break; |
- } |
- Forget(dropped_args); |
- ASSERT(cgen()->HasValidEntryRegisters()); |
- __ Call(code, rmode); |
-} |
- |
- |
-// NO_TOS_REGISTERS, R0_TOS, R1_TOS, R1_R0_TOS, R0_R1_TOS. |
-const bool VirtualFrame::kR0InUse[TOS_STATES] = |
- { false, true, false, true, true }; |
-const bool VirtualFrame::kR1InUse[TOS_STATES] = |
- { false, false, true, true, true }; |
-const int VirtualFrame::kVirtualElements[TOS_STATES] = |
- { 0, 1, 1, 2, 2 }; |
-const Register VirtualFrame::kTopRegister[TOS_STATES] = |
- { r0, r0, r1, r1, r0 }; |
-const Register VirtualFrame::kBottomRegister[TOS_STATES] = |
- { r0, r0, r1, r0, r1 }; |
-const Register VirtualFrame::kAllocatedRegisters[ |
- VirtualFrame::kNumberOfAllocatedRegisters] = { r2, r3, r4, r5, r6 }; |
-// Popping is done by the transition implied by kStateAfterPop. Of course if |
-// there were no stack slots allocated to registers then the physical SP must |
-// be adjusted. |
-const VirtualFrame::TopOfStack VirtualFrame::kStateAfterPop[TOS_STATES] = |
- { NO_TOS_REGISTERS, NO_TOS_REGISTERS, NO_TOS_REGISTERS, R0_TOS, R1_TOS }; |
-// Pushing is done by the transition implied by kStateAfterPush. Of course if |
-// the maximum number of registers was already allocated to the top of stack |
-// slots then one register must be physically pushed onto the stack. |
-const VirtualFrame::TopOfStack VirtualFrame::kStateAfterPush[TOS_STATES] = |
- { R0_TOS, R1_R0_TOS, R0_R1_TOS, R0_R1_TOS, R1_R0_TOS }; |
- |
- |
-void VirtualFrame::Drop(int count) { |
- ASSERT(count >= 0); |
- ASSERT(height() >= count); |
- // Discard elements from the virtual frame and free any registers. |
- int num_virtual_elements = kVirtualElements[top_of_stack_state_]; |
- while (num_virtual_elements > 0) { |
- Pop(); |
- num_virtual_elements--; |
- count--; |
- if (count == 0) return; |
- } |
- if (count == 0) return; |
- __ add(sp, sp, Operand(count * kPointerSize)); |
- LowerHeight(count); |
-} |
- |
- |
-void VirtualFrame::Pop() { |
- if (top_of_stack_state_ == NO_TOS_REGISTERS) { |
- __ add(sp, sp, Operand(kPointerSize)); |
- } else { |
- top_of_stack_state_ = kStateAfterPop[top_of_stack_state_]; |
- } |
- LowerHeight(1); |
-} |
- |
- |
-void VirtualFrame::EmitPop(Register reg) { |
- ASSERT(!is_used(RegisterAllocator::ToNumber(reg))); |
- if (top_of_stack_state_ == NO_TOS_REGISTERS) { |
- __ pop(reg); |
- } else { |
- __ mov(reg, kTopRegister[top_of_stack_state_]); |
- top_of_stack_state_ = kStateAfterPop[top_of_stack_state_]; |
- } |
- LowerHeight(1); |
-} |
- |
- |
-void VirtualFrame::SpillAllButCopyTOSToR0() { |
- switch (top_of_stack_state_) { |
- case NO_TOS_REGISTERS: |
- __ ldr(r0, MemOperand(sp, 0)); |
- break; |
- case R0_TOS: |
- __ push(r0); |
- break; |
- case R1_TOS: |
- __ push(r1); |
- __ mov(r0, r1); |
- break; |
- case R0_R1_TOS: |
- __ Push(r1, r0); |
- break; |
- case R1_R0_TOS: |
- __ Push(r0, r1); |
- __ mov(r0, r1); |
- break; |
- default: |
- UNREACHABLE(); |
- } |
- top_of_stack_state_ = NO_TOS_REGISTERS; |
-} |
- |
- |
-void VirtualFrame::SpillAllButCopyTOSToR1() { |
- switch (top_of_stack_state_) { |
- case NO_TOS_REGISTERS: |
- __ ldr(r1, MemOperand(sp, 0)); |
- break; |
- case R0_TOS: |
- __ push(r0); |
- __ mov(r1, r0); |
- break; |
- case R1_TOS: |
- __ push(r1); |
- break; |
- case R0_R1_TOS: |
- __ Push(r1, r0); |
- __ mov(r1, r0); |
- break; |
- case R1_R0_TOS: |
- __ Push(r0, r1); |
- break; |
- default: |
- UNREACHABLE(); |
- } |
- top_of_stack_state_ = NO_TOS_REGISTERS; |
-} |
- |
- |
-void VirtualFrame::SpillAllButCopyTOSToR1R0() { |
- switch (top_of_stack_state_) { |
- case NO_TOS_REGISTERS: |
- __ ldr(r1, MemOperand(sp, 0)); |
- __ ldr(r0, MemOperand(sp, kPointerSize)); |
- break; |
- case R0_TOS: |
- __ push(r0); |
- __ mov(r1, r0); |
- __ ldr(r0, MemOperand(sp, kPointerSize)); |
- break; |
- case R1_TOS: |
- __ push(r1); |
- __ ldr(r0, MemOperand(sp, kPointerSize)); |
- break; |
- case R0_R1_TOS: |
- __ Push(r1, r0); |
- __ Swap(r0, r1, ip); |
- break; |
- case R1_R0_TOS: |
- __ Push(r0, r1); |
- break; |
- default: |
- UNREACHABLE(); |
- } |
- top_of_stack_state_ = NO_TOS_REGISTERS; |
-} |
- |
- |
-Register VirtualFrame::Peek() { |
- AssertIsNotSpilled(); |
- if (top_of_stack_state_ == NO_TOS_REGISTERS) { |
- top_of_stack_state_ = kStateAfterPush[top_of_stack_state_]; |
- Register answer = kTopRegister[top_of_stack_state_]; |
- __ pop(answer); |
- return answer; |
- } else { |
- return kTopRegister[top_of_stack_state_]; |
- } |
-} |
- |
- |
-Register VirtualFrame::Peek2() { |
- AssertIsNotSpilled(); |
- switch (top_of_stack_state_) { |
- case NO_TOS_REGISTERS: |
- case R0_TOS: |
- case R0_R1_TOS: |
- MergeTOSTo(R0_R1_TOS); |
- return r1; |
- case R1_TOS: |
- case R1_R0_TOS: |
- MergeTOSTo(R1_R0_TOS); |
- return r0; |
- default: |
- UNREACHABLE(); |
- return no_reg; |
- } |
-} |
- |
- |
-void VirtualFrame::Dup() { |
- if (SpilledScope::is_spilled()) { |
- __ ldr(ip, MemOperand(sp, 0)); |
- __ push(ip); |
- } else { |
- switch (top_of_stack_state_) { |
- case NO_TOS_REGISTERS: |
- __ ldr(r0, MemOperand(sp, 0)); |
- top_of_stack_state_ = R0_TOS; |
- break; |
- case R0_TOS: |
- __ mov(r1, r0); |
- // r0 and r1 contains the same value. Prefer state with r0 holding TOS. |
- top_of_stack_state_ = R0_R1_TOS; |
- break; |
- case R1_TOS: |
- __ mov(r0, r1); |
- // r0 and r1 contains the same value. Prefer state with r0 holding TOS. |
- top_of_stack_state_ = R0_R1_TOS; |
- break; |
- case R0_R1_TOS: |
- __ push(r1); |
- __ mov(r1, r0); |
- // r0 and r1 contains the same value. Prefer state with r0 holding TOS. |
- top_of_stack_state_ = R0_R1_TOS; |
- break; |
- case R1_R0_TOS: |
- __ push(r0); |
- __ mov(r0, r1); |
- // r0 and r1 contains the same value. Prefer state with r0 holding TOS. |
- top_of_stack_state_ = R0_R1_TOS; |
- break; |
- default: |
- UNREACHABLE(); |
- } |
- } |
- RaiseHeight(1, tos_known_smi_map_ & 1); |
-} |
- |
- |
-void VirtualFrame::Dup2() { |
- if (SpilledScope::is_spilled()) { |
- __ ldr(ip, MemOperand(sp, kPointerSize)); |
- __ push(ip); |
- __ ldr(ip, MemOperand(sp, kPointerSize)); |
- __ push(ip); |
- } else { |
- switch (top_of_stack_state_) { |
- case NO_TOS_REGISTERS: |
- __ ldr(r0, MemOperand(sp, 0)); |
- __ ldr(r1, MemOperand(sp, kPointerSize)); |
- top_of_stack_state_ = R0_R1_TOS; |
- break; |
- case R0_TOS: |
- __ push(r0); |
- __ ldr(r1, MemOperand(sp, kPointerSize)); |
- top_of_stack_state_ = R0_R1_TOS; |
- break; |
- case R1_TOS: |
- __ push(r1); |
- __ ldr(r0, MemOperand(sp, kPointerSize)); |
- top_of_stack_state_ = R1_R0_TOS; |
- break; |
- case R0_R1_TOS: |
- __ Push(r1, r0); |
- top_of_stack_state_ = R0_R1_TOS; |
- break; |
- case R1_R0_TOS: |
- __ Push(r0, r1); |
- top_of_stack_state_ = R1_R0_TOS; |
- break; |
- default: |
- UNREACHABLE(); |
- } |
- } |
- RaiseHeight(2, tos_known_smi_map_ & 3); |
-} |
- |
- |
-Register VirtualFrame::PopToRegister(Register but_not_to_this_one) { |
- ASSERT(but_not_to_this_one.is(r0) || |
- but_not_to_this_one.is(r1) || |
- but_not_to_this_one.is(no_reg)); |
- LowerHeight(1); |
- if (top_of_stack_state_ == NO_TOS_REGISTERS) { |
- if (but_not_to_this_one.is(r0)) { |
- __ pop(r1); |
- return r1; |
- } else { |
- __ pop(r0); |
- return r0; |
- } |
- } else { |
- Register answer = kTopRegister[top_of_stack_state_]; |
- ASSERT(!answer.is(but_not_to_this_one)); |
- top_of_stack_state_ = kStateAfterPop[top_of_stack_state_]; |
- return answer; |
- } |
-} |
- |
- |
-void VirtualFrame::EnsureOneFreeTOSRegister() { |
- if (kVirtualElements[top_of_stack_state_] == kMaxTOSRegisters) { |
- __ push(kBottomRegister[top_of_stack_state_]); |
- top_of_stack_state_ = kStateAfterPush[top_of_stack_state_]; |
- top_of_stack_state_ = kStateAfterPop[top_of_stack_state_]; |
- } |
- ASSERT(kVirtualElements[top_of_stack_state_] != kMaxTOSRegisters); |
-} |
- |
- |
-void VirtualFrame::EmitPush(Register reg, TypeInfo info) { |
- RaiseHeight(1, info.IsSmi() ? 1 : 0); |
- if (reg.is(cp)) { |
- // If we are pushing cp then we are about to make a call and things have to |
- // be pushed to the physical stack. There's nothing to be gained my moving |
- // to a TOS register and then pushing that, we might as well push to the |
- // physical stack immediately. |
- MergeTOSTo(NO_TOS_REGISTERS); |
- __ push(reg); |
- return; |
- } |
- if (SpilledScope::is_spilled()) { |
- ASSERT(top_of_stack_state_ == NO_TOS_REGISTERS); |
- __ push(reg); |
- return; |
- } |
- if (top_of_stack_state_ == NO_TOS_REGISTERS) { |
- if (reg.is(r0)) { |
- top_of_stack_state_ = R0_TOS; |
- return; |
- } |
- if (reg.is(r1)) { |
- top_of_stack_state_ = R1_TOS; |
- return; |
- } |
- } |
- EnsureOneFreeTOSRegister(); |
- top_of_stack_state_ = kStateAfterPush[top_of_stack_state_]; |
- Register dest = kTopRegister[top_of_stack_state_]; |
- __ Move(dest, reg); |
-} |
- |
- |
-void VirtualFrame::SetElementAt(Register reg, int this_far_down) { |
- if (this_far_down < kTOSKnownSmiMapSize) { |
- tos_known_smi_map_ &= ~(1 << this_far_down); |
- } |
- if (this_far_down == 0) { |
- Pop(); |
- Register dest = GetTOSRegister(); |
- if (dest.is(reg)) { |
- // We already popped one item off the top of the stack. If the only |
- // free register is the one we were asked to push then we have been |
- // asked to push a register that was already in use, which cannot |
- // happen. It therefore folows that there are two free TOS registers: |
- ASSERT(top_of_stack_state_ == NO_TOS_REGISTERS); |
- dest = dest.is(r0) ? r1 : r0; |
- } |
- __ mov(dest, reg); |
- EmitPush(dest); |
- } else if (this_far_down == 1) { |
- int virtual_elements = kVirtualElements[top_of_stack_state_]; |
- if (virtual_elements < 2) { |
- __ str(reg, ElementAt(this_far_down)); |
- } else { |
- ASSERT(virtual_elements == 2); |
- ASSERT(!reg.is(r0)); |
- ASSERT(!reg.is(r1)); |
- Register dest = kBottomRegister[top_of_stack_state_]; |
- __ mov(dest, reg); |
- } |
- } else { |
- ASSERT(this_far_down >= 2); |
- ASSERT(kVirtualElements[top_of_stack_state_] <= 2); |
- __ str(reg, ElementAt(this_far_down)); |
- } |
-} |
- |
- |
-Register VirtualFrame::GetTOSRegister() { |
- if (SpilledScope::is_spilled()) return r0; |
- |
- EnsureOneFreeTOSRegister(); |
- return kTopRegister[kStateAfterPush[top_of_stack_state_]]; |
-} |
- |
- |
-void VirtualFrame::EmitPush(Operand operand, TypeInfo info) { |
- RaiseHeight(1, info.IsSmi() ? 1 : 0); |
- if (SpilledScope::is_spilled()) { |
- __ mov(r0, operand); |
- __ push(r0); |
- return; |
- } |
- EnsureOneFreeTOSRegister(); |
- top_of_stack_state_ = kStateAfterPush[top_of_stack_state_]; |
- __ mov(kTopRegister[top_of_stack_state_], operand); |
-} |
- |
- |
-void VirtualFrame::EmitPush(MemOperand operand, TypeInfo info) { |
- RaiseHeight(1, info.IsSmi() ? 1 : 0); |
- if (SpilledScope::is_spilled()) { |
- __ ldr(r0, operand); |
- __ push(r0); |
- return; |
- } |
- EnsureOneFreeTOSRegister(); |
- top_of_stack_state_ = kStateAfterPush[top_of_stack_state_]; |
- __ ldr(kTopRegister[top_of_stack_state_], operand); |
-} |
- |
- |
-void VirtualFrame::EmitPushRoot(Heap::RootListIndex index) { |
- RaiseHeight(1, 0); |
- if (SpilledScope::is_spilled()) { |
- __ LoadRoot(r0, index); |
- __ push(r0); |
- return; |
- } |
- EnsureOneFreeTOSRegister(); |
- top_of_stack_state_ = kStateAfterPush[top_of_stack_state_]; |
- __ LoadRoot(kTopRegister[top_of_stack_state_], index); |
-} |
- |
- |
-void VirtualFrame::EmitPushMultiple(int count, int src_regs) { |
- ASSERT(SpilledScope::is_spilled()); |
- Adjust(count); |
- __ stm(db_w, sp, src_regs); |
-} |
- |
- |
-void VirtualFrame::SpillAll() { |
- switch (top_of_stack_state_) { |
- case R1_R0_TOS: |
- masm()->push(r0); |
- // Fall through. |
- case R1_TOS: |
- masm()->push(r1); |
- top_of_stack_state_ = NO_TOS_REGISTERS; |
- break; |
- case R0_R1_TOS: |
- masm()->push(r1); |
- // Fall through. |
- case R0_TOS: |
- masm()->push(r0); |
- top_of_stack_state_ = NO_TOS_REGISTERS; |
- // Fall through. |
- case NO_TOS_REGISTERS: |
- break; |
- default: |
- UNREACHABLE(); |
- break; |
- } |
- ASSERT(register_allocation_map_ == 0); // Not yet implemented. |
-} |
- |
-#undef __ |
- |
-} } // namespace v8::internal |
- |
-#endif // V8_TARGET_ARCH_ARM |