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:
parent
8be7fd052e
commit
6ed860b7d6
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user