Commit fbefa72f authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Simple register allocation for ARM. Only top of expression

stack for now.  Next step is probably fixing the binary
op stubs so they can take swapped registers and fixing
the deferred code so it doesn't insist that all registers
except the two operands are flushed.  Generates slightly
worse code sometimes because the peephole push-pop
elimination gets confused when we don't use the same
register all the time (the old code used r0 always).
Review URL: http://codereview.chromium.org/1604002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4368 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent c898c7ae
......@@ -29,6 +29,8 @@
#ifndef V8_ARM_CODEGEN_ARM_INL_H_
#define V8_ARM_CODEGEN_ARM_INL_H_
#include "virtual-frame-arm.h"
namespace v8 {
namespace internal {
......@@ -43,6 +45,7 @@ void CodeGenerator::LoadConditionAndSpill(Expression* expression,
void CodeGenerator::LoadAndSpill(Expression* expression) {
ASSERT(VirtualFrame::SpilledScope::is_spilled());
Load(expression);
}
......@@ -57,11 +60,6 @@ void CodeGenerator::VisitStatementsAndSpill(ZoneList<Statement*>* statements) {
}
void Reference::GetValueAndSpill() {
GetValue();
}
// Platform-specific inline functions.
void DeferredCode::Jump() { __ jmp(&entry_label_); }
......
This diff is collapsed.
......@@ -92,10 +92,6 @@ class Reference BASE_EMBEDDED {
// If the reference is not consumed, it is left in place under its value.
void GetValue();
// Generate code to pop a reference, push the value of the reference,
// and then spill the stack frame.
inline void GetValueAndSpill();
// Generate code to store the value on top of the expression stack in the
// reference. The reference is expected to be immediately below the value
// on the expression stack. The value is stored in the location specified
......@@ -314,6 +310,9 @@ class CodeGenerator: public AstVisitor {
void GenericBinaryOperation(Token::Value op,
OverwriteMode overwrite_mode,
int known_rhs = kUnknownIntValue);
void VirtualFrameBinaryOperation(Token::Value op,
OverwriteMode overwrite_mode,
int known_rhs = kUnknownIntValue);
void Comparison(Condition cc,
Expression* left,
Expression* right,
......@@ -324,6 +323,11 @@ class CodeGenerator: public AstVisitor {
bool reversed,
OverwriteMode mode);
void VirtualFrameSmiOperation(Token::Value op,
Handle<Object> value,
bool reversed,
OverwriteMode mode);
void CallWithArguments(ZoneList<Expression*>* arguments,
CallFunctionFlags flags,
int position);
......
......@@ -180,6 +180,19 @@ void MacroAssembler::Drop(int count, Condition cond) {
}
void MacroAssembler::Swap(Register reg1, Register reg2, Register scratch) {
if (scratch.is(no_reg)) {
eor(reg1, reg1, Operand(reg2));
eor(reg2, reg2, Operand(reg1));
eor(reg1, reg1, Operand(reg2));
} else {
mov(scratch, reg1);
mov(reg1, reg2);
mov(reg2, scratch);
}
}
void MacroAssembler::Call(Label* target) {
bl(target);
}
......@@ -190,6 +203,13 @@ void MacroAssembler::Move(Register dst, Handle<Object> value) {
}
void MacroAssembler::Move(Register dst, Register src) {
if (!dst.is(src)) {
mov(dst, src);
}
}
void MacroAssembler::SmiJumpTable(Register index, Vector<Label*> targets) {
// Empty the const pool.
CheckConstPool(true, true);
......
......@@ -70,8 +70,15 @@ class MacroAssembler: public Assembler {
// from the stack, clobbering only the sp register.
void Drop(int count, Condition cond = al);
// Swap two registers. If the scratch register is omitted then a slightly
// less efficient form using xor instead of mov is emitted.
void Swap(Register reg1, Register reg2, Register scratch = no_reg);
void Call(Label* target);
void Move(Register dst, Handle<Object> value);
// May do nothing if the registers are identical.
void Move(Register dst, Register src);
// Jumps to the label at the index given by the Smi in "index".
void SmiJumpTable(Register index, Vector<Label*> targets);
// Load an object from the root table.
......
......@@ -92,9 +92,6 @@ Register RegisterAllocator::ToRegister(int 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.
}
......
......@@ -33,7 +33,8 @@ namespace internal {
class RegisterAllocatorConstants : public AllStatic {
public:
static const int kNumRegisters = 12;
// No registers are currently managed by the register allocator on ARM.
static const int kNumRegisters = 0;
static const int kInvalidRegister = -1;
};
......
This diff is collapsed.
This diff is collapsed.
......@@ -229,7 +229,12 @@ class DeferredCode: public ZoneObject {
Label entry_label_;
Label exit_label_;
int registers_[RegisterAllocator::kNumRegisters];
// C++ doesn't allow zero length arrays, so we make the array length 1 even
// if we don't need it.
static const int kRegistersArrayLength =
(RegisterAllocator::kNumRegisters == 0) ?
1 : RegisterAllocator::kNumRegisters;
int registers_[kRegistersArrayLength];
#ifdef DEBUG
const char* comment_;
......
......@@ -77,23 +77,10 @@ DeferredCode::DeferredCode()
ASSERT(position_ != RelocInfo::kNoPosition);
CodeGeneratorScope::Current()->AddDeferred(this);
#ifdef DEBUG
comment_ = "";
CodeGeneratorScope::Current()->frame()->AssertIsSpilled();
#endif
// Copy the register locations from the code generator's frame.
// These are the registers that will be spilled on entry to the
// deferred code and restored on exit.
VirtualFrame* frame = CodeGeneratorScope::Current()->frame();
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
int loc = frame->register_location(i);
if (loc == VirtualFrame::kIllegalIndex) {
registers_[i] = kIgnore;
} else {
// Needs to be restored on exit but not saved on entry.
registers_[i] = frame->fp_relative(loc) | kSyncedFlag;
}
}
}
} } // namespace v8::internal
......@@ -213,7 +213,11 @@ class RegisterFile BASE_EMBEDDED {
}
private:
static const int kNumRegisters = RegisterAllocatorConstants::kNumRegisters;
// C++ doesn't like zero length arrays, so we make the array length 1 even if
// we don't need it.
static const int kNumRegisters =
(RegisterAllocatorConstants::kNumRegisters == 0) ?
1 : RegisterAllocatorConstants::kNumRegisters;
int ref_counts_[kNumRegisters];
......
......@@ -131,6 +131,22 @@ void VirtualFrame::SetTypeForParamAt(int index, TypeInfo info) {
elements_[param0_index() + index].set_type_info(info);
}
void VirtualFrame::Nip(int num_dropped) {
ASSERT(num_dropped >= 0);
if (num_dropped == 0) return;
Result tos = Pop();
if (num_dropped > 1) {
Drop(num_dropped - 1);
}
SetElementAt(0, &tos);
}
void VirtualFrame::Push(Smi* value) {
Push(Handle<Object> (value));
}
} } // namespace v8::internal
#endif // V8_VIRTUAL_FRAME_HEAVY_INL_H_
......@@ -295,4 +295,18 @@ void VirtualFrame::PrepareForCall(int spilled_args, int dropped_args) {
}
// If there are any registers referenced only by the frame, spill one.
Register VirtualFrame::SpillAnyRegister() {
// Find the leftmost (ordered by register number) register whose only
// reference is in the frame.
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i) && cgen()->allocator()->count(i) == 1) {
SpillElementAt(register_location(i));
ASSERT(!cgen()->allocator()->is_used(i));
return RegisterAllocator::ToRegister(i);
}
}
return no_reg;
}
} } // namespace v8::internal
......@@ -36,25 +36,4 @@
#include "virtual-frame-light-inl.h"
#endif
namespace v8 {
namespace internal {
void VirtualFrame::Push(Smi* value) {
Push(Handle<Object> (value));
}
void VirtualFrame::Nip(int num_dropped) {
ASSERT(num_dropped >= 0);
if (num_dropped == 0) return;
Result tos = Pop();
if (num_dropped > 1) {
Drop(num_dropped - 1);
}
SetElementAt(0, &tos);
}
} } // namespace v8::internal
#endif // V8_VIRTUAL_FRAME_INL_H_
......@@ -39,54 +39,28 @@ namespace internal {
// the parameters, and a return address. All frame elements are in memory.
VirtualFrame::VirtualFrame()
: element_count_(parameter_count() + 2),
stack_pointer_(parameter_count() + 1) {
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
register_locations_[i] = kIllegalIndex;
}
}
top_of_stack_state_(NO_TOS_REGISTERS),
register_allocation_map_(0) { }
// When cloned, a frame is a deep copy of the original.
VirtualFrame::VirtualFrame(VirtualFrame* original)
: element_count_(original->element_count()),
stack_pointer_(original->stack_pointer_) {
memcpy(&register_locations_,
original->register_locations_,
sizeof(register_locations_));
}
void VirtualFrame::Push(Handle<Object> value) {
UNIMPLEMENTED();
}
top_of_stack_state_(original->top_of_stack_state_),
register_allocation_map_(original->register_allocation_map_) { }
bool VirtualFrame::Equals(VirtualFrame* other) {
#ifdef DEBUG
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (register_location(i) != other->register_location(i)) {
return false;
}
}
if (element_count() != other->element_count()) return false;
#endif
if (stack_pointer_ != other->stack_pointer_) return false;
ASSERT(element_count() == other->element_count());
if (top_of_stack_state_ != other->top_of_stack_state_) return false;
if (register_allocation_map_ != other->register_allocation_map_) return false;
return true;
}
void VirtualFrame::SetTypeForLocalAt(int index, TypeInfo info) {
UNIMPLEMENTED();
}
// Everything is always spilled anyway.
void VirtualFrame::SpillAll() {
}
void VirtualFrame::PrepareForReturn() {
SpillAll();
}
......
......@@ -36,17 +36,14 @@ namespace internal {
void VirtualFrame::Adjust(int count) {
ASSERT(count >= 0);
ASSERT(stack_pointer_ == element_count() - 1);
element_count_ += count;
stack_pointer_ += count;
}
// Make the type of the element at a given index be MEMORY.
void VirtualFrame::SpillElementAt(int index) {
// If there are any registers referenced only by the frame, spill one.
Register VirtualFrame::SpillAnyRegister() {
UNIMPLEMENTED();
return no_reg;
}
} } // namespace v8::internal
......@@ -37,21 +37,6 @@ namespace internal {
// -------------------------------------------------------------------------
// VirtualFrame implementation.
// If there are any registers referenced only by the frame, spill one.
Register VirtualFrame::SpillAnyRegister() {
// Find the leftmost (ordered by register number) register whose only
// reference is in the frame.
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (is_used(i) && cgen()->allocator()->count(i) == 1) {
SpillElementAt(register_location(i));
ASSERT(!cgen()->allocator()->is_used(i));
return RegisterAllocator::ToRegister(i);
}
}
return no_reg;
}
// Specialization of List::ResizeAdd to non-inlined version for FrameElements.
// The function ResizeAdd becomes a real function, whose implementation is the
// inlined ResizeAddInternal.
......
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