Author: whessev8
Date: Wed Jan 7 08:35:15 2009
New Revision: 1041
Modified:
branches/experimental/toiger/src/codegen-ia32.cc
branches/experimental/toiger/src/virtual-frame-ia32.cc
branches/experimental/toiger/src/virtual-frame-ia32.h
Log:
Adds Nip() function, makes UnloadReference() work without spilling
frames.
Review URL: http://codereview.chromium.org/16572
Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc Wed Jan 7 08:35:15
2009
@@ -549,17 +549,7 @@
void CodeGenerator::UnloadReference(Reference* ref) {
// Pop a reference from the stack while preserving TOS.
Comment cmnt(masm_, "[ UnloadReference");
- int size = ref->size();
- if (size == 1) {
- VirtualFrame::SpilledScope spilled_scope(this);
- frame_->EmitPop(eax);
- __ mov(frame_->Top(), eax);
- } else if (size > 1) {
- VirtualFrame::SpilledScope spilled_scope(this);
- frame_->EmitPop(eax);
- frame_->Drop(size);
- frame_->EmitPush(eax);
- }
+ frame_->Nip(ref->size());
}
@@ -3114,7 +3104,7 @@
var->mode() == Variable::CONST &&
node->op() != Token::INIT_VAR && node->op() != Token::INIT_CONST) {
// Assignment ignored - leave the value on the stack.
- } else {
+ } else {
CodeForSourcePosition(node->position());
if (node->op() == Token::INIT_CONST) {
// Dynamic constant initializations must use the function context
Modified: branches/experimental/toiger/src/virtual-frame-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/virtual-frame-ia32.cc (original)
+++ branches/experimental/toiger/src/virtual-frame-ia32.cc Wed Jan 7
08:35:15 2009
@@ -410,6 +410,24 @@
MergeMoveRegistersToRegisters(expected);
MergeMoveMemoryToRegisters(expected);
+ int height_difference = stack_pointer_ - expected->stack_pointer_;
+ if (stack_pointer_ > expected->stack_pointer_) {
+#ifdef DEBUG
+ for (int i = stack_pointer_; i > expected->stack_pointer_; i--) {
+ ASSERT(!elements_[i].is_memory());
+ ASSERT(!elements_[i].is_synced());
+ }
+#endif
+ __ add(Operand(esp), Immediate(height_difference * kPointerSize));
+ stack_pointer_ = expected->stack_pointer_;
+ } else if (stack_pointer_ < expected->stack_pointer_) {
+ // Put valid data on the stack, that will only be accessed by GC.
+ while (stack_pointer_ < expected->stack_pointer_) {
+ __ push(Immediate(Smi::FromInt(0)));
+ stack_pointer_++;
+ }
+ }
+
// At this point, the frames should be identical.
// TODO(): Consider an "equals" method for frames.
ASSERT(stack_pointer_ == expected->stack_pointer_);
@@ -674,25 +692,33 @@
ASSERT(frame_index >= 0);
ASSERT(frame_index < elements_.length());
ASSERT(value->is_valid());
+ FrameElement target = elements_[frame_index];
- // TODO(): if the element is backed by the same register or the same
- // constant, consider preserving the sync bit.
- if (elements_[frame_index].is_register()) {
- Unuse(elements_[frame_index].reg());
+ if (target.is_register()) {
+ Unuse(target.reg());
}
if (value->is_register()) {
Use(value->reg());
- elements_[frame_index] =
- FrameElement::RegisterElement(value->reg(),
- FrameElement::NOT_SYNCED);
+ // Write the new value to the frame, if it is changed.
+ // Otherwise, if target equals value, keep its current sync state.
+ if (!target.is_register() ||
+ !value->reg().is(target.reg())) {
+ elements_[frame_index] =
+ FrameElement::RegisterElement(value->reg(),
+ FrameElement::NOT_SYNCED);
+ }
} else {
ASSERT(value->is_constant());
- elements_[frame_index] =
- FrameElement::ConstantElement(value->handle(),
- FrameElement::NOT_SYNCED);
+ // Write the new value to the frame element, if it is a change.
+ // Otherwise, do nothing, and keep the current sync state.
+ if (!target.is_constant() ||
+ !value->handle().is_identical_to(target.handle())) {
+ elements_[frame_index] =
+ FrameElement::ConstantElement(value->handle(),
+ FrameElement::NOT_SYNCED);
+ }
}
-
value->Unuse();
}
@@ -1004,6 +1030,17 @@
Push(result->handle());
}
result->Unuse();
+}
+
+
+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);
}
Modified: branches/experimental/toiger/src/virtual-frame-ia32.h
==============================================================================
--- branches/experimental/toiger/src/virtual-frame-ia32.h (original)
+++ branches/experimental/toiger/src/virtual-frame-ia32.h Wed Jan 7
08:35:15 2009
@@ -385,6 +385,11 @@
// frame).
void Push(Result* result);
+ // Nip removes zero or more elements from immediately below the top
+ // of the frame, leaving the previous top-of-frame value on top of
+ // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
+ void Nip(int num_dropped);
+
#ifdef DEBUG
bool IsSpilled();
#endif
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---