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
This commit is contained in:
fschneider@chromium.org 2011-01-07 10:36:27 +00:00
parent 12b34fa927
commit bfecc95694
5 changed files with 61 additions and 23 deletions

View File

@ -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) {
TypeInfo info = oracle->CompareType(this);
if (info.IsSmi()) {
TypeInfo left = oracle->CompareType(this, TypeFeedbackOracle::LEFT);
TypeInfo right = oracle->CompareType(this, TypeFeedbackOracle::RIGHT);
if (left.IsSmi() && right.IsSmi()) {
compare_type_ = SMI_ONLY;
} else if (info.IsNonPrimitive()) {
} else if (left.IsNonPrimitive() && right.IsNonPrimitive()) {
compare_type_ = OBJECT_ONLY;
} else {
ASSERT(compare_type_ == NONE);

View File

@ -1392,7 +1392,7 @@ class BinaryOperation: public Expression {
Expression* left,
Expression* right,
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));
right_id_ = (op == Token::AND || op == Token::OR)
? static_cast<int>(GetNextId())
@ -1413,6 +1413,10 @@ class BinaryOperation: public Expression {
Expression* right() const { return right_; }
int position() const { return pos_; }
// Type feedback information.
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
bool IsSmiOnly() const { return is_smi_only_; }
// Bailout support.
int RightId() const { return right_id_; }
@ -1421,6 +1425,7 @@ class BinaryOperation: public Expression {
Expression* left_;
Expression* right_;
int pos_;
bool is_smi_only_;
// The short-circuit logical operations have an AST ID for their
// right-hand subexpression.
int right_id_;

View File

@ -3366,6 +3366,7 @@ void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
// We have a second position recorded in the FullCodeGenerator to have
// type feedback for the binary operation.
BinaryOperation* operation = expr->binary_operation();
operation->RecordTypeFeedback(oracle());
if (var != NULL) {
if (!var->is_global() && !var->IsStackAllocated()) {
@ -4730,7 +4731,7 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
default:
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
// for a smi operation. If one of the operands is a constant string
// do not generate code assuming it is a smi operation.
@ -4875,7 +4876,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
HValue* left = Pop();
Token::Value op = expr->op();
TypeInfo info = oracle()->CompareType(expr);
TypeInfo info = oracle()->CompareType(expr, TypeFeedbackOracle::RESULT);
HInstruction* instr = NULL;
if (op == Token::INSTANCEOF) {
// Check to see if the rhs of the instanceof is a global function not

View File

@ -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());
TypeInfo unknown = TypeInfo::Unknown();
if (!object->IsCode()) return unknown;
@ -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());
TypeInfo unknown = TypeInfo::Unknown();
if (!object->IsCode()) return unknown;
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>(
code->type_recording_binary_op_type());
TRBinaryOpIC::TypeInfo result_type = static_cast<TRBinaryOpIC::TypeInfo>(
@ -276,7 +291,8 @@ void TypeFeedbackOracle::PopulateMap(Handle<Code> code) {
int position = source_positions[i];
InlineCacheState state = target->ic_state();
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) {
// TODO(kasperl): Avoid having multiple ICs with the same
// position by making sure that we have position information
@ -316,18 +332,20 @@ void TypeFeedbackOracle::CollectPositions(Code* code,
if (target->is_inline_cache_stub()) {
InlineCacheState state = target->ic_state();
Code::Kind kind = target->kind();
if (kind == Code::TYPE_RECORDING_BINARY_OP_IC &&
target->type_recording_binary_op_type() == TRBinaryOpIC::GENERIC) {
continue;
} else if (kind == Code::COMPARE_IC &&
target->compare_state() == CompareIC::GENERIC) {
continue;
} else if (kind == Code::CALL_IC && state == MONOMORPHIC &&
target->check_type() != RECEIVER_MAP_CHECK) {
continue;
} else if (state != MONOMORPHIC && state != MEGAMORPHIC) {
if (kind == Code::BINARY_OP_IC) {
if (target->binary_op_type() == BinaryOpIC::GENERIC) continue;
} else if (kind == Code::TYPE_RECORDING_BINARY_OP_IC) {
if (target->type_recording_binary_op_type() ==
TRBinaryOpIC::GENERIC) {
continue;
}
} else if (kind == Code::COMPARE_IC) {
if (target->compare_state() == CompareIC::GENERIC) continue;
} else {
if (kind == Code::CALL_IC && state == MONOMORPHIC &&
target->check_type() != RECEIVER_MAP_CHECK) continue;
if (state != MONOMORPHIC && state != MEGAMORPHIC) continue;
}
code_positions->Add(
static_cast<int>(info->pc() - code->instruction_start()));
source_positions->Add(position);

View File

@ -230,6 +230,12 @@ class CaseClause;
class TypeFeedbackOracle BASE_EMBEDDED {
public:
enum Side {
LEFT,
RIGHT,
RESULT
};
explicit TypeFeedbackOracle(Handle<Code> code);
bool LoadIsMonomorphic(Property* expr);
@ -247,8 +253,8 @@ class TypeFeedbackOracle BASE_EMBEDDED {
bool LoadIsBuiltin(Property* expr, Builtins::Name id);
// Get type information for arithmetic operations and compares.
TypeInfo BinaryType(BinaryOperation* expr);
TypeInfo CompareType(CompareOperation* expr);
TypeInfo BinaryType(BinaryOperation* expr, Side side);
TypeInfo CompareType(CompareOperation* expr, Side side);
TypeInfo SwitchType(CaseClause* clause);
private: