Change the register allocator so that it no longer tracks references

to the platform-specific reserved registers.  They are always in use
for their intended purpose, cannot appear in the virtual frame, and
can be freely used without allocation in the code generator.

Review URL: http://codereview.chromium.org/113837

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2061 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 94524539
...@@ -84,8 +84,6 @@ struct Register { ...@@ -84,8 +84,6 @@ struct Register {
}; };
const int kNumRegisters = 16;
extern Register no_reg; extern Register no_reg;
extern Register r0; extern Register r0;
extern Register r1; extern Register r1;
......
...@@ -80,7 +80,7 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) { ...@@ -80,7 +80,7 @@ void JumpTarget::DoBranch(Condition cc, Hint ignored) {
// branch. // branch.
VirtualFrame* fall_through_frame = cgen()->frame(); VirtualFrame* fall_through_frame = cgen()->frame();
VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame); VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame);
RegisterFile non_frame_registers = RegisterAllocator::Reserved(); RegisterFile non_frame_registers;
cgen()->SetFrame(branch_frame, &non_frame_registers); cgen()->SetFrame(branch_frame, &non_frame_registers);
// Check if we can avoid merge code. // Check if we can avoid merge code.
...@@ -163,8 +163,7 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -163,8 +163,7 @@ void JumpTarget::DoBind(int mergable_elements) {
// virtual frame before the bind. Afterward, it should not. // virtual frame before the bind. Afterward, it should not.
ASSERT(cgen()->has_valid_frame()); ASSERT(cgen()->has_valid_frame());
VirtualFrame* frame = cgen()->frame(); VirtualFrame* frame = cgen()->frame();
int difference = int difference = frame->stack_pointer_ - (frame->element_count() - 1);
frame->stack_pointer_ - (frame->elements_.length() - 1);
if (difference > 0) { if (difference > 0) {
frame->stack_pointer_ -= difference; frame->stack_pointer_ -= difference;
__ add(sp, sp, Operand(difference * kPointerSize)); __ add(sp, sp, Operand(difference * kPointerSize));
...@@ -179,15 +178,14 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -179,15 +178,14 @@ void JumpTarget::DoBind(int mergable_elements) {
// Pick up the only reaching frame, take ownership of it, and // Pick up the only reaching frame, take ownership of it, and
// use it for the block about to be emitted. // use it for the block about to be emitted.
VirtualFrame* frame = reaching_frames_[0]; VirtualFrame* frame = reaching_frames_[0];
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
cgen()->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &empty);
reaching_frames_[0] = NULL; reaching_frames_[0] = NULL;
__ bind(&merge_labels_[0]); __ bind(&merge_labels_[0]);
// The stack pointer can be floating above the top of the // The stack pointer can be floating above the top of the
// virtual frame before the bind. Afterward, it should not. // virtual frame before the bind. Afterward, it should not.
int difference = int difference = frame->stack_pointer_ - (frame->element_count() - 1);
frame->stack_pointer_ - (frame->elements_.length() - 1);
if (difference > 0) { if (difference > 0) {
frame->stack_pointer_ -= difference; frame->stack_pointer_ -= difference;
__ add(sp, sp, Operand(difference * kPointerSize)); __ add(sp, sp, Operand(difference * kPointerSize));
...@@ -247,11 +245,11 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -247,11 +245,11 @@ void JumpTarget::DoBind(int mergable_elements) {
} }
// Pick up the frame for this block. Assume ownership if // Pick up the frame for this block. Assume ownership if
// there cannot be backward jumps. // there cannot be backward jumps.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
if (direction_ == BIDIRECTIONAL) { if (direction_ == BIDIRECTIONAL) {
cgen()->SetFrame(new VirtualFrame(frame), &reserved); cgen()->SetFrame(new VirtualFrame(frame), &empty);
} else { } else {
cgen()->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &empty);
reaching_frames_[i] = NULL; reaching_frames_[i] = NULL;
} }
__ bind(&merge_labels_[i]); __ bind(&merge_labels_[i]);
...@@ -274,8 +272,8 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -274,8 +272,8 @@ void JumpTarget::DoBind(int mergable_elements) {
// If this is the fall through, and it didn't need merge // If this is the fall through, and it didn't need merge
// code, we need to pick up the frame so we can jump around // code, we need to pick up the frame so we can jump around
// subsequent merge blocks if necessary. // subsequent merge blocks if necessary.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
cgen()->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &empty);
reaching_frames_[i] = NULL; reaching_frames_[i] = NULL;
} }
} }
...@@ -285,8 +283,8 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -285,8 +283,8 @@ void JumpTarget::DoBind(int mergable_elements) {
// fall through and none of the reaching frames needed merging. // fall through and none of the reaching frames needed merging.
// In that case, clone the entry frame as the current frame. // In that case, clone the entry frame as the current frame.
if (!cgen()->has_valid_frame()) { if (!cgen()->has_valid_frame()) {
RegisterFile reserved_registers = RegisterAllocator::Reserved(); RegisterFile empty;
cgen()->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers); cgen()->SetFrame(new VirtualFrame(entry_frame_), &empty);
} }
// There may be unprocessed reaching frames that did not need // There may be unprocessed reaching frames that did not need
...@@ -311,8 +309,8 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -311,8 +309,8 @@ void JumpTarget::DoBind(int mergable_elements) {
// Use a copy of the reaching frame so the original can be saved // Use a copy of the reaching frame so the original can be saved
// for possible reuse as a backward merge block. // for possible reuse as a backward merge block.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
cgen()->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved); cgen()->SetFrame(new VirtualFrame(reaching_frames_[0]), &empty);
__ bind(&merge_labels_[0]); __ bind(&merge_labels_[0]);
cgen()->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
} }
......
// 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.
#ifndef V8_ARM_REGISTER_ALLOCATOR_ARM_INL_H_
#define V8_ARM_REGISTER_ALLOCATOR_ARM_INL_H_
#include "v8.h"
namespace v8 {
namespace internal {
// -------------------------------------------------------------------------
// RegisterAllocator implementation.
bool RegisterAllocator::IsReserved(Register reg) {
return reg.is(cp) || reg.is(fp) || reg.is(sp) || reg.is(pc);
}
// The register allocator uses small integers to represent the
// non-reserved assembler registers. The mapping is:
//
// r0 <-> 0
// r1 <-> 1
// r2 <-> 2
// r3 <-> 3
// r4 <-> 4
// r5 <-> 5
// r6 <-> 6
// r7 <-> 7
// r9 <-> 8
// r10 <-> 9
// ip <-> 10
// lr <-> 11
int RegisterAllocator::ToNumber(Register reg) {
ASSERT(reg.is_valid() && !IsReserved(reg));
static int numbers[] = {
0, // r0
1, // r1
2, // r2
3, // r3
4, // r4
5, // r5
6, // r6
7, // r7
-1, // cp
8, // r9
9, // r10
-1, // fp
10, // ip
-1, // sp
11, // lr
-1 // pc
};
return numbers[reg.code()];
}
Register RegisterAllocator::ToRegister(int num) {
ASSERT(num >= 0 && num < kNumRegisters);
static Register registers[] =
{ r0, r1, r2, r3, r4, r5, r6, r7, r9, r10, ip, lr };
return registers[num];
}
void RegisterAllocator::Initialize() {
Reset();
// The non-reserved r1 and lr registers are live on JS function entry.
Use(r1); // JS function.
Use(lr); // Return address.
}
} } // namespace v8::internal
#endif // V8_ARM_REGISTER_ALLOCATOR_ARM_INL_H_
...@@ -49,54 +49,9 @@ void Result::ToRegister(Register target) { ...@@ -49,54 +49,9 @@ void Result::ToRegister(Register target) {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// RegisterAllocator implementation. // RegisterAllocator implementation.
RegisterFile RegisterAllocator::Reserved() {
RegisterFile reserved;
reserved.Use(sp);
reserved.Use(fp);
reserved.Use(cp);
reserved.Use(pc);
return reserved;
}
void RegisterAllocator::UnuseReserved(RegisterFile* register_file) {
register_file->ref_counts_[sp.code()] = 0;
register_file->ref_counts_[fp.code()] = 0;
register_file->ref_counts_[cp.code()] = 0;
register_file->ref_counts_[pc.code()] = 0;
}
bool RegisterAllocator::IsReserved(int reg_code) {
return (reg_code == sp.code())
|| (reg_code == fp.code())
|| (reg_code == cp.code())
|| (reg_code == pc.code());
}
void RegisterAllocator::Initialize() {
Reset();
// The following registers are live on function entry, saved in the
// frame, and available for allocation during execution.
Use(r1); // JS function.
Use(lr); // Return address.
}
void RegisterAllocator::Reset() {
registers_.Reset();
// The following registers are live on function entry and reserved
// during execution.
Use(sp); // Stack pointer.
Use(fp); // Frame pointer (caller's frame pointer on entry).
Use(cp); // Context context (callee's context on entry).
Use(pc); // Program counter.
}
Result RegisterAllocator::AllocateByteRegisterWithoutSpilling() { Result RegisterAllocator::AllocateByteRegisterWithoutSpilling() {
UNIMPLEMENTED(); // No byte registers on ARM.
UNREACHABLE();
return Result(); return Result();
} }
......
// 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.
#ifndef V8_ARM_REGISTER_ALLOCATOR_ARM_H_
#define V8_ARM_REGISTER_ALLOCATOR_ARM_H_
namespace v8 {
namespace internal {
class RegisterAllocatorConstants : public AllStatic {
public:
static const int kNumRegisters = 12;
static const int kInvalidRegister = -1;
};
} } // namespace v8::internal
#endif // V8_ARM_REGISTER_ALLOCATOR_ARM_H_
...@@ -49,7 +49,7 @@ VirtualFrame::VirtualFrame() ...@@ -49,7 +49,7 @@ VirtualFrame::VirtualFrame()
for (int i = 0; i <= stack_pointer_; i++) { for (int i = 0; i <= stack_pointer_; i++) {
elements_.Add(FrameElement::MemoryElement()); elements_.Add(FrameElement::MemoryElement());
} }
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
register_locations_[i] = kIllegalIndex; register_locations_[i] = kIllegalIndex;
} }
} }
...@@ -96,7 +96,7 @@ void VirtualFrame::MergeTo(VirtualFrame* expected) { ...@@ -96,7 +96,7 @@ void VirtualFrame::MergeTo(VirtualFrame* expected) {
// Fix any sync bit problems from the bottom-up, stopping when we // Fix any sync bit problems from the bottom-up, stopping when we
// hit the stack pointer or the top of the frame if the stack // hit the stack pointer or the top of the frame if the stack
// pointer is floating above the frame. // pointer is floating above the frame.
int limit = Min(static_cast<int>(stack_pointer_), elements_.length() - 1); int limit = Min(static_cast<int>(stack_pointer_), element_count() - 1);
for (int i = 0; i <= limit; i++) { for (int i = 0; i <= limit; i++) {
FrameElement source = elements_[i]; FrameElement source = elements_[i];
FrameElement target = expected->elements_[i]; FrameElement target = expected->elements_[i];
...@@ -128,7 +128,7 @@ void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame* expected) { ...@@ -128,7 +128,7 @@ void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame* expected) {
// On ARM, all elements are in memory. // On ARM, all elements are in memory.
#ifdef DEBUG #ifdef DEBUG
int start = Min(static_cast<int>(stack_pointer_), elements_.length() - 1); int start = Min(static_cast<int>(stack_pointer_), element_count() - 1);
for (int i = start; i >= 0; i--) { for (int i = start; i >= 0; i--) {
ASSERT(elements_[i].is_memory()); ASSERT(elements_[i].is_memory());
ASSERT(expected->elements_[i].is_memory()); ASSERT(expected->elements_[i].is_memory());
...@@ -393,7 +393,7 @@ Result VirtualFrame::CallCodeObject(Handle<Code> code, ...@@ -393,7 +393,7 @@ Result VirtualFrame::CallCodeObject(Handle<Code> code,
void VirtualFrame::Drop(int count) { void VirtualFrame::Drop(int count) {
ASSERT(height() >= count); ASSERT(height() >= count);
int num_virtual_elements = (elements_.length() - 1) - stack_pointer_; int num_virtual_elements = (element_count() - 1) - stack_pointer_;
// Emit code to lower the stack pointer if necessary. // Emit code to lower the stack pointer if necessary.
if (num_virtual_elements < count) { if (num_virtual_elements < count) {
...@@ -419,7 +419,7 @@ Result VirtualFrame::Pop() { ...@@ -419,7 +419,7 @@ Result VirtualFrame::Pop() {
void VirtualFrame::EmitPop(Register reg) { void VirtualFrame::EmitPop(Register reg) {
ASSERT(stack_pointer_ == elements_.length() - 1); ASSERT(stack_pointer_ == element_count() - 1);
stack_pointer_--; stack_pointer_--;
elements_.RemoveLast(); elements_.RemoveLast();
__ pop(reg); __ pop(reg);
...@@ -427,7 +427,7 @@ void VirtualFrame::EmitPop(Register reg) { ...@@ -427,7 +427,7 @@ void VirtualFrame::EmitPop(Register reg) {
void VirtualFrame::EmitPush(Register reg) { void VirtualFrame::EmitPush(Register reg) {
ASSERT(stack_pointer_ == elements_.length() - 1); ASSERT(stack_pointer_ == element_count() - 1);
elements_.Add(FrameElement::MemoryElement()); elements_.Add(FrameElement::MemoryElement());
stack_pointer_++; stack_pointer_++;
__ push(reg); __ push(reg);
......
...@@ -83,21 +83,35 @@ class VirtualFrame : public ZoneObject { ...@@ -83,21 +83,35 @@ class VirtualFrame : public ZoneObject {
// Create a duplicate of an existing valid frame element. // Create a duplicate of an existing valid frame element.
FrameElement CopyElementAt(int index); FrameElement CopyElementAt(int index);
// The number of elements on the virtual frame.
int element_count() { return elements_.length(); }
// The height of the virtual expression stack. // The height of the virtual expression stack.
int height() { int height() {
return elements_.length() - expression_base_index(); return element_count() - expression_base_index();
}
int register_location(int num) {
ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
return register_locations_[num];
}
int register_location(Register reg) {
return register_locations_[RegisterAllocator::ToNumber(reg)];
} }
int register_index(Register reg) { void set_register_location(Register reg, int index) {
return register_locations_[reg.code()]; register_locations_[RegisterAllocator::ToNumber(reg)] = index;
} }
bool is_used(int reg_code) { bool is_used(int num) {
return register_locations_[reg_code] != kIllegalIndex; ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
return register_locations_[num] != kIllegalIndex;
} }
bool is_used(Register reg) { bool is_used(Register reg) {
return is_used(reg.code()); return register_locations_[RegisterAllocator::ToNumber(reg)]
!= kIllegalIndex;
} }
// Add extra in-memory elements to the top of the frame to match an actual // Add extra in-memory elements to the top of the frame to match an actual
...@@ -109,7 +123,7 @@ class VirtualFrame : public ZoneObject { ...@@ -109,7 +123,7 @@ class VirtualFrame : public ZoneObject {
// the frame after a runtime call). No code is emitted. // the frame after a runtime call). No code is emitted.
void Forget(int count) { void Forget(int count) {
ASSERT(count >= 0); ASSERT(count >= 0);
ASSERT(stack_pointer_ == elements_.length() - 1); ASSERT(stack_pointer_ == element_count() - 1);
stack_pointer_ -= count; stack_pointer_ -= count;
ForgetElements(count); ForgetElements(count);
} }
...@@ -124,7 +138,7 @@ class VirtualFrame : public ZoneObject { ...@@ -124,7 +138,7 @@ class VirtualFrame : public ZoneObject {
// Spill all occurrences of a specific register from the frame. // Spill all occurrences of a specific register from the frame.
void Spill(Register reg) { void Spill(Register reg) {
if (is_used(reg)) SpillElementAt(register_index(reg)); if (is_used(reg)) SpillElementAt(register_location(reg));
} }
// Spill all occurrences of an arbitrary register if possible. Return the // Spill all occurrences of an arbitrary register if possible. Return the
...@@ -148,11 +162,8 @@ class VirtualFrame : public ZoneObject { ...@@ -148,11 +162,8 @@ class VirtualFrame : public ZoneObject {
// one to NULL by an unconditional jump. // one to NULL by an unconditional jump.
void DetachFromCodeGenerator() { void DetachFromCodeGenerator() {
RegisterAllocator* cgen_allocator = cgen()->allocator(); RegisterAllocator* cgen_allocator = cgen()->allocator();
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i)) { if (is_used(i)) cgen_allocator->Unuse(i);
Register temp = { i };
cgen_allocator->Unuse(temp);
}
} }
} }
...@@ -162,11 +173,8 @@ class VirtualFrame : public ZoneObject { ...@@ -162,11 +173,8 @@ class VirtualFrame : public ZoneObject {
// binding a label. // binding a label.
void AttachToCodeGenerator() { void AttachToCodeGenerator() {
RegisterAllocator* cgen_allocator = cgen()->allocator(); RegisterAllocator* cgen_allocator = cgen()->allocator();
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i)) { if (is_used(i)) cgen_allocator->Unuse(i);
Register temp = { i };
cgen_allocator->Use(temp);
}
} }
} }
...@@ -205,7 +213,7 @@ class VirtualFrame : public ZoneObject { ...@@ -205,7 +213,7 @@ class VirtualFrame : public ZoneObject {
} }
void PushElementAt(int index) { void PushElementAt(int index) {
PushFrameSlotAt(elements_.length() - index - 1); PushFrameSlotAt(element_count() - index - 1);
} }
// A frame-allocated local as an assembly operand. // A frame-allocated local as an assembly operand.
...@@ -336,7 +344,7 @@ class VirtualFrame : public ZoneObject { ...@@ -336,7 +344,7 @@ class VirtualFrame : public ZoneObject {
void Drop() { Drop(1); } void Drop() { Drop(1); }
// Duplicate the top element of the frame. // Duplicate the top element of the frame.
void Dup() { PushFrameSlotAt(elements_.length() - 1); } void Dup() { PushFrameSlotAt(element_count() - 1); }
// Pop an element from the top of the expression stack. Returns a // Pop an element from the top of the expression stack. Returns a
// Result, which may be a constant or a register. // Result, which may be a constant or a register.
...@@ -387,7 +395,7 @@ class VirtualFrame : public ZoneObject { ...@@ -387,7 +395,7 @@ class VirtualFrame : public ZoneObject {
// The index of the register frame element using each register, or // The index of the register frame element using each register, or
// kIllegalIndex if a register is not on the frame. // kIllegalIndex if a register is not on the frame.
int register_locations_[kNumRegisters]; int register_locations_[RegisterAllocator::kNumRegisters];
// The number of frame-allocated locals and parameters respectively. // The number of frame-allocated locals and parameters respectively.
int parameter_count() { return cgen()->scope()->num_parameters(); } int parameter_count() { return cgen()->scope()->num_parameters(); }
...@@ -420,8 +428,8 @@ class VirtualFrame : public ZoneObject { ...@@ -420,8 +428,8 @@ class VirtualFrame : public ZoneObject {
// Convert a frame index into a frame pointer relative offset into the // Convert a frame index into a frame pointer relative offset into the
// actual stack. // actual stack.
int fp_relative(int index) { int fp_relative(int index) {
ASSERT(index < elements_.length()); ASSERT(index < element_count());
ASSERT(frame_pointer() < elements_.length()); // FP is on the frame. ASSERT(frame_pointer() < element_count()); // FP is on the frame.
return (frame_pointer() - index) * kPointerSize; return (frame_pointer() - index) * kPointerSize;
} }
...@@ -430,7 +438,7 @@ class VirtualFrame : public ZoneObject { ...@@ -430,7 +438,7 @@ class VirtualFrame : public ZoneObject {
// of updating the index of the register's location in the frame. // of updating the index of the register's location in the frame.
void Use(Register reg, int index) { void Use(Register reg, int index) {
ASSERT(!is_used(reg)); ASSERT(!is_used(reg));
register_locations_[reg.code()] = index; set_register_location(reg, index);
cgen()->allocator()->Use(reg); cgen()->allocator()->Use(reg);
} }
...@@ -438,8 +446,8 @@ class VirtualFrame : public ZoneObject { ...@@ -438,8 +446,8 @@ class VirtualFrame : public ZoneObject {
// decrements the register's external reference count and invalidates the // decrements the register's external reference count and invalidates the
// index of the register's location in the frame. // index of the register's location in the frame.
void Unuse(Register reg) { void Unuse(Register reg) {
ASSERT(register_locations_[reg.code()] != kIllegalIndex); ASSERT(is_used(reg));
register_locations_[reg.code()] = kIllegalIndex; set_register_location(reg, kIllegalIndex);
cgen()->allocator()->Unuse(reg); cgen()->allocator()->Unuse(reg);
} }
...@@ -453,7 +461,7 @@ class VirtualFrame : public ZoneObject { ...@@ -453,7 +461,7 @@ class VirtualFrame : public ZoneObject {
// Keep the element type as register or constant, and clear the dirty bit. // Keep the element type as register or constant, and clear the dirty bit.
void SyncElementAt(int index); void SyncElementAt(int index);
// Sync the range of elements in [begin, end). // Sync the range of elements in [begin, end] with memory.
void SyncRange(int begin, int end); void SyncRange(int begin, int end);
// Sync a single unsynced element that lies beneath or at the stack pointer. // Sync a single unsynced element that lies beneath or at the stack pointer.
......
...@@ -515,8 +515,8 @@ void CodeGenerator::GenerateFastCaseSwitchCases( ...@@ -515,8 +515,8 @@ void CodeGenerator::GenerateFastCaseSwitchCases(
// frame. Otherwise, we have to merge the existing one to the // frame. Otherwise, we have to merge the existing one to the
// start frame as part of the previous case. // start frame as part of the previous case.
if (!has_valid_frame()) { if (!has_valid_frame()) {
RegisterFile non_frame_registers = RegisterAllocator::Reserved(); RegisterFile empty;
SetFrame(new VirtualFrame(start_frame), &non_frame_registers); SetFrame(new VirtualFrame(start_frame), &empty);
} else { } else {
frame_->MergeTo(start_frame); frame_->MergeTo(start_frame);
} }
......
...@@ -79,8 +79,6 @@ struct Register { ...@@ -79,8 +79,6 @@ struct Register {
int code_; int code_;
}; };
const int kNumRegisters = 8;
extern Register eax; extern Register eax;
extern Register ecx; extern Register ecx;
extern Register edx; extern Register edx;
......
This diff is collapsed.
...@@ -580,8 +580,8 @@ class CodeGenerator: public AstVisitor { ...@@ -580,8 +580,8 @@ class CodeGenerator: public AstVisitor {
void CodeForSourcePosition(int pos); void CodeForSourcePosition(int pos);
#ifdef DEBUG #ifdef DEBUG
// True if the registers are valid for entry to a block. There should be // True if the registers are valid for entry to a block. There should
// no frame-external references to eax, ebx, ecx, edx, or edi. // be no frame-external references to (non-reserved) registers.
bool HasValidEntryRegisters(); bool HasValidEntryRegisters();
#endif #endif
......
...@@ -84,7 +84,7 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) { ...@@ -84,7 +84,7 @@ void JumpTarget::DoBranch(Condition cc, Hint hint) {
// branch. // branch.
VirtualFrame* fall_through_frame = cgen()->frame(); VirtualFrame* fall_through_frame = cgen()->frame();
VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame); VirtualFrame* branch_frame = new VirtualFrame(fall_through_frame);
RegisterFile non_frame_registers = RegisterAllocator::Reserved(); RegisterFile non_frame_registers;
cgen()->SetFrame(branch_frame, &non_frame_registers); cgen()->SetFrame(branch_frame, &non_frame_registers);
// Check if we can avoid merge code. // Check if we can avoid merge code.
...@@ -179,14 +179,14 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -179,14 +179,14 @@ void JumpTarget::DoBind(int mergable_elements) {
ASSERT(reaching_frames_.is_empty()); ASSERT(reaching_frames_.is_empty());
ASSERT(!cgen()->has_valid_frame()); ASSERT(!cgen()->has_valid_frame());
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
if (direction_ == BIDIRECTIONAL) { if (direction_ == BIDIRECTIONAL) {
// Copy the entry frame so the original can be used for a // Copy the entry frame so the original can be used for a
// possible backward jump. // possible backward jump.
cgen()->SetFrame(new VirtualFrame(entry_frame_), &reserved); cgen()->SetFrame(new VirtualFrame(entry_frame_), &empty);
} else { } else {
// Take ownership of the entry frame. // Take ownership of the entry frame.
cgen()->SetFrame(entry_frame_, &reserved); cgen()->SetFrame(entry_frame_, &empty);
entry_frame_ = NULL; entry_frame_ = NULL;
} }
__ bind(&entry_label_); __ bind(&entry_label_);
...@@ -200,8 +200,7 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -200,8 +200,7 @@ void JumpTarget::DoBind(int mergable_elements) {
// The stack pointer can be floating above the top of the // The stack pointer can be floating above the top of the
// virtual frame before the bind. Afterward, it should not. // virtual frame before the bind. Afterward, it should not.
VirtualFrame* frame = cgen()->frame(); VirtualFrame* frame = cgen()->frame();
int difference = int difference = frame->stack_pointer_ - (frame->element_count() - 1);
frame->stack_pointer_ - (frame->elements_.length() - 1);
if (difference > 0) { if (difference > 0) {
frame->stack_pointer_ -= difference; frame->stack_pointer_ -= difference;
__ add(Operand(esp), Immediate(difference * kPointerSize)); __ add(Operand(esp), Immediate(difference * kPointerSize));
...@@ -225,15 +224,14 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -225,15 +224,14 @@ void JumpTarget::DoBind(int mergable_elements) {
// possible backward jumps. Pick up the only reaching frame, take // possible backward jumps. Pick up the only reaching frame, take
// ownership of it, and use it for the block about to be emitted. // ownership of it, and use it for the block about to be emitted.
VirtualFrame* frame = reaching_frames_[0]; VirtualFrame* frame = reaching_frames_[0];
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
cgen()->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &empty);
reaching_frames_[0] = NULL; reaching_frames_[0] = NULL;
__ bind(&merge_labels_[0]); __ bind(&merge_labels_[0]);
// The stack pointer can be floating above the top of the // The stack pointer can be floating above the top of the
// virtual frame before the bind. Afterward, it should not. // virtual frame before the bind. Afterward, it should not.
int difference = int difference = frame->stack_pointer_ - (frame->element_count() - 1);
frame->stack_pointer_ - (frame->elements_.length() - 1);
if (difference > 0) { if (difference > 0) {
frame->stack_pointer_ -= difference; frame->stack_pointer_ -= difference;
__ add(Operand(esp), Immediate(difference * kPointerSize)); __ add(Operand(esp), Immediate(difference * kPointerSize));
...@@ -291,11 +289,11 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -291,11 +289,11 @@ void JumpTarget::DoBind(int mergable_elements) {
} }
// Pick up the frame for this block. Assume ownership if // Pick up the frame for this block. Assume ownership if
// there cannot be backward jumps. // there cannot be backward jumps.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
if (direction_ == BIDIRECTIONAL) { if (direction_ == BIDIRECTIONAL) {
cgen()->SetFrame(new VirtualFrame(frame), &reserved); cgen()->SetFrame(new VirtualFrame(frame), &empty);
} else { } else {
cgen()->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &empty);
reaching_frames_[i] = NULL; reaching_frames_[i] = NULL;
} }
__ bind(&merge_labels_[i]); __ bind(&merge_labels_[i]);
...@@ -318,8 +316,8 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -318,8 +316,8 @@ void JumpTarget::DoBind(int mergable_elements) {
// If this is the fall through frame, and it didn't need // If this is the fall through frame, and it didn't need
// merge code, we need to pick up the frame so we can jump // merge code, we need to pick up the frame so we can jump
// around subsequent merge blocks if necessary. // around subsequent merge blocks if necessary.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
cgen()->SetFrame(frame, &reserved); cgen()->SetFrame(frame, &empty);
reaching_frames_[i] = NULL; reaching_frames_[i] = NULL;
} }
} }
...@@ -329,8 +327,8 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -329,8 +327,8 @@ void JumpTarget::DoBind(int mergable_elements) {
// fall through and none of the reaching frames needed merging. // fall through and none of the reaching frames needed merging.
// In that case, clone the entry frame as the current frame. // In that case, clone the entry frame as the current frame.
if (!cgen()->has_valid_frame()) { if (!cgen()->has_valid_frame()) {
RegisterFile reserved_registers = RegisterAllocator::Reserved(); RegisterFile empty;
cgen()->SetFrame(new VirtualFrame(entry_frame_), &reserved_registers); cgen()->SetFrame(new VirtualFrame(entry_frame_), &empty);
} }
// There may be unprocessed reaching frames that did not need // There may be unprocessed reaching frames that did not need
...@@ -355,8 +353,8 @@ void JumpTarget::DoBind(int mergable_elements) { ...@@ -355,8 +353,8 @@ void JumpTarget::DoBind(int mergable_elements) {
// Use a copy of the reaching frame so the original can be saved // Use a copy of the reaching frame so the original can be saved
// for possible reuse as a backward merge block. // for possible reuse as a backward merge block.
RegisterFile reserved = RegisterAllocator::Reserved(); RegisterFile empty;
cgen()->SetFrame(new VirtualFrame(reaching_frames_[0]), &reserved); cgen()->SetFrame(new VirtualFrame(reaching_frames_[0]), &empty);
__ bind(&merge_labels_[0]); __ bind(&merge_labels_[0]);
cgen()->frame()->MergeTo(entry_frame_); cgen()->frame()->MergeTo(entry_frame_);
} }
......
// 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.
#ifndef V8_IA32_REGISTER_ALLOCATOR_IA32_INL_H_
#define V8_IA32_REGISTER_ALLOCATOR_IA32_INL_H_
#include "v8.h"
namespace v8 {
namespace internal {
// -------------------------------------------------------------------------
// RegisterAllocator implementation.
bool RegisterAllocator::IsReserved(Register reg) {
// The code for this test relies on the order of register codes.
return reg.code() >= esp.code() && reg.code() <= esi.code();
}
// The register allocator uses small integers to represent the
// non-reserved assembler registers. The mapping is:
// eax <-> 0, ebx <-> 1, ecx <-> 2, edx <-> 3, edi <-> 4.
int RegisterAllocator::ToNumber(Register reg) {
ASSERT(reg.is_valid() && !IsReserved(reg));
static int numbers[] = {
0, // eax
2, // ecx
3, // edx
1, // ebx
-1, // esp
-1, // ebp
-1, // esi
4 // edi
};
return numbers[reg.code()];
}
Register RegisterAllocator::ToRegister(int num) {
ASSERT(num >= 0 && num < kNumRegisters);
static Register registers[] = { eax, ebx, ecx, edx, edi };
return registers[num];
}
void RegisterAllocator::Initialize() {
Reset();
// The non-reserved edi register is live on JS function entry.
Use(edi); // JS function.
}
} } // namespace v8::internal
#endif // V8_IA32_REGISTER_ALLOCATOR_IA32_INL_H_
...@@ -84,46 +84,6 @@ void Result::ToRegister(Register target) { ...@@ -84,46 +84,6 @@ void Result::ToRegister(Register target) {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// RegisterAllocator implementation. // RegisterAllocator implementation.
RegisterFile RegisterAllocator::Reserved() {
RegisterFile reserved;
reserved.Use(esp);
reserved.Use(ebp);
reserved.Use(esi);
return reserved;
}
void RegisterAllocator::UnuseReserved(RegisterFile* register_file) {
register_file->ref_counts_[esp.code()] = 0;
register_file->ref_counts_[ebp.code()] = 0;
register_file->ref_counts_[esi.code()] = 0;
}
bool RegisterAllocator::IsReserved(int reg_code) {
// Test below relies on the order of register codes.
return reg_code >= esp.code() && reg_code <= esi.code();
}
void RegisterAllocator::Initialize() {
Reset();
// The following register is live on function entry, saved in the
// frame, and available for allocation during execution.
Use(edi); // JS function.
}
void RegisterAllocator::Reset() {
registers_.Reset();
// The following registers are live on function entry and reserved
// during execution.
Use(esp); // Stack pointer.
Use(ebp); // Frame pointer (caller's frame pointer on entry).
Use(esi); // Context (callee's context on entry).
}
Result RegisterAllocator::AllocateByteRegisterWithoutSpilling() { Result RegisterAllocator::AllocateByteRegisterWithoutSpilling() {
Result result = AllocateWithoutSpilling(); Result result = AllocateWithoutSpilling();
// Check that the register is a byte register. If not, unuse the // Check that the register is a byte register. If not, unuse the
......
// 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.
#ifndef V8_IA32_REGISTER_ALLOCATOR_IA32_H_
#define V8_IA32_REGISTER_ALLOCATOR_IA32_H_
namespace v8 {
namespace internal {
class RegisterAllocatorConstants : public AllStatic {
public:
static const int kNumRegisters = 5;
static const int kInvalidRegister = -1;
};
} } // namespace v8::internal
#endif // V8_IA32_REGISTER_ALLOCATOR_IA32_H_
This diff is collapsed.
...@@ -83,21 +83,35 @@ class VirtualFrame : public ZoneObject { ...@@ -83,21 +83,35 @@ class VirtualFrame : public ZoneObject {
// Create a duplicate of an existing valid frame element. // Create a duplicate of an existing valid frame element.
FrameElement CopyElementAt(int index); FrameElement CopyElementAt(int index);
// The number of elements on the virtual frame.
int element_count() { return elements_.length(); }
// The height of the virtual expression stack. // The height of the virtual expression stack.
int height() { int height() {
return elements_.length() - expression_base_index(); return element_count() - expression_base_index();
}
int register_location(int num) {
ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
return register_locations_[num];
}
int register_location(Register reg) {
return register_locations_[RegisterAllocator::ToNumber(reg)];
} }
int register_index(Register reg) { void set_register_location(Register reg, int index) {
return register_locations_[reg.code()]; register_locations_[RegisterAllocator::ToNumber(reg)] = index;
} }
bool is_used(int reg_code) { bool is_used(int num) {
return register_locations_[reg_code] != kIllegalIndex; ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
return register_locations_[num] != kIllegalIndex;
} }
bool is_used(Register reg) { bool is_used(Register reg) {
return is_used(reg.code()); return register_locations_[RegisterAllocator::ToNumber(reg)]
!= kIllegalIndex;
} }
// Add extra in-memory elements to the top of the frame to match an actual // Add extra in-memory elements to the top of the frame to match an actual
...@@ -112,7 +126,7 @@ class VirtualFrame : public ZoneObject { ...@@ -112,7 +126,7 @@ class VirtualFrame : public ZoneObject {
// handler). No code will be emitted. // handler). No code will be emitted.
void Forget(int count) { void Forget(int count) {
ASSERT(count >= 0); ASSERT(count >= 0);
ASSERT(stack_pointer_ == elements_.length() - 1); ASSERT(stack_pointer_ == element_count() - 1);
stack_pointer_ -= count; stack_pointer_ -= count;
ForgetElements(count); ForgetElements(count);
} }
...@@ -127,7 +141,7 @@ class VirtualFrame : public ZoneObject { ...@@ -127,7 +141,7 @@ class VirtualFrame : public ZoneObject {
// Spill all occurrences of a specific register from the frame. // Spill all occurrences of a specific register from the frame.
void Spill(Register reg) { void Spill(Register reg) {
if (is_used(reg)) SpillElementAt(register_index(reg)); if (is_used(reg)) SpillElementAt(register_location(reg));
} }
// Spill all occurrences of an arbitrary register if possible. Return the // Spill all occurrences of an arbitrary register if possible. Return the
...@@ -135,6 +149,9 @@ class VirtualFrame : public ZoneObject { ...@@ -135,6 +149,9 @@ class VirtualFrame : public ZoneObject {
// (ie, they all have frame-external references). // (ie, they all have frame-external references).
Register SpillAnyRegister(); Register SpillAnyRegister();
// Sync the range of elements in [begin, end] with memory.
void SyncRange(int begin, int end);
// Make this frame so that an arbitrary frame of the same height can // Make this frame so that an arbitrary frame of the same height can
// be merged to it. Copies and constants are removed from the // be merged to it. Copies and constants are removed from the
// topmost mergable_elements elements of the frame. A // topmost mergable_elements elements of the frame. A
...@@ -158,11 +175,8 @@ class VirtualFrame : public ZoneObject { ...@@ -158,11 +175,8 @@ class VirtualFrame : public ZoneObject {
// one to NULL by an unconditional jump. // one to NULL by an unconditional jump.
void DetachFromCodeGenerator() { void DetachFromCodeGenerator() {
RegisterAllocator* cgen_allocator = cgen()->allocator(); RegisterAllocator* cgen_allocator = cgen()->allocator();
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i)) { if (is_used(i)) cgen_allocator->Unuse(i);
Register temp = { i };
cgen_allocator->Unuse(temp);
}
} }
} }
...@@ -172,11 +186,8 @@ class VirtualFrame : public ZoneObject { ...@@ -172,11 +186,8 @@ class VirtualFrame : public ZoneObject {
// binding a label. // binding a label.
void AttachToCodeGenerator() { void AttachToCodeGenerator() {
RegisterAllocator* cgen_allocator = cgen()->allocator(); RegisterAllocator* cgen_allocator = cgen()->allocator();
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i)) { if (is_used(i)) cgen_allocator->Use(i);
Register temp = { i };
cgen_allocator->Use(temp);
}
} }
} }
...@@ -211,11 +222,11 @@ class VirtualFrame : public ZoneObject { ...@@ -211,11 +222,11 @@ class VirtualFrame : public ZoneObject {
} }
void PushElementAt(int index) { void PushElementAt(int index) {
PushFrameSlotAt(elements_.length() - index - 1); PushFrameSlotAt(element_count() - index - 1);
} }
void StoreToElementAt(int index) { void StoreToElementAt(int index) {
StoreToFrameSlotAt(elements_.length() - index - 1); StoreToFrameSlotAt(element_count() - index - 1);
} }
// A frame-allocated local as an assembly operand. // A frame-allocated local as an assembly operand.
...@@ -259,7 +270,7 @@ class VirtualFrame : public ZoneObject { ...@@ -259,7 +270,7 @@ class VirtualFrame : public ZoneObject {
// A parameter as an assembly operand. // A parameter as an assembly operand.
Operand ParameterAt(int index) { Operand ParameterAt(int index) {
ASSERT(-1 <= index); // -1 is the receiver. ASSERT(-1 <= index); // -1 is the receiver.
ASSERT(index <= parameter_count()); ASSERT(index < parameter_count());
return Operand(ebp, (1 + parameter_count() - index) * kPointerSize); return Operand(ebp, (1 + parameter_count() - index) * kPointerSize);
} }
...@@ -352,7 +363,7 @@ class VirtualFrame : public ZoneObject { ...@@ -352,7 +363,7 @@ class VirtualFrame : public ZoneObject {
void Drop() { Drop(1); } void Drop() { Drop(1); }
// Duplicate the top element of the frame. // Duplicate the top element of the frame.
void Dup() { PushFrameSlotAt(elements_.length() - 1); } void Dup() { PushFrameSlotAt(element_count() - 1); }
// Pop an element from the top of the expression stack. Returns a // Pop an element from the top of the expression stack. Returns a
// Result, which may be a constant or a register. // Result, which may be a constant or a register.
...@@ -407,7 +418,7 @@ class VirtualFrame : public ZoneObject { ...@@ -407,7 +418,7 @@ class VirtualFrame : public ZoneObject {
// The index of the register frame element using each register, or // The index of the register frame element using each register, or
// kIllegalIndex if a register is not on the frame. // kIllegalIndex if a register is not on the frame.
int register_locations_[kNumRegisters]; int register_locations_[RegisterAllocator::kNumRegisters];
// The number of frame-allocated locals and parameters respectively. // The number of frame-allocated locals and parameters respectively.
int parameter_count() { return cgen()->scope()->num_parameters(); } int parameter_count() { return cgen()->scope()->num_parameters(); }
...@@ -440,8 +451,8 @@ class VirtualFrame : public ZoneObject { ...@@ -440,8 +451,8 @@ class VirtualFrame : public ZoneObject {
// Convert a frame index into a frame pointer relative offset into the // Convert a frame index into a frame pointer relative offset into the
// actual stack. // actual stack.
int fp_relative(int index) { int fp_relative(int index) {
ASSERT(index < elements_.length()); ASSERT(index < element_count());
ASSERT(frame_pointer() < elements_.length()); // FP is on the frame. ASSERT(frame_pointer() < element_count()); // FP is on the frame.
return (frame_pointer() - index) * kPointerSize; return (frame_pointer() - index) * kPointerSize;
} }
...@@ -450,7 +461,7 @@ class VirtualFrame : public ZoneObject { ...@@ -450,7 +461,7 @@ class VirtualFrame : public ZoneObject {
// of updating the index of the register's location in the frame. // of updating the index of the register's location in the frame.
void Use(Register reg, int index) { void Use(Register reg, int index) {
ASSERT(!is_used(reg)); ASSERT(!is_used(reg));
register_locations_[reg.code()] = index; set_register_location(reg, index);
cgen()->allocator()->Use(reg); cgen()->allocator()->Use(reg);
} }
...@@ -458,8 +469,8 @@ class VirtualFrame : public ZoneObject { ...@@ -458,8 +469,8 @@ class VirtualFrame : public ZoneObject {
// decrements the register's external reference count and invalidates the // decrements the register's external reference count and invalidates the
// index of the register's location in the frame. // index of the register's location in the frame.
void Unuse(Register reg) { void Unuse(Register reg) {
ASSERT(register_locations_[reg.code()] != kIllegalIndex); ASSERT(is_used(reg));
register_locations_[reg.code()] = kIllegalIndex; set_register_location(reg, kIllegalIndex);
cgen()->allocator()->Unuse(reg); cgen()->allocator()->Unuse(reg);
} }
...@@ -473,9 +484,6 @@ class VirtualFrame : public ZoneObject { ...@@ -473,9 +484,6 @@ class VirtualFrame : public ZoneObject {
// Keep the element type as register or constant, and clear the dirty bit. // Keep the element type as register or constant, and clear the dirty bit.
void SyncElementAt(int index); void SyncElementAt(int index);
// Sync the range of elements in [begin, end).
void SyncRange(int begin, int end);
// Sync a single unsynced element that lies beneath or at the stack pointer. // Sync a single unsynced element that lies beneath or at the stack pointer.
void SyncElementBelowStackPointer(int index); void SyncElementBelowStackPointer(int index);
......
...@@ -38,7 +38,7 @@ CodeGenerator* JumpTarget::cgen() { ...@@ -38,7 +38,7 @@ CodeGenerator* JumpTarget::cgen() {
void JumpTarget::InitializeEntryElement(int index, FrameElement* target) { void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
entry_frame_->elements_[index].clear_copied(); entry_frame_->elements_[index].clear_copied();
if (target->is_register()) { if (target->is_register()) {
entry_frame_->register_locations_[target->reg().code()] = index; entry_frame_->set_register_location(target->reg(), index);
} else if (target->is_copy()) { } else if (target->is_copy()) {
entry_frame_->elements_[target->index()].set_copied(); entry_frame_->elements_[target->index()].set_copied();
} }
......
...@@ -74,7 +74,7 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) { ...@@ -74,7 +74,7 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) {
// A list of pointers to frame elements in the entry frame. NULL // A list of pointers to frame elements in the entry frame. NULL
// indicates that the element has not yet been determined. // indicates that the element has not yet been determined.
int length = initial_frame->elements_.length(); int length = initial_frame->element_count();
ZoneList<FrameElement*> elements(length); ZoneList<FrameElement*> elements(length);
// Convert the number of mergable elements (counted from the top // Convert the number of mergable elements (counted from the top
...@@ -124,7 +124,7 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) { ...@@ -124,7 +124,7 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) {
// return address). Replace those first. // return address). Replace those first.
entry_frame_ = new VirtualFrame(); entry_frame_ = new VirtualFrame();
int index = 0; int index = 0;
for (; index < entry_frame_->elements_.length(); index++) { for (; index < entry_frame_->element_count(); index++) {
FrameElement* target = elements[index]; FrameElement* target = elements[index];
// If the element is determined, set it now. Count registers. Mark // If the element is determined, set it now. Count registers. Mark
// elements as copied exactly when they have a copy. Undetermined // elements as copied exactly when they have a copy. Undetermined
...@@ -155,7 +155,7 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) { ...@@ -155,7 +155,7 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) {
bool is_synced = true; bool is_synced = true;
RegisterFile candidate_registers; RegisterFile candidate_registers;
int best_count = kMinInt; int best_count = kMinInt;
int best_reg_code = no_reg.code_; int best_reg_num = RegisterAllocator::kInvalidRegister;
StaticType type; // Initially invalid. StaticType type; // Initially invalid.
if (direction_ != BIDIRECTIONAL || i < high_water_mark) { if (direction_ != BIDIRECTIONAL || i < high_water_mark) {
...@@ -168,10 +168,11 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) { ...@@ -168,10 +168,11 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) {
if (element.is_register() && !entry_frame_->is_used(element.reg())) { if (element.is_register() && !entry_frame_->is_used(element.reg())) {
// Count the register occurrence and remember it if better // Count the register occurrence and remember it if better
// than the previous best. // than the previous best.
candidate_registers.Use(element.reg()); int num = RegisterAllocator::ToNumber(element.reg());
if (candidate_registers.count(element.reg()) > best_count) { candidate_registers.Use(num);
best_count = candidate_registers.count(element.reg()); if (candidate_registers.count(num) > best_count) {
best_reg_code = element.reg().code(); best_count = candidate_registers.count(num);
best_reg_num = num;
} }
} }
type = type.merge(element.static_type()); type = type.merge(element.static_type());
...@@ -188,16 +189,16 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) { ...@@ -188,16 +189,16 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) {
// Try to put it in a register. If there was no best choice // Try to put it in a register. If there was no best choice
// consider any free register. // consider any free register.
if (best_reg_code == no_reg.code_) { if (best_reg_num == RegisterAllocator::kInvalidRegister) {
for (int j = 0; j < kNumRegisters; j++) { for (int j = 0; j < RegisterAllocator::kNumRegisters; j++) {
if (!entry_frame_->is_used(j) && !RegisterAllocator::IsReserved(j)) { if (!entry_frame_->is_used(j)) {
best_reg_code = j; best_reg_num = j;
break; break;
} }
} }
} }
if (best_reg_code == no_reg.code_) { if (best_reg_num == RegisterAllocator::kInvalidRegister) {
// If there was no register found, the element is already // If there was no register found, the element is already
// recorded as in memory. // recorded as in memory.
entry_frame_->elements_[i].set_static_type(type); entry_frame_->elements_[i].set_static_type(type);
...@@ -205,13 +206,13 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) { ...@@ -205,13 +206,13 @@ void JumpTarget::ComputeEntryFrame(int mergable_elements) {
// If there was a register choice, use it. Preserve the copied // If there was a register choice, use it. Preserve the copied
// flag on the element. Set the static type as computed. // flag on the element. Set the static type as computed.
bool is_copied = entry_frame_->elements_[i].is_copied(); bool is_copied = entry_frame_->elements_[i].is_copied();
Register reg = { best_reg_code }; Register reg = RegisterAllocator::ToRegister(best_reg_num);
entry_frame_->elements_[i] = entry_frame_->elements_[i] =
FrameElement::RegisterElement(reg, FrameElement::RegisterElement(reg,
FrameElement::NOT_SYNCED); FrameElement::NOT_SYNCED);
if (is_copied) entry_frame_->elements_[i].set_copied(); if (is_copied) entry_frame_->elements_[i].set_copied();
entry_frame_->elements_[i].set_static_type(type); entry_frame_->elements_[i].set_static_type(type);
entry_frame_->register_locations_[best_reg_code] = i; entry_frame_->set_register_location(reg, i);
} }
} }
} }
......
...@@ -32,6 +32,17 @@ ...@@ -32,6 +32,17 @@
#include "register-allocator.h" #include "register-allocator.h"
#include "virtual-frame.h" #include "virtual-frame.h"
#if V8_TARGET_ARCH_IA32
#include "ia32/register-allocator-ia32-inl.h"
#elif V8_TARGET_ARCH_X64
#include "x64/register-allocator-x64-inl.h"
#elif V8_TARGET_ARCH_ARM
#include "arm/register-allocator-arm-inl.h"
#else
#error Unsupported target architecture.
#endif
namespace v8 { namespace v8 {
namespace internal { namespace internal {
......
...@@ -38,7 +38,7 @@ namespace internal { ...@@ -38,7 +38,7 @@ namespace internal {
Result::Result(Register reg) { Result::Result(Register reg) {
ASSERT(reg.is_valid()); ASSERT(reg.is_valid() && !RegisterAllocator::IsReserved(reg));
CodeGeneratorScope::Current()->allocator()->Use(reg); CodeGeneratorScope::Current()->allocator()->Use(reg);
value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE) value_ = StaticTypeField::encode(StaticType::UNKNOWN_TYPE)
| TypeField::encode(REGISTER) | TypeField::encode(REGISTER)
...@@ -47,7 +47,7 @@ Result::Result(Register reg) { ...@@ -47,7 +47,7 @@ Result::Result(Register reg) {
Result::Result(Register reg, StaticType type) { Result::Result(Register reg, StaticType type) {
ASSERT(reg.is_valid()); ASSERT(reg.is_valid() && !RegisterAllocator::IsReserved(reg));
CodeGeneratorScope::Current()->allocator()->Use(reg); CodeGeneratorScope::Current()->allocator()->Use(reg);
value_ = StaticTypeField::encode(type.static_type_) value_ = StaticTypeField::encode(type.static_type_)
| TypeField::encode(REGISTER) | TypeField::encode(REGISTER)
...@@ -61,12 +61,11 @@ Result::Result(Register reg, StaticType type) { ...@@ -61,12 +61,11 @@ Result::Result(Register reg, StaticType type) {
Result RegisterAllocator::AllocateWithoutSpilling() { Result RegisterAllocator::AllocateWithoutSpilling() {
// Return the first free register, if any. // Return the first free register, if any.
int free_reg = registers_.ScanForFreeRegister(); int num = registers_.ScanForFreeRegister();
if (free_reg < kNumRegisters) { if (num == RegisterAllocator::kInvalidRegister) {
Register free_result = { free_reg }; return Result();
return Result(free_result);
} }
return Result(); return Result(RegisterAllocator::ToRegister(num));
} }
......
...@@ -30,6 +30,16 @@ ...@@ -30,6 +30,16 @@
#include "macro-assembler.h" #include "macro-assembler.h"
#if V8_TARGET_ARCH_IA32
#include "ia32/register-allocator-ia32.h"
#elif V8_TARGET_ARCH_X64
#include "x64/register-allocator-x64.h"
#elif V8_TARGET_ARCH_ARM
#include "arm/register-allocator-arm.h"
#else
#error Unsupported target architecture.
#endif
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -241,25 +251,28 @@ class RegisterFile BASE_EMBEDDED { ...@@ -241,25 +251,28 @@ class RegisterFile BASE_EMBEDDED {
} }
} }
// Predicates and accessors for the reference counts. The versions // Predicates and accessors for the reference counts.
// that take a register code rather than a register are for bool is_used(int num) {
// convenience in loops over the register codes. ASSERT(0 <= num && num < kNumRegisters);
bool is_used(int reg_code) const { return ref_counts_[reg_code] > 0; } return ref_counts_[num] > 0;
bool is_used(Register reg) const { return is_used(reg.code()); } }
int count(int reg_code) const { return ref_counts_[reg_code]; }
int count(Register reg) const { return count(reg.code()); } int count(int num) {
ASSERT(0 <= num && num < kNumRegisters);
return ref_counts_[num];
}
// Record a use of a register by incrementing its reference count. // Record a use of a register by incrementing its reference count.
void Use(Register reg) { void Use(int num) {
ref_counts_[reg.code()]++; ASSERT(0 <= num && num < kNumRegisters);
ref_counts_[num]++;
} }
// Record that a register will no longer be used by decrementing its // Record that a register will no longer be used by decrementing its
// reference count. // reference count.
void Unuse(Register reg) { void Unuse(int num) {
ASSERT(!reg.is(no_reg)); ASSERT(is_used(num));
ASSERT(is_used(reg.code())); ref_counts_[num]--;
ref_counts_[reg.code()]--;
} }
// Copy the reference counts from this register file to the other. // Copy the reference counts from this register file to the other.
...@@ -270,17 +283,18 @@ class RegisterFile BASE_EMBEDDED { ...@@ -270,17 +283,18 @@ class RegisterFile BASE_EMBEDDED {
} }
private: private:
static const int kNumRegisters = RegisterAllocatorConstants::kNumRegisters;
int ref_counts_[kNumRegisters]; int ref_counts_[kNumRegisters];
// Very fast inlined loop to find a free register. // Very fast inlined loop to find a free register. Used in
// Used in RegisterAllocator::AllocateWithoutSpilling. // RegisterAllocator::AllocateWithoutSpilling. Returns
// Returns kNumRegisters if no free register found. // kInvalidRegister if no free register found.
inline int ScanForFreeRegister() { int ScanForFreeRegister() {
int i = 0; for (int i = 0; i < RegisterAllocatorConstants::kNumRegisters; i++) {
for (; i < kNumRegisters ; ++i) { if (!is_used(i)) return i;
if (ref_counts_[i] == 0) break;
} }
return i; return RegisterAllocatorConstants::kInvalidRegister;
} }
friend class RegisterAllocator; friend class RegisterAllocator;
...@@ -293,55 +307,62 @@ class RegisterFile BASE_EMBEDDED { ...@@ -293,55 +307,62 @@ class RegisterFile BASE_EMBEDDED {
class RegisterAllocator BASE_EMBEDDED { class RegisterAllocator BASE_EMBEDDED {
public: public:
explicit RegisterAllocator(CodeGenerator* cgen) : cgen_(cgen) {} static const int kNumRegisters =
RegisterAllocatorConstants::kNumRegisters;
static const int kInvalidRegister =
RegisterAllocatorConstants::kInvalidRegister;
// A register file with each of the reserved registers counted once. explicit RegisterAllocator(CodeGenerator* cgen) : cgen_(cgen) {}
static RegisterFile Reserved();
// Unuse all the reserved registers in a register file.
static void UnuseReserved(RegisterFile* register_file);
// True if the register is reserved by the code generator, false if it // True if the register is reserved by the code generator, false if it
// can be freely used by the allocator. // can be freely used by the allocator Defined in the
static bool IsReserved(int reg_code); // platform-specific XXX-inl.h files..
static bool IsReserved(Register reg) { return IsReserved(reg); } static inline bool IsReserved(Register reg);
// Convert between (unreserved) assembler registers and allocator
// numbers. Defined in the platform-specific XXX-inl.h files.
static inline int ToNumber(Register reg);
static inline Register ToRegister(int num);
// Predicates and accessors for the registers' reference counts. // Predicates and accessors for the registers' reference counts.
bool is_used(int reg_code) const { return registers_.is_used(reg_code); } bool is_used(int num) { return registers_.is_used(num); }
bool is_used(Register reg) const { return registers_.is_used(reg.code()); } bool is_used(Register reg) { return registers_.is_used(ToNumber(reg)); }
int count(int reg_code) const { return registers_.count(reg_code); }
int count(Register reg) const { return registers_.count(reg.code()); } int count(int num) { return registers_.count(num); }
int count(Register reg) { return registers_.count(ToNumber(reg)); }
// Explicitly record a reference to a register. // Explicitly record a reference to a register.
void Use(Register reg) { registers_.Use(reg); } void Use(int num) { registers_.Use(num); }
void Use(Register reg) { registers_.Use(ToNumber(reg)); }
// Explicitly record that a register will no longer be used. // Explicitly record that a register will no longer be used.
void Unuse(Register reg) { registers_.Unuse(reg); } void Unuse(int num) { registers_.Unuse(num); }
void Unuse(Register reg) { registers_.Unuse(ToNumber(reg)); }
// Initialize the register allocator for entry to a JS function. On
// entry, the registers used by the JS calling convention are
// externally referenced (ie, outside the virtual frame); and the
// other registers are free.
void Initialize();
// Reset the register reference counts to free all non-reserved registers. // Reset the register reference counts to free all non-reserved registers.
// A frame-external reference is kept to each of the reserved registers. void Reset() { registers_.Reset(); }
void Reset();
// Initialize the register allocator for entry to a JS function. On
// entry, the (non-reserved) registers used by the JS calling
// convention are referenced and the other (non-reserved) registers
// are free.
inline void Initialize();
// Allocate a free register and return a register result if possible or // Allocate a free register and return a register result if possible or
// fail and return an invalid result. // fail and return an invalid result.
Result Allocate(); Result Allocate();
// Allocate a specific register if possible, spilling it from the frame if // Allocate a specific register if possible, spilling it from the
// necessary, or else fail and return an invalid result. // current frame if necessary, or else fail and return an invalid
// result.
Result Allocate(Register target); Result Allocate(Register target);
// Allocate a free register without spilling any from the current frame or // Allocate a free register without spilling any from the current
// fail and return an invalid result. // frame or fail and return an invalid result.
Result AllocateWithoutSpilling(); Result AllocateWithoutSpilling();
// Allocate a free byte register without spilling any from the // Allocate a free byte register without spilling any from the current
// current frame or fail and return an invalid result. // frame or fail and return an invalid result.
Result AllocateByteRegisterWithoutSpilling(); Result AllocateByteRegisterWithoutSpilling();
// Copy the internal state to a register file, to be restored later by // Copy the internal state to a register file, to be restored later by
...@@ -350,6 +371,7 @@ class RegisterAllocator BASE_EMBEDDED { ...@@ -350,6 +371,7 @@ class RegisterAllocator BASE_EMBEDDED {
registers_.CopyTo(register_file); registers_.CopyTo(register_file);
} }
// Restore the internal state.
void RestoreFrom(RegisterFile* register_file) { void RestoreFrom(RegisterFile* register_file) {
register_file->CopyTo(&registers_); register_file->CopyTo(&registers_);
} }
......
...@@ -38,7 +38,7 @@ namespace internal { ...@@ -38,7 +38,7 @@ namespace internal {
// When cloned, a frame is a deep copy of the original. // When cloned, a frame is a deep copy of the original.
VirtualFrame::VirtualFrame(VirtualFrame* original) VirtualFrame::VirtualFrame(VirtualFrame* original)
: elements_(original->elements_.length()), : elements_(original->element_count()),
stack_pointer_(original->stack_pointer_) { stack_pointer_(original->stack_pointer_) {
elements_.AddAll(original->elements_); elements_.AddAll(original->elements_);
// Copy register locations from original. // Copy register locations from original.
...@@ -50,7 +50,7 @@ VirtualFrame::VirtualFrame(VirtualFrame* original) ...@@ -50,7 +50,7 @@ VirtualFrame::VirtualFrame(VirtualFrame* original)
FrameElement VirtualFrame::CopyElementAt(int index) { FrameElement VirtualFrame::CopyElementAt(int index) {
ASSERT(index >= 0); ASSERT(index >= 0);
ASSERT(index < elements_.length()); ASSERT(index < element_count());
FrameElement target = elements_[index]; FrameElement target = elements_[index];
FrameElement result; FrameElement result;
...@@ -96,7 +96,7 @@ FrameElement VirtualFrame::CopyElementAt(int index) { ...@@ -96,7 +96,7 @@ FrameElement VirtualFrame::CopyElementAt(int index) {
// pushing an exception handler). No code is emitted. // pushing an exception handler). No code is emitted.
void VirtualFrame::Adjust(int count) { void VirtualFrame::Adjust(int count) {
ASSERT(count >= 0); ASSERT(count >= 0);
ASSERT(stack_pointer_ == elements_.length() - 1); ASSERT(stack_pointer_ == element_count() - 1);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
elements_.Add(FrameElement::MemoryElement()); elements_.Add(FrameElement::MemoryElement());
...@@ -107,7 +107,7 @@ void VirtualFrame::Adjust(int count) { ...@@ -107,7 +107,7 @@ void VirtualFrame::Adjust(int count) {
void VirtualFrame::ForgetElements(int count) { void VirtualFrame::ForgetElements(int count) {
ASSERT(count >= 0); ASSERT(count >= 0);
ASSERT(elements_.length() >= count); ASSERT(element_count() >= count);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
FrameElement last = elements_.RemoveLast(); FrameElement last = elements_.RemoveLast();
...@@ -118,7 +118,7 @@ void VirtualFrame::ForgetElements(int count) { ...@@ -118,7 +118,7 @@ void VirtualFrame::ForgetElements(int count) {
if (cgen()->frame() == this) { if (cgen()->frame() == this) {
Unuse(last.reg()); Unuse(last.reg());
} else { } else {
register_locations_[last.reg().code()] = kIllegalIndex; set_register_location(last.reg(), kIllegalIndex);
} }
} }
} }
...@@ -127,14 +127,13 @@ void VirtualFrame::ForgetElements(int count) { ...@@ -127,14 +127,13 @@ void VirtualFrame::ForgetElements(int count) {
// If there are any registers referenced only by the frame, spill one. // If there are any registers referenced only by the frame, spill one.
Register VirtualFrame::SpillAnyRegister() { Register VirtualFrame::SpillAnyRegister() {
// Find the leftmost (ordered by register code) register whose only // Find the leftmost (ordered by register number) register whose only
// reference is in the frame. // reference is in the frame.
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i) && cgen()->allocator()->count(i) == 1) { if (is_used(i) && cgen()->allocator()->count(i) == 1) {
Register result = { i }; SpillElementAt(register_location(i));
Spill(result); ASSERT(!cgen()->allocator()->is_used(i));
ASSERT(!cgen()->allocator()->is_used(result)); return RegisterAllocator::ToRegister(i);
return result;
} }
} }
return no_reg; return no_reg;
...@@ -173,7 +172,7 @@ void VirtualFrame::SyncElementAt(int index) { ...@@ -173,7 +172,7 @@ void VirtualFrame::SyncElementAt(int index) {
// Make the type of all elements be MEMORY. // Make the type of all elements be MEMORY.
void VirtualFrame::SpillAll() { void VirtualFrame::SpillAll() {
for (int i = 0; i < elements_.length(); i++) { for (int i = 0; i < element_count(); i++) {
SpillElementAt(i); SpillElementAt(i);
} }
} }
...@@ -183,7 +182,7 @@ void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) { ...@@ -183,7 +182,7 @@ void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) {
// Perform state changes on this frame that will make merge to the // Perform state changes on this frame that will make merge to the
// expected frame simpler or else increase the likelihood that his // expected frame simpler or else increase the likelihood that his
// frame will match another. // frame will match another.
for (int i = 0; i < elements_.length(); i++) { for (int i = 0; i < element_count(); i++) {
FrameElement source = elements_[i]; FrameElement source = elements_[i];
FrameElement target = expected->elements_[i]; FrameElement target = expected->elements_[i];
...@@ -200,7 +199,7 @@ void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) { ...@@ -200,7 +199,7 @@ void VirtualFrame::PrepareMergeTo(VirtualFrame* expected) {
if (cgen()->frame() == this) { if (cgen()->frame() == this) {
Unuse(source.reg()); Unuse(source.reg());
} else { } else {
register_locations_[source.reg().code()] = kIllegalIndex; set_register_location(source.reg(), kIllegalIndex);
} }
} }
elements_[i] = target; elements_[i] = target;
...@@ -224,16 +223,16 @@ void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) { ...@@ -224,16 +223,16 @@ void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
ASSERT(height() >= spilled_args); ASSERT(height() >= spilled_args);
ASSERT(dropped_args <= spilled_args); ASSERT(dropped_args <= spilled_args);
SyncRange(0, elements_.length() - 1); SyncRange(0, element_count() - 1);
// Spill registers. // Spill registers.
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i)) { if (is_used(i)) {
SpillElementAt(register_locations_[i]); SpillElementAt(register_location(i));
} }
} }
// Spill the arguments. // Spill the arguments.
for (int i = elements_.length() - spilled_args; i < elements_.length(); i++) { for (int i = element_count() - spilled_args; i < element_count(); i++) {
if (!elements_[i].is_memory()) { if (!elements_[i].is_memory()) {
SpillElementAt(i); SpillElementAt(i);
} }
...@@ -257,9 +256,9 @@ void VirtualFrame::PrepareForReturn() { ...@@ -257,9 +256,9 @@ void VirtualFrame::PrepareForReturn() {
void VirtualFrame::SetElementAt(int index, Result* value) { void VirtualFrame::SetElementAt(int index, Result* value) {
int frame_index = elements_.length() - index - 1; int frame_index = element_count() - index - 1;
ASSERT(frame_index >= 0); ASSERT(frame_index >= 0);
ASSERT(frame_index < elements_.length()); ASSERT(frame_index < element_count());
ASSERT(value->is_valid()); ASSERT(value->is_valid());
FrameElement original = elements_[frame_index]; FrameElement original = elements_[frame_index];
...@@ -283,7 +282,7 @@ void VirtualFrame::SetElementAt(int index, Result* value) { ...@@ -283,7 +282,7 @@ void VirtualFrame::SetElementAt(int index, Result* value) {
// The register already appears on the frame. Either the existing // The register already appears on the frame. Either the existing
// register element, or the new element at frame_index, must be made // register element, or the new element at frame_index, must be made
// a copy. // a copy.
int i = register_index(value->reg()); int i = register_location(value->reg());
ASSERT(value->static_type() == elements_[i].static_type()); ASSERT(value->static_type() == elements_[i].static_type());
if (i < frame_index) { if (i < frame_index) {
...@@ -299,8 +298,8 @@ void VirtualFrame::SetElementAt(int index, Result* value) { ...@@ -299,8 +298,8 @@ void VirtualFrame::SetElementAt(int index, Result* value) {
elements_[i].set_sync(); elements_[i].set_sync();
} }
elements_[frame_index].clear_sync(); elements_[frame_index].clear_sync();
register_locations_[value->reg().code()] = frame_index; set_register_location(value->reg(), frame_index);
for (int j = i + 1; j < elements_.length(); j++) { for (int j = i + 1; j < element_count(); j++) {
if (elements_[j].is_copy() && elements_[j].index() == i) { if (elements_[j].is_copy() && elements_[j].index() == i) {
elements_[j].set_index(frame_index); elements_[j].set_index(frame_index);
} }
...@@ -331,12 +330,12 @@ void VirtualFrame::PushFrameSlotAt(int index) { ...@@ -331,12 +330,12 @@ void VirtualFrame::PushFrameSlotAt(int index) {
void VirtualFrame::Push(Register reg, StaticType static_type) { void VirtualFrame::Push(Register reg, StaticType static_type) {
if (is_used(reg)) { if (is_used(reg)) {
int index = register_index(reg); int index = register_location(reg);
FrameElement element = CopyElementAt(index); FrameElement element = CopyElementAt(index);
ASSERT(static_type.merge(element.static_type()) == element.static_type()); ASSERT(static_type.merge(element.static_type()) == element.static_type());
elements_.Add(element); elements_.Add(element);
} else { } else {
Use(reg, elements_.length()); Use(reg, element_count());
FrameElement element = FrameElement element =
FrameElement::RegisterElement(reg, FrameElement::RegisterElement(reg,
FrameElement::NOT_SYNCED, FrameElement::NOT_SYNCED,
...@@ -366,15 +365,15 @@ void VirtualFrame::Nip(int num_dropped) { ...@@ -366,15 +365,15 @@ void VirtualFrame::Nip(int num_dropped) {
bool VirtualFrame::Equals(VirtualFrame* other) { bool VirtualFrame::Equals(VirtualFrame* other) {
#ifdef DEBUG #ifdef DEBUG
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (register_locations_[i] != other->register_locations_[i]) { if (register_location(i) != other->register_location(i)) {
return false; return false;
} }
} }
if (elements_.length() != other->elements_.length()) return false; if (element_count() != other->element_count()) return false;
#endif #endif
if (stack_pointer_ != other->stack_pointer_) return false; if (stack_pointer_ != other->stack_pointer_) return false;
for (int i = 0; i < elements_.length(); i++) { for (int i = 0; i < element_count(); i++) {
if (!elements_[i].Equals(other->elements_[i])) return false; if (!elements_[i].Equals(other->elements_[i])) return false;
} }
......
...@@ -682,16 +682,6 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* a, ...@@ -682,16 +682,6 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* a,
return NULL; return NULL;
} }
bool RegisterAllocator::IsReserved(int a) {
UNIMPLEMENTED();
return false;
}
RegisterFile RegisterAllocator::Reserved() {
UNIMPLEMENTED();
return RegisterFile();
}
const int RelocInfo::kApplyMask = -1; const int RelocInfo::kApplyMask = -1;
StackFrame::Type StackFrame::ComputeType(StackFrame::State* a) { StackFrame::Type StackFrame::ComputeType(StackFrame::State* a) {
......
...@@ -61,10 +61,9 @@ namespace internal { ...@@ -61,10 +61,9 @@ namespace internal {
// mode. This way we get the compile-time error checking in debug mode // mode. This way we get the compile-time error checking in debug mode
// and best performance in optimized code. // and best performance in optimized code.
// //
const int kNumRegisters = 16;
struct Register { struct Register {
bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; } bool is_valid() const { return 0 <= code_ && code_ < 16; }
bool is(Register reg) const { return code_ == reg.code_; } bool is(Register reg) const { return code_ == reg.code_; }
// The byte-register distinction of ai32 has dissapeared. // The byte-register distinction of ai32 has dissapeared.
bool is_byte_register() const { return false; } bool is_byte_register() const { return false; }
......
...@@ -578,14 +578,14 @@ class CodeGenerator: public AstVisitor { ...@@ -578,14 +578,14 @@ class CodeGenerator: public AstVisitor {
void CodeForSourcePosition(int pos); void CodeForSourcePosition(int pos);
#ifdef DEBUG #ifdef DEBUG
// True if the registers are valid for entry to a block. There should be // True if the registers are valid for entry to a block. There should
// no frame-external references to eax, ebx, ecx, edx, or edi. // be no frame-external references to (non-reserved) registers.
bool HasValidEntryRegisters(); bool HasValidEntryRegisters();
#endif #endif
bool is_eval_; // Tells whether code is generated for eval. bool is_eval_; // Tells whether code is generated for eval.
Handle<Script> script_; Handle<Script> script_;
List<DeferredCode*> deferred_; ZoneList<DeferredCode*> deferred_;
// Assembler // Assembler
MacroAssembler* masm_; // to generate code MacroAssembler* masm_; // to generate code
......
// 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.
#ifndef V8_X64_REGISTER_ALLOCATOR_X64_INL_H_
#define V8_X64_REGISTER_ALLOCATOR_X64_INL_H_
#include "v8.h"
namespace v8 {
namespace internal {
// -------------------------------------------------------------------------
// RegisterAllocator implementation.
bool RegisterAllocator::IsReserved(Register reg) {
// All registers are reserved for now.
return true;
}
// The register allocator uses small integers to represent the
// non-reserved assembler registers.
int RegisterAllocator::ToNumber(Register reg) {
ASSERT(reg.is_valid() && !IsReserved(reg));
UNIMPLEMENTED();
return -1;
}
Register RegisterAllocator::ToRegister(int num) {
ASSERT(num >= 0 && num < kNumRegisters);
UNIMPLEMENTED();
return no_reg;
}
void RegisterAllocator::Initialize() {
UNIMPLEMENTED();
}
} } // namespace v8::internal
#endif // V8_X64_REGISTER_ALLOCATOR_X64_INL_H_
// 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.
#ifndef V8_X64_REGISTER_ALLOCATOR_X64_H_
#define V8_X64_REGISTER_ALLOCATOR_X64_H_
namespace v8 {
namespace internal {
class RegisterAllocatorConstants : public AllStatic {
public:
// Register allocation is not yet implemented on x64, but C++
// forbids 0-length arrays so we use 1 as the number of registers.
static const int kNumRegisters = 1;
static const int kInvalidRegister = -1;
};
} } // namespace v8::internal
#endif // V8_X64_REGISTER_ALLOCATOR_X64_H_
...@@ -83,21 +83,35 @@ class VirtualFrame : public ZoneObject { ...@@ -83,21 +83,35 @@ class VirtualFrame : public ZoneObject {
// Create a duplicate of an existing valid frame element. // Create a duplicate of an existing valid frame element.
FrameElement CopyElementAt(int index); FrameElement CopyElementAt(int index);
// The number of elements on the virtual frame.
int element_count() { return elements_.length(); }
// The height of the virtual expression stack. // The height of the virtual expression stack.
int height() { int height() {
return elements_.length() - expression_base_index(); return element_count() - expression_base_index();
}
int register_location(int num) {
ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
return register_locations_[num];
}
int register_location(Register reg) {
return register_locations_[RegisterAllocator::ToNumber(reg)];
} }
int register_index(Register reg) { void set_register_location(Register reg, int index) {
return register_locations_[reg.code()]; register_locations_[RegisterAllocator::ToNumber(reg)] = index;
} }
bool is_used(int reg_code) { bool is_used(int num) {
return register_locations_[reg_code] != kIllegalIndex; ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
return register_locations_[num] != kIllegalIndex;
} }
bool is_used(Register reg) { bool is_used(Register reg) {
return is_used(reg.code()); return register_locations_[RegisterAllocator::ToNumber(reg)]
!= kIllegalIndex;
} }
// Add extra in-memory elements to the top of the frame to match an actual // Add extra in-memory elements to the top of the frame to match an actual
...@@ -112,7 +126,7 @@ class VirtualFrame : public ZoneObject { ...@@ -112,7 +126,7 @@ class VirtualFrame : public ZoneObject {
// handler). No code will be emitted. // handler). No code will be emitted.
void Forget(int count) { void Forget(int count) {
ASSERT(count >= 0); ASSERT(count >= 0);
ASSERT(stack_pointer_ == elements_.length() - 1); ASSERT(stack_pointer_ == element_count() - 1);
stack_pointer_ -= count; stack_pointer_ -= count;
ForgetElements(count); ForgetElements(count);
} }
...@@ -127,7 +141,7 @@ class VirtualFrame : public ZoneObject { ...@@ -127,7 +141,7 @@ class VirtualFrame : public ZoneObject {
// Spill all occurrences of a specific register from the frame. // Spill all occurrences of a specific register from the frame.
void Spill(Register reg) { void Spill(Register reg) {
if (is_used(reg)) SpillElementAt(register_index(reg)); if (is_used(reg)) SpillElementAt(register_location(reg));
} }
// Spill all occurrences of an arbitrary register if possible. Return the // Spill all occurrences of an arbitrary register if possible. Return the
...@@ -135,6 +149,9 @@ class VirtualFrame : public ZoneObject { ...@@ -135,6 +149,9 @@ class VirtualFrame : public ZoneObject {
// (ie, they all have frame-external references). // (ie, they all have frame-external references).
Register SpillAnyRegister(); Register SpillAnyRegister();
// Sync the range of elements in [begin, end] with memory.
void SyncRange(int begin, int end);
// Make this frame so that an arbitrary frame of the same height can // Make this frame so that an arbitrary frame of the same height can
// be merged to it. Copies and constants are removed from the // be merged to it. Copies and constants are removed from the
// topmost mergable_elements elements of the frame. A // topmost mergable_elements elements of the frame. A
...@@ -158,11 +175,8 @@ class VirtualFrame : public ZoneObject { ...@@ -158,11 +175,8 @@ class VirtualFrame : public ZoneObject {
// one to NULL by an unconditional jump. // one to NULL by an unconditional jump.
void DetachFromCodeGenerator() { void DetachFromCodeGenerator() {
RegisterAllocator* cgen_allocator = cgen()->allocator(); RegisterAllocator* cgen_allocator = cgen()->allocator();
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i)) { if (is_used(i)) cgen_allocator->Unuse(i);
Register temp = { i };
cgen_allocator->Unuse(temp);
}
} }
} }
...@@ -172,11 +186,8 @@ class VirtualFrame : public ZoneObject { ...@@ -172,11 +186,8 @@ class VirtualFrame : public ZoneObject {
// binding a label. // binding a label.
void AttachToCodeGenerator() { void AttachToCodeGenerator() {
RegisterAllocator* cgen_allocator = cgen()->allocator(); RegisterAllocator* cgen_allocator = cgen()->allocator();
for (int i = 0; i < kNumRegisters; i++) { for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i)) { if (is_used(i)) cgen_allocator->Use(i);
Register temp = { i };
cgen_allocator->Use(temp);
}
} }
} }
...@@ -211,11 +222,11 @@ class VirtualFrame : public ZoneObject { ...@@ -211,11 +222,11 @@ class VirtualFrame : public ZoneObject {
} }
void PushElementAt(int index) { void PushElementAt(int index) {
PushFrameSlotAt(elements_.length() - index - 1); PushFrameSlotAt(element_count() - index - 1);
} }
void StoreToElementAt(int index) { void StoreToElementAt(int index) {
StoreToFrameSlotAt(elements_.length() - index - 1); StoreToFrameSlotAt(element_count() - index - 1);
} }
// A frame-allocated local as an assembly operand. // A frame-allocated local as an assembly operand.
...@@ -352,7 +363,7 @@ class VirtualFrame : public ZoneObject { ...@@ -352,7 +363,7 @@ class VirtualFrame : public ZoneObject {
void Drop() { Drop(1); } void Drop() { Drop(1); }
// Duplicate the top element of the frame. // Duplicate the top element of the frame.
void Dup() { PushFrameSlotAt(elements_.length() - 1); } void Dup() { PushFrameSlotAt(element_count() - 1); }
// Pop an element from the top of the expression stack. Returns a // Pop an element from the top of the expression stack. Returns a
// Result, which may be a constant or a register. // Result, which may be a constant or a register.
...@@ -407,7 +418,7 @@ class VirtualFrame : public ZoneObject { ...@@ -407,7 +418,7 @@ class VirtualFrame : public ZoneObject {
// The index of the register frame element using each register, or // The index of the register frame element using each register, or
// kIllegalIndex if a register is not on the frame. // kIllegalIndex if a register is not on the frame.
int register_locations_[kNumRegisters]; int register_locations_[RegisterAllocator::kNumRegisters];
// The number of frame-allocated locals and parameters respectively. // The number of frame-allocated locals and parameters respectively.
int parameter_count() { return cgen()->scope()->num_parameters(); } int parameter_count() { return cgen()->scope()->num_parameters(); }
...@@ -420,7 +431,7 @@ class VirtualFrame : public ZoneObject { ...@@ -420,7 +431,7 @@ class VirtualFrame : public ZoneObject {
// The index of the first parameter. The receiver lies below the first // The index of the first parameter. The receiver lies below the first
// parameter. // parameter.
int param0_index() const { return 1; } int param0_index() { return 1; }
// The index of the context slot in the frame. It is immediately // The index of the context slot in the frame. It is immediately
// above the frame pointer. // above the frame pointer.
...@@ -440,8 +451,8 @@ class VirtualFrame : public ZoneObject { ...@@ -440,8 +451,8 @@ class VirtualFrame : public ZoneObject {
// Convert a frame index into a frame pointer relative offset into the // Convert a frame index into a frame pointer relative offset into the
// actual stack. // actual stack.
int fp_relative(int index) { int fp_relative(int index) {
ASSERT(index < elements_.length()); ASSERT(index < element_count());
ASSERT(frame_pointer() < elements_.length()); // FP is on the frame. ASSERT(frame_pointer() < element_count()); // FP is on the frame.
return (frame_pointer() - index) * kPointerSize; return (frame_pointer() - index) * kPointerSize;
} }
...@@ -450,7 +461,7 @@ class VirtualFrame : public ZoneObject { ...@@ -450,7 +461,7 @@ class VirtualFrame : public ZoneObject {
// of updating the index of the register's location in the frame. // of updating the index of the register's location in the frame.
void Use(Register reg, int index) { void Use(Register reg, int index) {
ASSERT(!is_used(reg)); ASSERT(!is_used(reg));
register_locations_[reg.code()] = index; set_register_location(reg, index);
cgen()->allocator()->Use(reg); cgen()->allocator()->Use(reg);
} }
...@@ -458,8 +469,8 @@ class VirtualFrame : public ZoneObject { ...@@ -458,8 +469,8 @@ class VirtualFrame : public ZoneObject {
// decrements the register's external reference count and invalidates the // decrements the register's external reference count and invalidates the
// index of the register's location in the frame. // index of the register's location in the frame.
void Unuse(Register reg) { void Unuse(Register reg) {
ASSERT(register_locations_[reg.code()] != kIllegalIndex); ASSERT(is_used(reg));
register_locations_[reg.code()] = kIllegalIndex; set_register_location(reg, kIllegalIndex);
cgen()->allocator()->Unuse(reg); cgen()->allocator()->Unuse(reg);
} }
...@@ -473,9 +484,6 @@ class VirtualFrame : public ZoneObject { ...@@ -473,9 +484,6 @@ class VirtualFrame : public ZoneObject {
// Keep the element type as register or constant, and clear the dirty bit. // Keep the element type as register or constant, and clear the dirty bit.
void SyncElementAt(int index); void SyncElementAt(int index);
// Sync the range of elements in [begin, end).
void SyncRange(int begin, int end);
// Sync a single unsynced element that lies beneath or at the stack pointer. // Sync a single unsynced element that lies beneath or at the stack pointer.
void SyncElementBelowStackPointer(int index); void SyncElementBelowStackPointer(int index);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment