Remove branching and binding with two arguments from the JumpTarget

class.  Manually manage off-frame results at the two sites where they
were used.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2157 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
kmillikin@chromium.org 2009-06-12 14:43:27 +00:00
parent 8be7fd052e
commit 6ed860b7d6
3 changed files with 51 additions and 62 deletions

View File

@ -1871,13 +1871,19 @@ void CodeGenerator::Comparison(Condition cc,
// Implement comparison against a constant Smi, inlining the case // Implement comparison against a constant Smi, inlining the case
// where both sides are Smis. // where both sides are Smis.
left_side.ToRegister(); left_side.ToRegister();
ASSERT(left_side.is_valid());
JumpTarget is_smi;
__ test(left_side.reg(), Immediate(kSmiTagMask));
is_smi.Branch(zero, &left_side, &right_side, taken);
// Setup and call the compare stub, which expects its arguments // Here we split control flow to the stub call and inlined cases
// in registers. // before finally splitting it to the control destination. We use
// a jump target and branching to duplicate the virtual frame at
// the first split. We manually handle the off-frame references
// by reconstituting them on the non-fall-through path.
JumpTarget is_smi;
Register left_reg = left_side.reg();
Handle<Object> right_val = right_side.handle();
__ test(left_side.reg(), Immediate(kSmiTagMask));
is_smi.Branch(zero, taken);
// Setup and call the compare stub.
CompareStub stub(cc, strict); CompareStub stub(cc, strict);
Result result = frame_->CallStub(&stub, &left_side, &right_side); Result result = frame_->CallStub(&stub, &left_side, &right_side);
result.ToRegister(); result.ToRegister();
@ -1886,12 +1892,12 @@ void CodeGenerator::Comparison(Condition cc,
dest->true_target()->Branch(cc); dest->true_target()->Branch(cc);
dest->false_target()->Jump(); dest->false_target()->Jump();
is_smi.Bind(&left_side, &right_side); is_smi.Bind();
left_side.ToRegister(); left_side = Result(left_reg);
right_side = Result(right_val);
// Test smi equality and comparison by signed int comparison. // Test smi equality and comparison by signed int comparison.
if (IsUnsafeSmi(right_side.handle())) { if (IsUnsafeSmi(right_side.handle())) {
right_side.ToRegister(); right_side.ToRegister();
ASSERT(right_side.is_valid());
__ cmp(left_side.reg(), Operand(right_side.reg())); __ cmp(left_side.reg(), Operand(right_side.reg()));
} else { } else {
__ cmp(Operand(left_side.reg()), Immediate(right_side.handle())); __ cmp(Operand(left_side.reg()), Immediate(right_side.handle()));
@ -1943,35 +1949,50 @@ void CodeGenerator::Comparison(Condition cc,
(right_side.is_constant() && !right_side.handle()->IsSmi()); (right_side.is_constant() && !right_side.handle()->IsSmi());
left_side.ToRegister(); left_side.ToRegister();
right_side.ToRegister(); right_side.ToRegister();
JumpTarget is_smi;
if (!known_non_smi) { if (known_non_smi) {
// Check for the smi case. // When non-smi, call out to the compare stub.
CompareStub stub(cc, strict);
Result answer = frame_->CallStub(&stub, &left_side, &right_side);
if (cc == equal) {
__ test(answer.reg(), Operand(answer.reg()));
} else {
__ cmp(answer.reg(), 0);
}
answer.Unuse();
dest->Split(cc);
} else {
// Here we split control flow to the stub call and inlined cases
// before finally splitting it to the control destination. We use
// a jump target and branching to duplicate the virtual frame at
// the first split. We manually handle the off-frame references
// by reconstituting them on the non-fall-through path.
JumpTarget is_smi;
Register left_reg = left_side.reg();
Register right_reg = right_side.reg();
Result temp = allocator_->Allocate(); Result temp = allocator_->Allocate();
ASSERT(temp.is_valid()); ASSERT(temp.is_valid());
__ mov(temp.reg(), left_side.reg()); __ mov(temp.reg(), left_side.reg());
__ or_(temp.reg(), Operand(right_side.reg())); __ or_(temp.reg(), Operand(right_side.reg()));
__ test(temp.reg(), Immediate(kSmiTagMask)); __ test(temp.reg(), Immediate(kSmiTagMask));
temp.Unuse(); temp.Unuse();
is_smi.Branch(zero, &left_side, &right_side, taken); is_smi.Branch(zero, taken);
} // When non-smi, call out to the compare stub.
// When non-smi, call out to the compare stub, which expects its CompareStub stub(cc, strict);
// arguments in registers. Result answer = frame_->CallStub(&stub, &left_side, &right_side);
CompareStub stub(cc, strict); if (cc == equal) {
Result answer = frame_->CallStub(&stub, &left_side, &right_side); __ test(answer.reg(), Operand(answer.reg()));
if (cc == equal) { } else {
__ test(answer.reg(), Operand(answer.reg())); __ cmp(answer.reg(), 0);
} else { }
__ cmp(answer.reg(), 0); answer.Unuse();
}
answer.Unuse();
if (known_non_smi) {
dest->Split(cc);
} else {
dest->true_target()->Branch(cc); dest->true_target()->Branch(cc);
dest->false_target()->Jump(); dest->false_target()->Jump();
is_smi.Bind(&left_side, &right_side);
left_side.ToRegister(); is_smi.Bind();
right_side.ToRegister(); left_side = Result(left_reg);
right_side = Result(right_reg);
__ cmp(left_side.reg(), Operand(right_side.reg())); __ cmp(left_side.reg(), Operand(right_side.reg()));
right_side.Unuse(); right_side.Unuse();
left_side.Unuse(); left_side.Unuse();

View File

@ -268,25 +268,6 @@ void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
} }
void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
ASSERT(cgen()->frame() != NULL);
// We want to check that non-frame registers at the call site stay in
// the same registers on the fall-through branch.
DECLARE_ARGCHECK_VARS(arg0);
DECLARE_ARGCHECK_VARS(arg1);
cgen()->frame()->Push(arg0);
cgen()->frame()->Push(arg1);
DoBranch(cc, hint);
*arg1 = cgen()->frame()->Pop();
*arg0 = cgen()->frame()->Pop();
ASSERT_ARGCHECK(arg0);
ASSERT_ARGCHECK(arg1);
}
void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) { void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
ASSERT(cgen()->has_valid_frame()); ASSERT(cgen()->has_valid_frame());
@ -328,17 +309,6 @@ void JumpTarget::Bind(Result* arg) {
} }
void JumpTarget::Bind(Result* arg0, Result* arg1) {
if (cgen()->has_valid_frame()) {
cgen()->frame()->Push(arg0);
cgen()->frame()->Push(arg1);
}
DoBind();
*arg1 = cgen()->frame()->Pop();
*arg0 = cgen()->frame()->Pop();
}
void JumpTarget::AddReachingFrame(VirtualFrame* frame) { void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
ASSERT(reaching_frames_.length() == merge_labels_.length()); ASSERT(reaching_frames_.length() == merge_labels_.length());
ASSERT(entry_frame_ == NULL); ASSERT(entry_frame_ == NULL);

View File

@ -113,14 +113,12 @@ class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
// code after the branch. // code after the branch.
virtual void Branch(Condition cc, Hint hint = no_hint); virtual void Branch(Condition cc, Hint hint = no_hint);
virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint); virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
void Branch(Condition cc, Result* arg0, Result* arg1, Hint hint = no_hint);
// Bind a jump target. If there is no current frame at the binding // Bind a jump target. If there is no current frame at the binding
// site, there must be at least one frame reaching via a forward // site, there must be at least one frame reaching via a forward
// jump. // jump.
virtual void Bind(); virtual void Bind();
virtual void Bind(Result* arg); virtual void Bind(Result* arg);
void Bind(Result* arg0, Result* arg1);
// Emit a call to a jump target. There must be a current frame at // Emit a call to a jump target. There must be a current frame at
// the call. The frame at the target is the same as the current // the call. The frame at the target is the same as the current