Reviewers: William Hesse,
Description:
Revert r6194: Clean up code for type feedback a bit.
This causes a big performance regression. I'll investigate.
Please review this at http://codereview.chromium.org/6172001/
SVN Base: http://v8.googlecode.com/svn/branches/bleeding_edge/
Affected files:
M src/ast.h
M src/ast.cc
M src/hydrogen.cc
M src/type-info.h
M src/type-info.cc
Index: src/ast.cc
===================================================================
--- src/ast.cc (revision 6216)
+++ src/ast.cc (working copy)
@@ -649,11 +649,19 @@
}
+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);
Index: src/ast.h
===================================================================
--- src/ast.h (revision 6216)
+++ src/ast.h (working copy)
@@ -1392,7 +1392,7 @@
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 @@
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 @@
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_;
Index: src/hydrogen.cc
===================================================================
--- src/hydrogen.cc (revision 6216)
+++ src/hydrogen.cc (working copy)
@@ -3366,6 +3366,7 @@
// 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 @@
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 @@
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
Index: src/type-info.cc
===================================================================
--- src/type-info.cc (revision 6216)
+++ src/type-info.cc (working copy)
@@ -132,7 +132,7 @@
}
-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::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 @@
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,17 +332,19 @@
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) {
- continue;
+ 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()));
Index: src/type-info.h
===================================================================
--- src/type-info.h (revision 6216)
+++ src/type-info.h (working copy)
@@ -230,6 +230,12 @@
class TypeFeedbackOracle BASE_EMBEDDED {
public:
+ enum Side {
+ LEFT,
+ RIGHT,
+ RESULT
+ };
+
explicit TypeFeedbackOracle(Handle<Code> code);
bool LoadIsMonomorphic(Property* expr);
@@ -247,8 +253,8 @@
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:
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev