MIPS: Landing: [hydrogen] optimize switch with string clauses.

Port r10019 (9bbb78bf)

Original commit message:
Patch by Fedor Indutny <fedor.indutny@gmail.com>.

BUG=
TEST=
Review URL: http://codereview.chromium.org/8574073

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10043 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
fschneider@chromium.org 2011-11-22 13:51:56 +00:00
parent de389f1d23
commit be1a94b626
4 changed files with 133 additions and 20 deletions

View File

@ -1677,6 +1677,32 @@ void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) {
} }
Condition LCodeGen::EmitIsString(Register input,
Register temp1,
Label* is_not_string) {
__ JumpIfSmi(input, is_not_string);
__ GetObjectType(input, temp1, temp1);
return lt;
}
void LCodeGen::DoIsStringAndBranch(LIsStringAndBranch* instr) {
Register reg = ToRegister(instr->InputAt(0));
Register temp1 = ToRegister(instr->TempAt(0));
int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id());
Label* false_label = chunk_->GetAssemblyLabel(false_block);
Condition true_cond =
EmitIsString(reg, temp1, false_label);
EmitBranch(true_block, false_block, true_cond, temp1,
Operand(FIRST_NONSTRING_TYPE));
}
void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) {
int true_block = chunk_->LookupDestination(instr->true_block_id()); int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id()); int false_block = chunk_->LookupDestination(instr->false_block_id());
@ -1702,6 +1728,40 @@ void LCodeGen::DoIsUndetectableAndBranch(LIsUndetectableAndBranch* instr) {
} }
static Condition ComputeCompareCondition(Token::Value op) {
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
return eq;
case Token::LT:
return lt;
case Token::GT:
return gt;
case Token::LTE:
return le;
case Token::GTE:
return ge;
default:
UNREACHABLE();
return kNoCondition;
}
}
void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
Token::Value op = instr->op();
int true_block = chunk_->LookupDestination(instr->true_block_id());
int false_block = chunk_->LookupDestination(instr->false_block_id());
Handle<Code> ic = CompareIC::GetUninitialized(op);
CallCode(ic, RelocInfo::CODE_TARGET, instr);
Condition condition = ComputeCompareCondition(op);
EmitBranch(true_block, false_block, condition, v0, Operand(zero_reg));
}
static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
InstanceType from = instr->from(); InstanceType from = instr->from();
InstanceType to = instr->to(); InstanceType to = instr->to();
@ -2002,26 +2062,6 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
} }
static Condition ComputeCompareCondition(Token::Value op) {
switch (op) {
case Token::EQ_STRICT:
case Token::EQ:
return eq;
case Token::LT:
return lt;
case Token::GT:
return gt;
case Token::LTE:
return le;
case Token::GTE:
return ge;
default:
UNREACHABLE();
return kNoCondition;
}
}
void LCodeGen::DoCmpT(LCmpT* instr) { void LCodeGen::DoCmpT(LCmpT* instr) {
Token::Value op = instr->op(); Token::Value op = instr->op();

View File

@ -299,6 +299,13 @@ class LCodeGen BASE_EMBEDDED {
Label* is_not_object, Label* is_not_object,
Label* is_object); Label* is_object);
// Emits optimized code for %_IsString(x). Preserves input register.
// Returns the condition on which a final split to
// true and false label should be made, to optimize fallthrough.
Condition EmitIsString(Register input,
Register temp1,
Label* is_not_string);
// Emits optimized code for %_IsConstructCall(). // Emits optimized code for %_IsConstructCall().
// Caller should branch on equal condition. // Caller should branch on equal condition.
void EmitIsConstructCall(Register temp1, Register temp2); void EmitIsConstructCall(Register temp1, Register temp2);

View File

@ -228,6 +228,13 @@ void LIsObjectAndBranch::PrintDataTo(StringStream* stream) {
} }
void LIsStringAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_string(");
InputAt(0)->PrintTo(stream);
stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
}
void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { void LIsSmiAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if is_smi("); stream->Add("if is_smi(");
InputAt(0)->PrintTo(stream); InputAt(0)->PrintTo(stream);
@ -242,6 +249,14 @@ void LIsUndetectableAndBranch::PrintDataTo(StringStream* stream) {
} }
void LStringCompareAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if string_compare(");
InputAt(0)->PrintTo(stream);
InputAt(1)->PrintTo(stream);
stream->Add(") then B%d else B%d", true_block_id(), false_block_id());
}
void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) {
stream->Add("if has_instance_type("); stream->Add("if has_instance_type(");
InputAt(0)->PrintTo(stream); InputAt(0)->PrintTo(stream);
@ -1452,6 +1467,13 @@ LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) {
} }
LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* temp = TempRegister();
return new LIsStringAndBranch(UseRegisterAtStart(instr->value()), temp);
}
LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged()); ASSERT(instr->value()->representation().IsTagged());
return new LIsSmiAndBranch(Use(instr->value())); return new LIsSmiAndBranch(Use(instr->value()));
@ -1466,6 +1488,17 @@ LInstruction* LChunkBuilder::DoIsUndetectableAndBranch(
} }
LInstruction* LChunkBuilder::DoStringCompareAndBranch(
HStringCompareAndBranch* instr) {
ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged());
LOperand* left = UseFixed(instr->left(), a1);
LOperand* right = UseFixed(instr->right(), a0);
LStringCompareAndBranch* result = new LStringCompareAndBranch(left, right);
return MarkAsCall(result, instr);
}
LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch(
HHasInstanceTypeAndBranch* instr) { HHasInstanceTypeAndBranch* instr) {
ASSERT(instr->value()->representation().IsTagged()); ASSERT(instr->value()->representation().IsTagged());

View File

@ -109,8 +109,10 @@ class LCodeGen;
V(IsConstructCallAndBranch) \ V(IsConstructCallAndBranch) \
V(IsNilAndBranch) \ V(IsNilAndBranch) \
V(IsObjectAndBranch) \ V(IsObjectAndBranch) \
V(IsStringAndBranch) \
V(IsSmiAndBranch) \ V(IsSmiAndBranch) \
V(IsUndetectableAndBranch) \ V(IsUndetectableAndBranch) \
V(StringCompareAndBranch) \
V(JSArrayLength) \ V(JSArrayLength) \
V(Label) \ V(Label) \
V(LazyBailout) \ V(LazyBailout) \
@ -658,6 +660,20 @@ class LIsObjectAndBranch: public LControlInstruction<1, 1> {
}; };
class LIsStringAndBranch: public LControlInstruction<1, 1> {
public:
LIsStringAndBranch(LOperand* value, LOperand* temp) {
inputs_[0] = value;
temps_[0] = temp;
}
DECLARE_CONCRETE_INSTRUCTION(IsStringAndBranch, "is-string-and-branch")
DECLARE_HYDROGEN_ACCESSOR(IsStringAndBranch)
virtual void PrintDataTo(StringStream* stream);
};
class LIsSmiAndBranch: public LControlInstruction<1, 0> { class LIsSmiAndBranch: public LControlInstruction<1, 0> {
public: public:
explicit LIsSmiAndBranch(LOperand* value) { explicit LIsSmiAndBranch(LOperand* value) {
@ -686,6 +702,23 @@ class LIsUndetectableAndBranch: public LControlInstruction<1, 1> {
}; };
class LStringCompareAndBranch: public LControlInstruction<2, 0> {
public:
LStringCompareAndBranch(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
}
DECLARE_CONCRETE_INSTRUCTION(StringCompareAndBranch,
"string-compare-and-branch")
DECLARE_HYDROGEN_ACCESSOR(StringCompareAndBranch)
Token::Value op() const { return hydrogen()->token(); }
virtual void PrintDataTo(StringStream* stream);
};
class LHasInstanceTypeAndBranch: public LControlInstruction<1, 0> { class LHasInstanceTypeAndBranch: public LControlInstruction<1, 0> {
public: public:
explicit LHasInstanceTypeAndBranch(LOperand* value) { explicit LHasInstanceTypeAndBranch(LOperand* value) {