Migrate BinaryOpICs and UnaryOpICs to new type rep

R=rossberg@chromium.org

Review URL: https://codereview.chromium.org/16957004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15172 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
jkummerow@chromium.org 2013-06-14 17:02:39 +00:00
parent 60c2218ae3
commit 47ba2b2dd8
7 changed files with 186 additions and 131 deletions

View File

@ -663,12 +663,13 @@ void ObjectLiteral::Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
void UnaryOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
type_ = oracle->UnaryType(this);
type_ = oracle->UnaryType(UnaryOperationFeedbackId());
}
void BinaryOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
oracle->BinaryType(this, &left_type_, &right_type_, &result_type_,
oracle->BinaryType(BinaryOperationFeedbackId(),
&left_type_, &right_type_, &result_type_,
&has_fixed_right_arg_, &fixed_right_arg_value_);
}

View File

@ -1837,7 +1837,7 @@ class UnaryOperation: public Expression {
TypeFeedbackId UnaryOperationFeedbackId() const { return reuse(id()); }
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
TypeInfo type() const { return type_; }
Handle<Type> type() const { return type_; }
protected:
UnaryOperation(Isolate* isolate,
@ -1858,7 +1858,7 @@ class UnaryOperation: public Expression {
Expression* expression_;
int pos_;
TypeInfo type_;
Handle<Type> type_;
// For unary not (Token::NOT), the AST ids where true and false will
// actually be materialized, respectively.
@ -1882,9 +1882,9 @@ class BinaryOperation: public Expression {
TypeFeedbackId BinaryOperationFeedbackId() const { return reuse(id()); }
void RecordTypeFeedback(TypeFeedbackOracle* oracle);
TypeInfo left_type() const { return left_type_; }
TypeInfo right_type() const { return right_type_; }
TypeInfo result_type() const { return result_type_; }
Handle<Type> left_type() const { return left_type_; }
Handle<Type> right_type() const { return right_type_; }
Handle<Type> result_type() const { return result_type_; }
bool has_fixed_right_arg() const { return has_fixed_right_arg_; }
int fixed_right_arg_value() const { return fixed_right_arg_value_; }
@ -1909,9 +1909,9 @@ class BinaryOperation: public Expression {
Expression* right_;
int pos_;
TypeInfo left_type_;
TypeInfo right_type_;
TypeInfo result_type_;
Handle<Type> left_type_;
Handle<Type> right_type_;
Handle<Type> result_type_;
bool has_fixed_right_arg_;
int fixed_right_arg_value_;

View File

@ -9106,11 +9106,11 @@ void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
HValue* context = environment()->LookupContext();
HInstruction* instr =
HMul::New(zone(), context, value, graph()->GetConstantMinus1());
TypeInfo info = expr->type();
Representation rep = ToRepresentation(info);
if (info.IsUninitialized()) {
Handle<Type> type = expr->type();
Representation rep = ToRepresentation(type);
if (type->Is(Type::None())) {
AddSoftDeoptimize();
info = TypeInfo::Unknown();
type = handle(Type::Any(), isolate());
}
if (instr->IsBinaryOperation()) {
HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep);
@ -9123,8 +9123,8 @@ void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
CHECK_ALIVE(VisitForValue(expr->expression()));
HValue* value = Pop();
TypeInfo info = expr->type();
if (info.IsUninitialized()) {
Handle<Type> info = expr->type();
if (info->Is(Type::None())) {
AddSoftDeoptimize();
}
HInstruction* instr = new(zone()) HBitNot(value);
@ -9486,24 +9486,26 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
HValue* left,
HValue* right) {
HValue* context = environment()->LookupContext();
TypeInfo left_info = expr->left_type();
TypeInfo right_info = expr->right_type();
TypeInfo result_info = expr->result_type();
Handle<Type> left_type = expr->left_type();
Handle<Type> right_type = expr->right_type();
Handle<Type> result_type = expr->result_type();
bool has_fixed_right_arg = expr->has_fixed_right_arg();
int fixed_right_arg_value = expr->fixed_right_arg_value();
Representation left_rep = ToRepresentation(left_info);
Representation right_rep = ToRepresentation(right_info);
Representation result_rep = ToRepresentation(result_info);
if (left_info.IsUninitialized()) {
// Can't have initialized one but not the other.
ASSERT(right_info.IsUninitialized());
Representation left_rep = ToRepresentation(left_type);
Representation right_rep = ToRepresentation(right_type);
Representation result_rep = ToRepresentation(result_type);
if (left_type->Is(Type::None())) {
AddSoftDeoptimize();
left_info = right_info = TypeInfo::Unknown();
left_type = handle(Type::Any(), isolate());
}
if (right_type->Is(Type::None())) {
AddSoftDeoptimize();
right_type = handle(Type::Any(), isolate());
}
HInstruction* instr = NULL;
switch (expr->op()) {
case Token::ADD:
if (left_info.IsString() && right_info.IsString()) {
if (left_type->Is(Type::String()) && right_type->Is(Type::String())) {
BuildCheckNonSmi(left);
AddInstruction(HCheckInstanceType::NewIsString(left, zone()));
BuildCheckNonSmi(right);
@ -9536,7 +9538,8 @@ HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation(
break;
case Token::BIT_OR: {
HValue* operand, *shift_amount;
if (left_info.IsInteger32() && right_info.IsInteger32() &&
if (left_type->Is(Type::Integer32()) &&
right_type->Is(Type::Integer32()) &&
MatchRotateRight(left, right, &operand, &shift_amount)) {
instr = new(zone()) HRor(context, operand, shift_amount);
} else {

136
src/ic.cc
View File

@ -2420,17 +2420,34 @@ const char* UnaryOpIC::GetName(TypeInfo type_info) {
UnaryOpIC::State UnaryOpIC::ToState(TypeInfo type_info) {
switch (type_info) {
case UNINITIALIZED:
return ::v8::internal::UNINITIALIZED;
return v8::internal::UNINITIALIZED;
case SMI:
case NUMBER:
return MONOMORPHIC;
case GENERIC:
return ::v8::internal::GENERIC;
return v8::internal::GENERIC;
}
UNREACHABLE();
return ::v8::internal::UNINITIALIZED;
return v8::internal::UNINITIALIZED;
}
Handle<Type> UnaryOpIC::TypeInfoToType(TypeInfo type_info, Isolate* isolate) {
switch (type_info) {
case UNINITIALIZED:
return handle(Type::None(), isolate);
case SMI:
return handle(Type::Integer31(), isolate);
case NUMBER:
return handle(Type::Number(), isolate);
case GENERIC:
return handle(Type::Any(), isolate);
}
UNREACHABLE();
return handle(Type::Any(), isolate);
}
UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle<Object> operand) {
v8::internal::TypeInfo operand_type =
v8::internal::TypeInfo::FromValue(operand);
@ -2501,6 +2518,46 @@ BinaryOpIC::State BinaryOpIC::ToState(TypeInfo type_info) {
}
Handle<Type> BinaryOpIC::TypeInfoToType(BinaryOpIC::TypeInfo binary_type,
Isolate* isolate) {
switch (binary_type) {
case UNINITIALIZED:
return handle(Type::None(), isolate);
case SMI:
return handle(Type::Integer31(), isolate);
case INT32:
return handle(Type::Integer32(), isolate);
case NUMBER:
return handle(Type::Number(), isolate);
case ODDBALL:
return handle(Type::Optional(
handle(Type::Union(
handle(Type::Number(), isolate),
handle(Type::String(), isolate)), isolate)), isolate);
case STRING:
return handle(Type::String(), isolate);
case GENERIC:
return handle(Type::Any(), isolate);
}
UNREACHABLE();
return handle(Type::Any(), isolate);
}
void BinaryOpIC::StubInfoToType(int minor_key,
Handle<Type>* left,
Handle<Type>* right,
Handle<Type>* result,
Isolate* isolate) {
TypeInfo left_typeinfo, right_typeinfo, result_typeinfo;
BinaryOpStub::decode_types_from_minor_key(
minor_key, &left_typeinfo, &right_typeinfo, &result_typeinfo);
*left = TypeInfoToType(left_typeinfo, isolate);
*right = TypeInfoToType(right_typeinfo, isolate);
*result = TypeInfoToType(result_typeinfo, isolate);
}
RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) {
ASSERT(args.length() == 4);
@ -2814,45 +2871,60 @@ Handle<Type> CompareIC::StateToType(
}
static CompareIC::State InputState(CompareIC::State old_state,
Handle<Object> value) {
void CompareIC::StubInfoToType(int stub_minor_key,
Handle<Type>* left_type,
Handle<Type>* right_type,
Handle<Type>* overall_type,
Handle<Map> map,
Isolate* isolate) {
State left_state, right_state, handler_state;
ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state,
&handler_state, NULL);
*left_type = StateToType(isolate, left_state);
*right_type = StateToType(isolate, right_state);
*overall_type = StateToType(isolate, handler_state, map);
}
CompareIC::State CompareIC::NewInputState(State old_state,
Handle<Object> value) {
switch (old_state) {
case CompareIC::UNINITIALIZED:
if (value->IsSmi()) return CompareIC::SMI;
if (value->IsHeapNumber()) return CompareIC::NUMBER;
if (value->IsInternalizedString()) return CompareIC::INTERNALIZED_STRING;
if (value->IsString()) return CompareIC::STRING;
if (value->IsSymbol()) return CompareIC::UNIQUE_NAME;
if (value->IsJSObject()) return CompareIC::OBJECT;
case UNINITIALIZED:
if (value->IsSmi()) return SMI;
if (value->IsHeapNumber()) return NUMBER;
if (value->IsInternalizedString()) return INTERNALIZED_STRING;
if (value->IsString()) return STRING;
if (value->IsSymbol()) return UNIQUE_NAME;
if (value->IsJSObject()) return OBJECT;
break;
case CompareIC::SMI:
if (value->IsSmi()) return CompareIC::SMI;
if (value->IsHeapNumber()) return CompareIC::NUMBER;
case SMI:
if (value->IsSmi()) return SMI;
if (value->IsHeapNumber()) return NUMBER;
break;
case CompareIC::NUMBER:
if (value->IsNumber()) return CompareIC::NUMBER;
case NUMBER:
if (value->IsNumber()) return NUMBER;
break;
case CompareIC::INTERNALIZED_STRING:
if (value->IsInternalizedString()) return CompareIC::INTERNALIZED_STRING;
if (value->IsString()) return CompareIC::STRING;
if (value->IsSymbol()) return CompareIC::UNIQUE_NAME;
case INTERNALIZED_STRING:
if (value->IsInternalizedString()) return INTERNALIZED_STRING;
if (value->IsString()) return STRING;
if (value->IsSymbol()) return UNIQUE_NAME;
break;
case CompareIC::STRING:
if (value->IsString()) return CompareIC::STRING;
case STRING:
if (value->IsString()) return STRING;
break;
case CompareIC::UNIQUE_NAME:
if (value->IsUniqueName()) return CompareIC::UNIQUE_NAME;
case UNIQUE_NAME:
if (value->IsUniqueName()) return UNIQUE_NAME;
break;
case CompareIC::OBJECT:
if (value->IsJSObject()) return CompareIC::OBJECT;
case OBJECT:
if (value->IsJSObject()) return OBJECT;
break;
case CompareIC::GENERIC:
case GENERIC:
break;
case CompareIC::KNOWN_OBJECT:
case KNOWN_OBJECT:
UNREACHABLE();
break;
}
return CompareIC::GENERIC;
return GENERIC;
}
@ -2925,8 +2997,8 @@ void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
State previous_left, previous_right, previous_state;
ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left,
&previous_right, &previous_state, NULL);
State new_left = InputState(previous_left, x);
State new_right = InputState(previous_right, y);
State new_left = NewInputState(previous_left, x);
State new_right = NewInputState(previous_right, y);
State state = TargetState(previous_state, previous_left, previous_right,
HasInlinedSmiCode(address()), x, y);
ICCompareStub stub(op_, new_left, new_right, state);

View File

@ -690,6 +690,8 @@ class UnaryOpIC: public IC {
GENERIC
};
static Handle<Type> TypeInfoToType(TypeInfo info, Isolate* isolate);
explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
void patch(Code* code);
@ -717,6 +719,12 @@ class BinaryOpIC: public IC {
GENERIC
};
static void StubInfoToType(int minor_key,
Handle<Type>* left,
Handle<Type>* right,
Handle<Type>* result,
Isolate* isolate);
explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
void patch(Code* code);
@ -724,6 +732,9 @@ class BinaryOpIC: public IC {
static const char* GetName(TypeInfo type_info);
static State ToState(TypeInfo type_info);
private:
static Handle<Type> TypeInfoToType(TypeInfo binary_type, Isolate* isolate);
};
@ -747,8 +758,18 @@ class CompareIC: public IC {
GENERIC
};
static Handle<Type> StateToType(
Isolate* isolate, State state, Handle<Map> map = Handle<Map>());
static State NewInputState(State old_state, Handle<Object> value);
static Handle<Type> StateToType(Isolate* isolate,
State state,
Handle<Map> map = Handle<Map>());
static void StubInfoToType(int stub_minor_key,
Handle<Type>* left_type,
Handle<Type>* right_type,
Handle<Type>* overall_type,
Handle<Map> map,
Isolate* isolate);
CompareIC(Isolate* isolate, Token::Value op)
: IC(EXTRA_CALL_FRAME, isolate), op_(op) { }

View File

@ -363,12 +363,8 @@ void TypeFeedbackOracle::CompareTypes(TypeFeedbackId id,
if (code->is_compare_ic_stub()) {
int stub_minor_key = code->stub_info();
CompareIC::State left_state, right_state, handler_state;
ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state,
&handler_state, NULL);
*left_type = CompareIC::StateToType(isolate_, left_state);
*right_type = CompareIC::StateToType(isolate_, right_state);
*overall_type = CompareIC::StateToType(isolate_, handler_state, map);
CompareIC::StubInfoToType(
stub_minor_key, left_type, right_type, overall_type, map, isolate());
} else if (code->is_compare_nil_ic_stub()) {
CompareNilICStub::State state(code->compare_nil_state());
*compare_nil_type = CompareNilICStub::StateToType(isolate_, state, map);
@ -376,70 +372,34 @@ void TypeFeedbackOracle::CompareTypes(TypeFeedbackId id,
}
TypeInfo TypeFeedbackOracle::UnaryType(UnaryOperation* expr) {
Handle<Object> object = GetInfo(expr->UnaryOperationFeedbackId());
TypeInfo unknown = TypeInfo::Unknown();
if (!object->IsCode()) return unknown;
Handle<Type> TypeFeedbackOracle::UnaryType(TypeFeedbackId id) {
Handle<Object> object = GetInfo(id);
if (!object->IsCode()) return handle(Type::Any(), isolate());
Handle<Code> code = Handle<Code>::cast(object);
ASSERT(code->is_unary_op_stub());
UnaryOpIC::TypeInfo type = static_cast<UnaryOpIC::TypeInfo>(
code->unary_op_type());
switch (type) {
case UnaryOpIC::SMI:
return TypeInfo::Smi();
case UnaryOpIC::NUMBER:
return TypeInfo::Double();
default:
return unknown;
}
return UnaryOpIC::TypeInfoToType(
static_cast<UnaryOpIC::TypeInfo>(code->unary_op_type()), isolate());
}
static TypeInfo TypeFromBinaryOpType(BinaryOpIC::TypeInfo binary_type) {
switch (binary_type) {
// Uninitialized means never executed.
case BinaryOpIC::UNINITIALIZED: return TypeInfo::Uninitialized();
case BinaryOpIC::SMI: return TypeInfo::Smi();
case BinaryOpIC::INT32: return TypeInfo::Integer32();
case BinaryOpIC::NUMBER: return TypeInfo::Double();
case BinaryOpIC::ODDBALL: return TypeInfo::Unknown();
case BinaryOpIC::STRING: return TypeInfo::String();
case BinaryOpIC::GENERIC: return TypeInfo::Unknown();
}
UNREACHABLE();
return TypeInfo::Unknown();
}
void TypeFeedbackOracle::BinaryType(BinaryOperation* expr,
TypeInfo* left,
TypeInfo* right,
TypeInfo* result,
void TypeFeedbackOracle::BinaryType(TypeFeedbackId id,
Handle<Type>* left,
Handle<Type>* right,
Handle<Type>* result,
bool* has_fixed_right_arg,
int* fixed_right_arg_value) {
Handle<Object> object = GetInfo(expr->BinaryOperationFeedbackId());
TypeInfo unknown = TypeInfo::Unknown();
if (!object->IsCode()) {
*left = *right = *result = unknown;
return;
}
Handle<Object> object = GetInfo(id);
*left = *right = *result = handle(Type::Any(), isolate_);
if (!object->IsCode()) return;
Handle<Code> code = Handle<Code>::cast(object);
if (code->is_binary_op_stub()) {
int minor_key = code->stub_info();
BinaryOpIC::TypeInfo left_type, right_type, result_type;
BinaryOpStub::decode_types_from_minor_key(
minor_key, &left_type, &right_type, &result_type);
*left = TypeFromBinaryOpType(left_type);
*right = TypeFromBinaryOpType(right_type);
*result = TypeFromBinaryOpType(result_type);
*has_fixed_right_arg =
BinaryOpStub::decode_has_fixed_right_arg_from_minor_key(minor_key);
*fixed_right_arg_value =
BinaryOpStub::decode_fixed_right_arg_value_from_minor_key(minor_key);
return;
}
// Not a binary op stub.
*left = *right = *result = unknown;
if (!code->is_binary_op_stub()) return;
int minor_key = code->stub_info();
BinaryOpIC::StubInfoToType(minor_key, left, right, result, isolate());
*has_fixed_right_arg =
BinaryOpStub::decode_has_fixed_right_arg_from_minor_key(minor_key);
*fixed_right_arg_value =
BinaryOpStub::decode_fixed_right_arg_value_from_minor_key(minor_key);
}

View File

@ -220,7 +220,6 @@ enum StringStubFeedback {
// Forward declarations.
// TODO(rossberg): these should all go away eventually.
class Assignment;
class BinaryOperation;
class Call;
class CallNew;
class CaseClause;
@ -231,7 +230,6 @@ class ForInStatement;
class ICStub;
class Property;
class SmallMapList;
class UnaryOperation;
class ObjectLiteral;
class ObjectLiteralProperty;
@ -296,11 +294,11 @@ class TypeFeedbackOracle: public ZoneObject {
byte ToBooleanTypes(TypeFeedbackId id);
// Get type information for arithmetic operations and compares.
TypeInfo UnaryType(UnaryOperation* expr);
void BinaryType(BinaryOperation* expr,
TypeInfo* left,
TypeInfo* right,
TypeInfo* result,
Handle<Type> UnaryType(TypeFeedbackId id);
void BinaryType(TypeFeedbackId id,
Handle<Type>* left,
Handle<Type>* right,
Handle<Type>* result,
bool* has_fixed_right_arg,
int* fixed_right_arg_value);