Re-enable using push instructions for syncing the virtual frame.

This change fixes the problem with the original version of this approach
(r3032) that may lead to a corrupted stack if we would invoke spilling during 
syncing a large SMI constant (unsafe SMIs) in the virtual frame.

The new code for storing unsafe SMI constants does not use an extra temporary 
register. This prevents the compiler from ever having to spill during a 
virutal frame sync operation.

For storing a large SMI constant we previously generated:

  mov ecx, (large_smi & 0x0000ffff)
  xor ecx, (large_smi & 0xffff0000)
  push ecx

we now generate:

  push (large_smi & 0x0000ffff)
  or   [esp], (large_smi & 0xffff0000)

Not using a temporary register avoids spilling within an nvocation 
of VirtualFrame::SyncRange.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3313 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9bafc329
...@@ -3939,12 +3939,28 @@ void CodeGenerator::VisitLiteral(Literal* node) { ...@@ -3939,12 +3939,28 @@ void CodeGenerator::VisitLiteral(Literal* node) {
} }
void CodeGenerator::LoadUnsafeSmi(Register target, Handle<Object> value) { void CodeGenerator::PushUnsafeSmi(Handle<Object> value) {
ASSERT(value->IsSmi());
int bits = reinterpret_cast<int>(*value);
__ push(Immediate(bits & 0x0000FFFF));
__ or_(Operand(esp, 0), Immediate(bits & 0xFFFF0000));
}
void CodeGenerator::StoreUnsafeSmiToLocal(int offset, Handle<Object> value) {
ASSERT(value->IsSmi());
int bits = reinterpret_cast<int>(*value);
__ mov(Operand(ebp, offset), Immediate(bits & 0x0000FFFF));
__ or_(Operand(ebp, offset), Immediate(bits & 0xFFFF0000));
}
void CodeGenerator::MoveUnsafeSmi(Register target, Handle<Object> value) {
ASSERT(target.is_valid()); ASSERT(target.is_valid());
ASSERT(value->IsSmi()); ASSERT(value->IsSmi());
int bits = reinterpret_cast<int>(*value); int bits = reinterpret_cast<int>(*value);
__ Set(target, Immediate(bits & 0x0000FFFF)); __ Set(target, Immediate(bits & 0x0000FFFF));
__ xor_(target, bits & 0xFFFF0000); __ or_(target, bits & 0xFFFF0000);
} }
......
...@@ -468,9 +468,11 @@ class CodeGenerator: public AstVisitor { ...@@ -468,9 +468,11 @@ class CodeGenerator: public AstVisitor {
// than 16 bits. // than 16 bits.
static const int kMaxSmiInlinedBits = 16; static const int kMaxSmiInlinedBits = 16;
bool IsUnsafeSmi(Handle<Object> value); bool IsUnsafeSmi(Handle<Object> value);
// Load an integer constant x into a register target using // Load an integer constant x into a register target or into the stack using
// at most 16 bits of user-controlled data per assembly operation. // at most 16 bits of user-controlled data per assembly operation.
void LoadUnsafeSmi(Register target, Handle<Object> value); void MoveUnsafeSmi(Register target, Handle<Object> value);
void StoreUnsafeSmiToLocal(int offset, Handle<Object> value);
void PushUnsafeSmi(Handle<Object> value);
void CallWithArguments(ZoneList<Expression*>* arguments, int position); void CallWithArguments(ZoneList<Expression*>* arguments, int position);
......
...@@ -42,7 +42,7 @@ void Result::ToRegister() { ...@@ -42,7 +42,7 @@ void Result::ToRegister() {
Result fresh = CodeGeneratorScope::Current()->allocator()->Allocate(); Result fresh = CodeGeneratorScope::Current()->allocator()->Allocate();
ASSERT(fresh.is_valid()); ASSERT(fresh.is_valid());
if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) { if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) {
CodeGeneratorScope::Current()->LoadUnsafeSmi(fresh.reg(), handle()); CodeGeneratorScope::Current()->MoveUnsafeSmi(fresh.reg(), handle());
} else { } else {
CodeGeneratorScope::Current()->masm()->Set(fresh.reg(), CodeGeneratorScope::Current()->masm()->Set(fresh.reg(),
Immediate(handle())); Immediate(handle()));
...@@ -64,7 +64,7 @@ void Result::ToRegister(Register target) { ...@@ -64,7 +64,7 @@ void Result::ToRegister(Register target) {
} else { } else {
ASSERT(is_constant()); ASSERT(is_constant());
if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) { if (CodeGeneratorScope::Current()->IsUnsafeSmi(handle())) {
CodeGeneratorScope::Current()->LoadUnsafeSmi(fresh.reg(), handle()); CodeGeneratorScope::Current()->MoveUnsafeSmi(fresh.reg(), handle());
} else { } else {
CodeGeneratorScope::Current()->masm()->Set(fresh.reg(), CodeGeneratorScope::Current()->masm()->Set(fresh.reg(),
Immediate(handle())); Immediate(handle()));
......
...@@ -75,10 +75,7 @@ void VirtualFrame::SyncElementBelowStackPointer(int index) { ...@@ -75,10 +75,7 @@ void VirtualFrame::SyncElementBelowStackPointer(int index) {
case FrameElement::CONSTANT: case FrameElement::CONSTANT:
if (cgen()->IsUnsafeSmi(element.handle())) { if (cgen()->IsUnsafeSmi(element.handle())) {
Result temp = cgen()->allocator()->Allocate(); cgen()->StoreUnsafeSmiToLocal(fp_relative(index), element.handle());
ASSERT(temp.is_valid());
cgen()->LoadUnsafeSmi(temp.reg(), element.handle());
__ mov(Operand(ebp, fp_relative(index)), temp.reg());
} else { } else {
__ Set(Operand(ebp, fp_relative(index)), __ Set(Operand(ebp, fp_relative(index)),
Immediate(element.handle())); Immediate(element.handle()));
...@@ -127,10 +124,7 @@ void VirtualFrame::SyncElementByPushing(int index) { ...@@ -127,10 +124,7 @@ void VirtualFrame::SyncElementByPushing(int index) {
case FrameElement::CONSTANT: case FrameElement::CONSTANT:
if (cgen()->IsUnsafeSmi(element.handle())) { if (cgen()->IsUnsafeSmi(element.handle())) {
Result temp = cgen()->allocator()->Allocate(); cgen()->PushUnsafeSmi(element.handle());
ASSERT(temp.is_valid());
cgen()->LoadUnsafeSmi(temp.reg(), element.handle());
__ push(temp.reg());
} else { } else {
__ push(Immediate(element.handle())); __ push(Immediate(element.handle()));
} }
...@@ -161,15 +155,16 @@ void VirtualFrame::SyncRange(int begin, int end) { ...@@ -161,15 +155,16 @@ void VirtualFrame::SyncRange(int begin, int end) {
// on the stack. // on the stack.
int start = Min(begin, stack_pointer_ + 1); int start = Min(begin, stack_pointer_ + 1);
// If positive we have to adjust the stack pointer. // Emit normal push instructions for elements above stack pointer
int delta = end - stack_pointer_; // and use mov instructions if we are below stack pointer.
if (delta > 0) {
stack_pointer_ = end;
__ sub(Operand(esp), Immediate(delta * kPointerSize));
}
for (int i = start; i <= end; i++) { for (int i = start; i <= end; i++) {
if (!elements_[i].is_synced()) SyncElementBelowStackPointer(i); if (!elements_[i].is_synced()) {
if (i <= stack_pointer_) {
SyncElementBelowStackPointer(i);
} else {
SyncElementByPushing(i);
}
}
} }
} }
...@@ -198,7 +193,7 @@ void VirtualFrame::MakeMergable() { ...@@ -198,7 +193,7 @@ void VirtualFrame::MakeMergable() {
// Emit a move. // Emit a move.
if (element.is_constant()) { if (element.is_constant()) {
if (cgen()->IsUnsafeSmi(element.handle())) { if (cgen()->IsUnsafeSmi(element.handle())) {
cgen()->LoadUnsafeSmi(fresh.reg(), element.handle()); cgen()->MoveUnsafeSmi(fresh.reg(), element.handle());
} else { } else {
__ Set(fresh.reg(), Immediate(element.handle())); __ Set(fresh.reg(), Immediate(element.handle()));
} }
...@@ -299,7 +294,7 @@ void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame* expected) { ...@@ -299,7 +294,7 @@ void VirtualFrame::MergeMoveRegistersToMemory(VirtualFrame* expected) {
if (!source.is_synced()) { if (!source.is_synced()) {
if (cgen()->IsUnsafeSmi(source.handle())) { if (cgen()->IsUnsafeSmi(source.handle())) {
esi_caches = i; esi_caches = i;
cgen()->LoadUnsafeSmi(esi, source.handle()); cgen()->MoveUnsafeSmi(esi, source.handle());
__ mov(Operand(ebp, fp_relative(i)), esi); __ mov(Operand(ebp, fp_relative(i)), esi);
} else { } else {
__ Set(Operand(ebp, fp_relative(i)), Immediate(source.handle())); __ Set(Operand(ebp, fp_relative(i)), Immediate(source.handle()));
...@@ -407,7 +402,7 @@ void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame* expected) { ...@@ -407,7 +402,7 @@ void VirtualFrame::MergeMoveMemoryToRegisters(VirtualFrame* expected) {
case FrameElement::CONSTANT: case FrameElement::CONSTANT:
if (cgen()->IsUnsafeSmi(source.handle())) { if (cgen()->IsUnsafeSmi(source.handle())) {
cgen()->LoadUnsafeSmi(target_reg, source.handle()); cgen()->MoveUnsafeSmi(target_reg, source.handle());
} else { } else {
__ Set(target_reg, Immediate(source.handle())); __ Set(target_reg, Immediate(source.handle()));
} }
......
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