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_);
}
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,
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.
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_; }
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_;
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);
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);
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_type = handle(Type::Any(), isolate());
+ }
+ if (right_type->Is(Type::None())) {
AddSoftDeoptimize();
- left_info = right_info = TypeInfo::Unknown();
+ 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);
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 {
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);
}
+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);
}
-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;
}
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);
GENERIC
};
+ static Handle<Type> TypeInfoToType(TypeInfo info, Isolate* isolate);
+
explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
void patch(Code* code);
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);
static const char* GetName(TypeInfo type_info);
static State ToState(TypeInfo type_info);
+
+ private:
+ static Handle<Type> TypeInfoToType(TypeInfo binary_type, Isolate* isolate);
};
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) { }
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);
}
-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);
}
// Forward declarations.
// TODO(rossberg): these should all go away eventually.
class Assignment;
-class BinaryOperation;
class Call;
class CallNew;
class CaseClause;
class ICStub;
class Property;
class SmallMapList;
-class UnaryOperation;
class ObjectLiteral;
class ObjectLiteralProperty;
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);