Revert r6194: Clean up code for type feedback a bit.

This causes a big performance regression. I'll investigate.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6217 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 12b34fa9
...@@ -649,11 +649,19 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle) { ...@@ -649,11 +649,19 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
} }
void BinaryOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
TypeInfo left = oracle->BinaryType(this, TypeFeedbackOracle::LEFT);
TypeInfo right = oracle->BinaryType(this, TypeFeedbackOracle::RIGHT);
is_smi_only_ = left.IsSmi() && right.IsSmi();
}
void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) { void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
TypeInfo info = oracle->CompareType(this); TypeInfo left = oracle->CompareType(this, TypeFeedbackOracle::LEFT);
if (info.IsSmi()) { TypeInfo right = oracle->CompareType(this, TypeFeedbackOracle::RIGHT);
if (left.IsSmi() && right.IsSmi()) {
compare_type_ = SMI_ONLY; compare_type_ = SMI_ONLY;
} else if (info.IsNonPrimitive()) { } else if (left.IsNonPrimitive() && right.IsNonPrimitive()) {
compare_type_ = OBJECT_ONLY; compare_type_ = OBJECT_ONLY;
} else { } else {
ASSERT(compare_type_ == NONE); ASSERT(compare_type_ == NONE);
......
...@@ -1392,7 +1392,7 @@ class BinaryOperation: public Expression { ...@@ -1392,7 +1392,7 @@ class BinaryOperation: public Expression {
Expression* left, Expression* left,
Expression* right, Expression* right,
int pos) int pos)
: op_(op), left_(left), right_(right), pos_(pos) { : op_(op), left_(left), right_(right), pos_(pos), is_smi_only_(false) {
ASSERT(Token::IsBinaryOp(op)); ASSERT(Token::IsBinaryOp(op));
right_id_ = (op == Token::AND || op == Token::OR) right_id_ = (op == Token::AND || op == Token::OR)
? static_cast<int>(GetNextId()) ? static_cast<int>(GetNextId())
...@@ -1413,6 +1413,10 @@ class BinaryOperation: public Expression { ...@@ -1413,6 +1413,10 @@ class BinaryOperation: public Expression {
Expression* right() const { return right_; } Expression* right() const { return right_; }
int position() const { return pos_; } int position() const { return pos_; }
// Type feedback information.
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
bool IsSmiOnly() const { return is_smi_only_; }
// Bailout support. // Bailout support.
int RightId() const { return right_id_; } int RightId() const { return right_id_; }
...@@ -1421,6 +1425,7 @@ class BinaryOperation: public Expression { ...@@ -1421,6 +1425,7 @@ class BinaryOperation: public Expression {
Expression* left_; Expression* left_;
Expression* right_; Expression* right_;
int pos_; int pos_;
bool is_smi_only_;
// The short-circuit logical operations have an AST ID for their // The short-circuit logical operations have an AST ID for their
// right-hand subexpression. // right-hand subexpression.
int right_id_; int right_id_;
......
...@@ -3366,6 +3366,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { ...@@ -3366,6 +3366,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
// We have a second position recorded in the FullCodeGenerator to have // We have a second position recorded in the FullCodeGenerator to have
// type feedback for the binary operation. // type feedback for the binary operation.
BinaryOperation* operation = expr->binary_operation(); BinaryOperation* operation = expr->binary_operation();
operation->RecordTypeFeedback(oracle());
if (var != NULL) { if (var != NULL) {
if (!var->is_global() && !var->IsStackAllocated()) { if (!var->is_global() && !var->IsStackAllocated()) {
...@@ -4730,7 +4731,7 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, ...@@ -4730,7 +4731,7 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
default: default:
UNREACHABLE(); UNREACHABLE();
} }
TypeInfo info = oracle()->BinaryType(expr); TypeInfo info = oracle()->BinaryType(expr, TypeFeedbackOracle::RESULT);
// If we hit an uninitialized binary op stub we will get type info // If we hit an uninitialized binary op stub we will get type info
// for a smi operation. If one of the operands is a constant string // for a smi operation. If one of the operands is a constant string
// do not generate code assuming it is a smi operation. // do not generate code assuming it is a smi operation.
...@@ -4875,7 +4876,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { ...@@ -4875,7 +4876,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
HValue* left = Pop(); HValue* left = Pop();
Token::Value op = expr->op(); Token::Value op = expr->op();
TypeInfo info = oracle()->CompareType(expr); TypeInfo info = oracle()->CompareType(expr, TypeFeedbackOracle::RESULT);
HInstruction* instr = NULL; HInstruction* instr = NULL;
if (op == Token::INSTANCEOF) { if (op == Token::INSTANCEOF) {
// Check to see if the rhs of the instanceof is a global function not // Check to see if the rhs of the instanceof is a global function not
......
...@@ -132,7 +132,7 @@ bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) { ...@@ -132,7 +132,7 @@ bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
} }
TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr, Side side) {
Handle<Object> object = GetElement(map_, expr->position()); Handle<Object> object = GetElement(map_, expr->position());
TypeInfo unknown = TypeInfo::Unknown(); TypeInfo unknown = TypeInfo::Unknown();
if (!object->IsCode()) return unknown; if (!object->IsCode()) return unknown;
...@@ -159,12 +159,27 @@ TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) { ...@@ -159,12 +159,27 @@ TypeInfo TypeFeedbackOracle::CompareType(CompareOperation* expr) {
} }
TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr) { TypeInfo TypeFeedbackOracle::BinaryType(BinaryOperation* expr, Side side) {
Handle<Object> object = GetElement(map_, expr->position()); Handle<Object> object = GetElement(map_, expr->position());
TypeInfo unknown = TypeInfo::Unknown(); TypeInfo unknown = TypeInfo::Unknown();
if (!object->IsCode()) return unknown; if (!object->IsCode()) return unknown;
Handle<Code> code = Handle<Code>::cast(object); Handle<Code> code = Handle<Code>::cast(object);
if (code->is_type_recording_binary_op_stub()) { if (code->is_binary_op_stub()) {
BinaryOpIC::TypeInfo type = static_cast<BinaryOpIC::TypeInfo>(
code->binary_op_type());
switch (type) {
case BinaryOpIC::UNINIT_OR_SMI:
return TypeInfo::Smi();
case BinaryOpIC::DEFAULT:
return (expr->op() == Token::DIV || expr->op() == Token::MUL)
? TypeInfo::Double()
: TypeInfo::Integer32();
case BinaryOpIC::HEAP_NUMBERS:
return TypeInfo::Double();
default:
return unknown;
}
} else if (code->is_type_recording_binary_op_stub()) {
TRBinaryOpIC::TypeInfo type = static_cast<TRBinaryOpIC::TypeInfo>( TRBinaryOpIC::TypeInfo type = static_cast<TRBinaryOpIC::TypeInfo>(
code->type_recording_binary_op_type()); code->type_recording_binary_op_type());
TRBinaryOpIC::TypeInfo result_type = static_cast<TRBinaryOpIC::TypeInfo>( TRBinaryOpIC::TypeInfo result_type = static_cast<TRBinaryOpIC::TypeInfo>(
...@@ -276,7 +291,8 @@ void TypeFeedbackOracle::PopulateMap(Handle<Code> code) { ...@@ -276,7 +291,8 @@ void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
int position = source_positions[i]; int position = source_positions[i];
InlineCacheState state = target->ic_state(); InlineCacheState state = target->ic_state();
Code::Kind kind = target->kind(); Code::Kind kind = target->kind();
if (kind == Code::TYPE_RECORDING_BINARY_OP_IC || if (kind == Code::BINARY_OP_IC ||
kind == Code::TYPE_RECORDING_BINARY_OP_IC ||
kind == Code::COMPARE_IC) { kind == Code::COMPARE_IC) {
// TODO(kasperl): Avoid having multiple ICs with the same // TODO(kasperl): Avoid having multiple ICs with the same
// position by making sure that we have position information // position by making sure that we have position information
...@@ -316,17 +332,19 @@ void TypeFeedbackOracle::CollectPositions(Code* code, ...@@ -316,17 +332,19 @@ void TypeFeedbackOracle::CollectPositions(Code* code,
if (target->is_inline_cache_stub()) { if (target->is_inline_cache_stub()) {
InlineCacheState state = target->ic_state(); InlineCacheState state = target->ic_state();
Code::Kind kind = target->kind(); Code::Kind kind = target->kind();
if (kind == Code::TYPE_RECORDING_BINARY_OP_IC && if (kind == Code::BINARY_OP_IC) {
target->type_recording_binary_op_type() == TRBinaryOpIC::GENERIC) { if (target->binary_op_type() == BinaryOpIC::GENERIC) continue;
continue; } else if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) {
} else if (kind == Code::COMPARE_IC && if (target->type_recording_binary_op_type() ==
target->compare_state() == CompareIC::GENERIC) { TRBinaryOpIC::GENERIC) {
continue; continue;
} else if (kind == Code::CALL_IC && state == MONOMORPHIC && }
target->check_type() != RECEIVER_MAP_CHECK) { } else if (kind == Code::COMPARE_IC) {
continue; if (target->compare_state() == CompareIC::GENERIC) continue;
} else if (state != MONOMORPHIC && state != MEGAMORPHIC) { } else {
continue; if (kind == Code::CALL_IC && state == MONOMORPHIC &&
target->check_type() != RECEIVER_MAP_CHECK) continue;
if (state != MONOMORPHIC && state != MEGAMORPHIC) continue;
} }
code_positions->Add( code_positions->Add(
static_cast<int>(info->pc() - code->instruction_start())); static_cast<int>(info->pc() - code->instruction_start()));
......
...@@ -230,6 +230,12 @@ class CaseClause; ...@@ -230,6 +230,12 @@ class CaseClause;
class TypeFeedbackOracle BASE_EMBEDDED { class TypeFeedbackOracle BASE_EMBEDDED {
public: public:
enum Side {
LEFT,
RIGHT,
RESULT
};
explicit TypeFeedbackOracle(Handle<Code> code); explicit TypeFeedbackOracle(Handle<Code> code);
bool LoadIsMonomorphic(Property* expr); bool LoadIsMonomorphic(Property* expr);
...@@ -247,8 +253,8 @@ class TypeFeedbackOracle BASE_EMBEDDED { ...@@ -247,8 +253,8 @@ class TypeFeedbackOracle BASE_EMBEDDED {
bool LoadIsBuiltin(Property* expr, Builtins::Name id); bool LoadIsBuiltin(Property* expr, Builtins::Name id);
// Get type information for arithmetic operations and compares. // Get type information for arithmetic operations and compares.
TypeInfo BinaryType(BinaryOperation* expr); TypeInfo BinaryType(BinaryOperation* expr, Side side);
TypeInfo CompareType(CompareOperation* expr); TypeInfo CompareType(CompareOperation* expr, Side side);
TypeInfo SwitchType(CaseClause* clause); TypeInfo SwitchType(CaseClause* clause);
private: private:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment