Support symbol comparison in crankshaft.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7865 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
vitalyr@chromium.org 2011-05-11 12:50:04 +00:00
parent b77f131914
commit 03c00ee6a6
14 changed files with 250 additions and 0 deletions

View File

@ -1120,6 +1120,10 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
UseRegisterAtStart(compare->right()));
} else if (v->IsCompareSymbolEq()) {
HCompareSymbolEq* compare = HCompareSymbolEq::cast(v);
return new LCmpSymbolEqAndBranch(UseRegisterAtStart(compare->left()),
UseRegisterAtStart(compare->right()));
} else if (v->IsInstanceOf()) {
HInstanceOf* instance_of = HInstanceOf::cast(v);
LInstruction* result =
@ -1520,6 +1524,15 @@ LInstruction* LChunkBuilder::DoCompareJSObjectEq(
}
LInstruction* LChunkBuilder::DoCompareSymbolEq(
HCompareSymbolEq* instr) {
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
LCmpSymbolEq* result = new LCmpSymbolEq(left, right);
return DefineAsRegister(result);
}
LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());

View File

@ -80,6 +80,8 @@ class LCodeGen;
V(CmpJSObjectEq) \
V(CmpJSObjectEqAndBranch) \
V(CmpMapAndBranch) \
V(CmpSymbolEq) \
V(CmpSymbolEqAndBranch) \
V(CmpT) \
V(CmpTAndBranch) \
V(ConstantD) \
@ -683,6 +685,28 @@ class LCmpJSObjectEqAndBranch: public LControlInstruction<2, 0> {
};
class LCmpSymbolEq: public LTemplateInstruction<1, 2, 0> {
public:
LCmpSymbolEq(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
}
DECLARE_CONCRETE_INSTRUCTION(CmpSymbolEq, "cmp-symbol-eq")
};
class LCmpSymbolEqAndBranch: public LControlInstruction<2, 0> {
public:
LCmpSymbolEqAndBranch(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
}
DECLARE_CONCRETE_INSTRUCTION(CmpSymbolEqAndBranch, "cmp-symbol-eq-and-branch")
};
class LIsNull: public LTemplateInstruction<1, 1, 0> {
public:
explicit LIsNull(LOperand* value) {

View File

@ -1620,6 +1620,28 @@ void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
}
void LCodeGen::DoCmpSymbolEq(LCmpSymbolEq* instr) {
Register left = ToRegister(instr->InputAt(0));
Register right = ToRegister(instr->InputAt(1));
Register result = ToRegister(instr->result());
__ cmp(left, Operand(right));
__ LoadRoot(result, Heap::kTrueValueRootIndex, eq);
__ LoadRoot(result, Heap::kFalseValueRootIndex, ne);
}
void LCodeGen::DoCmpSymbolEqAndBranch(LCmpSymbolEqAndBranch* instr) {
Register left = ToRegister(instr->InputAt(0));
Register right = ToRegister(instr->InputAt(1));
int false_block = chunk_->LookupDestination(instr->false_block_id());
int true_block = chunk_->LookupDestination(instr->true_block_id());
__ cmp(left, Operand(right));
EmitBranch(true_block, false_block, eq);
}
void LCodeGen::DoIsNull(LIsNull* instr) {
Register reg = ToRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());

View File

@ -91,6 +91,7 @@ class LChunkBuilder;
V(Compare) \
V(CompareJSObjectEq) \
V(CompareMap) \
V(CompareSymbolEq) \
V(Constant) \
V(Context) \
V(DeleteProperty) \
@ -2410,6 +2411,40 @@ class HCompareJSObjectEq: public HBinaryOperation {
};
class HCompareSymbolEq: public HBinaryOperation {
public:
HCompareSymbolEq(HValue* left, HValue* right, Token::Value op)
: HBinaryOperation(left, right), op_(op) {
ASSERT(op == Token::EQ || op == Token::EQ_STRICT);
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
SetFlag(kDependsOnMaps);
}
Token::Value op() const { return op_; }
virtual bool EmitAtUses() {
return !HasSideEffects() && !HasMultipleUses();
}
virtual Representation RequiredInputRepresentation(int index) const {
return Representation::Tagged();
}
virtual HType CalculateInferredType() { return HType::Boolean(); }
DECLARE_CONCRETE_INSTRUCTION(CompareSymbolEq);
protected:
virtual bool DataEquals(HValue* other) {
return op_ == HCompareSymbolEq::cast(other)->op_;
}
private:
const Token::Value op_;
};
class HUnaryPredicate: public HUnaryOperation {
public:
explicit HUnaryPredicate(HValue* value) : HUnaryOperation(value) {

View File

@ -4834,6 +4834,18 @@ void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
}
HCompareSymbolEq* HGraphBuilder::BuildSymbolCompare(HValue* left,
HValue* right,
Token::Value op) {
ASSERT(op == Token::EQ || op == Token::EQ_STRICT);
AddInstruction(new(zone()) HCheckNonSmi(left));
AddInstruction(HCheckInstanceType::NewIsSymbol(left));
AddInstruction(new(zone()) HCheckNonSmi(right));
AddInstruction(HCheckInstanceType::NewIsSymbol(right));
return new(zone()) HCompareSymbolEq(left, right, op);
}
HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string,
HValue* index) {
AddInstruction(new(zone()) HCheckNonSmi(string));
@ -5153,6 +5165,9 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
return Bailout("Unsupported non-primitive compare");
break;
}
} else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) &&
(op == Token::EQ || op == Token::EQ_STRICT)) {
instr = BuildSymbolCompare(left, right, op);
} else {
HCompare* compare = new(zone()) HCompare(left, right, op);
Representation r = ToRepresentation(type_info);

View File

@ -871,6 +871,9 @@ class HGraphBuilder: public AstVisitor {
ZoneMapList* types,
Handle<String> name);
HCompareSymbolEq* BuildSymbolCompare(HValue* left,
HValue* right,
Token::Value op);
HStringCharCodeAt* BuildStringCharCodeAt(HValue* string,
HValue* index);
HInstruction* BuildBinaryOperation(BinaryOperation* expr,

View File

@ -1543,6 +1543,31 @@ void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
}
void LCodeGen::DoCmpSymbolEq(LCmpSymbolEq* instr) {
Register left = ToRegister(instr->InputAt(0));
Register right = ToRegister(instr->InputAt(1));
Register result = ToRegister(instr->result());
Label done;
__ cmp(left, Operand(right));
__ mov(result, factory()->false_value());
__ j(not_equal, &done, Label::kNear);
__ mov(result, factory()->true_value());
__ bind(&done);
}
void LCodeGen::DoCmpSymbolEqAndBranch(LCmpSymbolEqAndBranch* instr) {
Register left = ToRegister(instr->InputAt(0));
Register right = ToRegister(instr->InputAt(1));
int false_block = chunk_->LookupDestination(instr->false_block_id());
int true_block = chunk_->LookupDestination(instr->true_block_id());
__ cmp(left, Operand(right));
EmitBranch(true_block, false_block, equal);
}
void LCodeGen::DoIsNull(LIsNull* instr) {
Register reg = ToRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());

View File

@ -1126,6 +1126,10 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
UseRegisterAtStart(compare->right()));
} else if (v->IsCompareSymbolEq()) {
HCompareSymbolEq* compare = HCompareSymbolEq::cast(v);
return new LCmpSymbolEqAndBranch(UseRegisterAtStart(compare->left()),
UseRegisterAtStart(compare->right()));
} else if (v->IsInstanceOf()) {
HInstanceOf* instance_of = HInstanceOf::cast(v);
LOperand* left = UseFixed(instance_of->left(), InstanceofStub::left());
@ -1553,6 +1557,15 @@ LInstruction* LChunkBuilder::DoCompareJSObjectEq(
}
LInstruction* LChunkBuilder::DoCompareSymbolEq(
HCompareSymbolEq* instr) {
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
LCmpSymbolEq* result = new LCmpSymbolEq(left, right);
return DefineAsRegister(result);
}
LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());

View File

@ -73,6 +73,8 @@ class LCodeGen;
V(CmpIDAndBranch) \
V(CmpJSObjectEq) \
V(CmpJSObjectEqAndBranch) \
V(CmpSymbolEq) \
V(CmpSymbolEqAndBranch) \
V(CmpMapAndBranch) \
V(CmpT) \
V(CmpTAndBranch) \
@ -668,6 +670,28 @@ class LCmpJSObjectEqAndBranch: public LControlInstruction<2, 0> {
};
class LCmpSymbolEq: public LTemplateInstruction<1, 2, 0> {
public:
LCmpSymbolEq(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
}
DECLARE_CONCRETE_INSTRUCTION(CmpSymbolEq, "cmp-symbol-eq")
};
class LCmpSymbolEqAndBranch: public LControlInstruction<2, 0> {
public:
LCmpSymbolEqAndBranch(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
}
DECLARE_CONCRETE_INSTRUCTION(CmpSymbolEqAndBranch, "cmp-symbol-eq-and-branch")
};
class LIsNull: public LTemplateInstruction<1, 1, 0> {
public:
explicit LIsNull(LOperand* value) {

View File

@ -229,6 +229,9 @@ TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) {
return TypeInfo::Smi();
case CompareIC::HEAP_NUMBERS:
return TypeInfo::Number();
case CompareIC::SYMBOLS:
case CompareIC::STRINGS:
return TypeInfo::String();
case CompareIC::OBJECTS:
// TODO(kasperl): We really need a type for JS objects here.
return TypeInfo::NonPrimitive();
@ -239,6 +242,16 @@ TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) {
}
bool TypeFeedbackOracle::IsSymbolCompare(CompareOperation* expr) {
Handle<Object> object = GetInfo(expr->id());
if (!object->IsCode()) return false;
Handle<Code> code = Handle<Code>::cast(object);
if (!code->is_compare_ic_stub()) return false;
CompareIC::State state = static_cast<CompareIC::State>(code->compare_state());
return state == CompareIC::SYMBOLS;
}
TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) {
Handle<Object> object = GetInfo(expr->id());
TypeInfo unknown = TypeInfo::Unknown();

View File

@ -264,6 +264,7 @@ class TypeFeedbackOracle BASE_EMBEDDED {
TypeInfo UnaryType(UnaryOperation* expr);
TypeInfo BinaryType(BinaryOperation* expr);
TypeInfo CompareType(CompareOperation* expr);
bool IsSymbolCompare(CompareOperation* expr);
TypeInfo SwitchType(CaseClause* clause);
TypeInfo IncrementType(CountOperation* expr);

View File

@ -1552,6 +1552,31 @@ void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) {
}
void LCodeGen::DoCmpSymbolEq(LCmpSymbolEq* instr) {
Register left = ToRegister(instr->InputAt(0));
Register right = ToRegister(instr->InputAt(1));
Register result = ToRegister(instr->result());
Label done;
__ cmpq(left, right);
__ LoadRoot(result, Heap::kFalseValueRootIndex);
__ j(not_equal, &done, Label::kNear);
__ LoadRoot(result, Heap::kTrueValueRootIndex);
__ bind(&done);
}
void LCodeGen::DoCmpSymbolEqAndBranch(LCmpSymbolEqAndBranch* instr) {
Register left = ToRegister(instr->InputAt(0));
Register right = ToRegister(instr->InputAt(1));
int false_block = chunk_->LookupDestination(instr->false_block_id());
int true_block = chunk_->LookupDestination(instr->true_block_id());
__ cmpq(left, right);
EmitBranch(true_block, false_block, equal);
}
void LCodeGen::DoIsNull(LIsNull* instr) {
Register reg = ToRegister(instr->InputAt(0));
Register result = ToRegister(instr->result());

View File

@ -1120,6 +1120,10 @@ LInstruction* LChunkBuilder::DoTest(HTest* instr) {
HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v);
return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()),
UseRegisterAtStart(compare->right()));
} else if (v->IsCompareSymbolEq()) {
HCompareSymbolEq* compare = HCompareSymbolEq::cast(v);
return new LCmpSymbolEqAndBranch(UseRegisterAtStart(compare->left()),
UseRegisterAtStart(compare->right()));
} else if (v->IsInstanceOf()) {
HInstanceOf* instance_of = HInstanceOf::cast(v);
LInstanceOfAndBranch* result =
@ -1527,6 +1531,15 @@ LInstruction* LChunkBuilder::DoCompareJSObjectEq(
}
LInstruction* LChunkBuilder::DoCompareSymbolEq(
HCompareSymbolEq* instr) {
LOperand* left = UseRegisterAtStart(instr->left());
LOperand* right = UseRegisterAtStart(instr->right());
LCmpSymbolEq* result = new LCmpSymbolEq(left, right);
return DefineAsRegister(result);
}
LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseRegisterAtStart(instr->value());

View File

@ -80,6 +80,8 @@ class LCodeGen;
V(CmpJSObjectEq) \
V(CmpJSObjectEqAndBranch) \
V(CmpMapAndBranch) \
V(CmpSymbolEq) \
V(CmpSymbolEqAndBranch) \
V(CmpT) \
V(CmpTAndBranch) \
V(ConstantD) \
@ -666,6 +668,28 @@ class LCmpJSObjectEqAndBranch: public LControlInstruction<2, 0> {
};
class LCmpSymbolEq: public LTemplateInstruction<1, 2, 0> {
public:
LCmpSymbolEq(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
}
DECLARE_CONCRETE_INSTRUCTION(CmpSymbolEq, "cmp-symbol-eq")
};
class LCmpSymbolEqAndBranch: public LControlInstruction<2, 0> {
public:
LCmpSymbolEqAndBranch(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
}
DECLARE_CONCRETE_INSTRUCTION(CmpSymbolEqAndBranch, "cmp-symbol-eq-and-branch")
};
class LIsNull: public LTemplateInstruction<1, 1, 0> {
public:
explicit LIsNull(LOperand* value) {