diff --git a/src/ast.cc b/src/ast.cc index a94feb88e5..0ebbd35be8 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -503,19 +503,7 @@ void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle, void CaseClause::RecordTypeFeedback(TypeFeedbackOracle* oracle) { - TypeInfo info = oracle->SwitchType(this); - if (info.IsUninitialized()) info = TypeInfo::Unknown(); - if (info.IsSmi()) { - compare_type_ = SMI_ONLY; - } else if (info.IsInternalizedString()) { - compare_type_ = NAME_ONLY; - } else if (info.IsNonInternalizedString()) { - compare_type_ = STRING_ONLY; - } else if (info.IsNonPrimitive()) { - compare_type_ = OBJECT_ONLY; - } else { - ASSERT(compare_type_ == NONE); - } + compare_type_ = oracle->ClauseType(CompareId()); } @@ -685,17 +673,11 @@ void BinaryOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) { } +// TODO(rossberg): this function (and all other RecordTypeFeedback functions) +// should disappear once we use the common type field in the AST consistently. void CompareOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) { - oracle->CompareType(this, &left_type_, &right_type_, &overall_type_); - if (!overall_type_.IsUninitialized() && overall_type_.IsNonPrimitive() && - (op_ == Token::EQ || op_ == Token::EQ_STRICT)) { - map_ = oracle->GetCompareMap(this); - } else { - // May be a compare to nil. - map_ = oracle->CompareNilMonomorphicReceiverType(this); - if (op_ != Token::EQ_STRICT) - compare_nil_types_ = oracle->CompareNilTypes(this); - } + oracle->CompareTypes(CompareOperationFeedbackId(), + &left_type_, &right_type_, &overall_type_, &compare_nil_type_); } @@ -1072,7 +1054,7 @@ CaseClause::CaseClause(Isolate* isolate, : label_(label), statements_(statements), position_(pos), - compare_type_(NONE), + compare_type_(Type::None(), isolate), compare_id_(AstNode::GetNextId(isolate)), entry_id_(AstNode::GetNextId(isolate)) { } diff --git a/src/ast.h b/src/ast.h index d96fcfd199..b7ada60665 100644 --- a/src/ast.h +++ b/src/ast.h @@ -358,6 +358,7 @@ class Expression: public AstNode { // Expression type Handle type() { return type_; } + void set_type(Handle type) { type_ = type; } // Type feedback information for assignments and properties. virtual bool IsMonomorphic() { @@ -388,7 +389,7 @@ class Expression: public AstNode { protected: explicit Expression(Isolate* isolate) - : type_(Type::Any(), isolate), + : type_(Type::None(), isolate), id_(GetNextId(isolate)), test_id_(GetNextId(isolate)) {} @@ -1106,24 +1107,15 @@ class CaseClause: public ZoneObject { // Type feedback information. TypeFeedbackId CompareId() { return compare_id_; } void RecordTypeFeedback(TypeFeedbackOracle* oracle); - bool IsSmiCompare() { return compare_type_ == SMI_ONLY; } - bool IsNameCompare() { return compare_type_ == NAME_ONLY; } - bool IsStringCompare() { return compare_type_ == STRING_ONLY; } - bool IsObjectCompare() { return compare_type_ == OBJECT_ONLY; } + Handle compare_type() { return compare_type_; } private: Expression* label_; Label body_target_; ZoneList* statements_; int position_; - enum CompareTypeFeedback { - NONE, - SMI_ONLY, - NAME_ONLY, - STRING_ONLY, - OBJECT_ONLY - }; - CompareTypeFeedback compare_type_; + Handle compare_type_; + const TypeFeedbackId compare_id_; const BailoutId entry_id_; }; @@ -2003,11 +1995,10 @@ class CompareOperation: public Expression { // Type feedback information. TypeFeedbackId CompareOperationFeedbackId() const { return reuse(id()); } void RecordTypeFeedback(TypeFeedbackOracle* oracle); - TypeInfo left_type() const { return left_type_; } - TypeInfo right_type() const { return right_type_; } - TypeInfo overall_type() const { return overall_type_; } - byte compare_nil_types() const { return compare_nil_types_; } - Handle map() const { return map_; } + Handle left_type() const { return left_type_; } + Handle right_type() const { return right_type_; } + Handle overall_type() const { return overall_type_; } + Handle compare_nil_type() const { return compare_nil_type_; } // Match special cases. bool IsLiteralCompareTypeof(Expression** expr, Handle* check); @@ -2034,11 +2025,10 @@ class CompareOperation: public Expression { Expression* right_; int pos_; - TypeInfo left_type_; - TypeInfo right_type_; - TypeInfo overall_type_; - byte compare_nil_types_; - Handle map_; + Handle left_type_; + Handle right_type_; + Handle overall_type_; + Handle compare_nil_type_; }; diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index 99c4db55b7..e1e25fb3cd 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -733,12 +733,13 @@ Handle InternalArrayNArgumentsConstructorStub::GenerateCode() { template <> HValue* CodeStubGraphBuilder::BuildCodeInitializedStub() { + Isolate* isolate = graph()->isolate(); CompareNilICStub* stub = casted_stub(); HIfContinuation continuation; - Handle sentinel_map(graph()->isolate()->heap()->meta_map()); - BuildCompareNil(GetParameter(0), - stub->GetTypes(), sentinel_map, - RelocInfo::kNoPosition, &continuation); + Handle sentinel_map(isolate->heap()->meta_map()); + Handle type = + CompareNilICStub::StateToType(isolate, stub->GetState(), sentinel_map); + BuildCompareNil(GetParameter(0), type, RelocInfo::kNoPosition, &continuation); IfBuilder if_nil(this, &continuation); if_nil.Then(); if (continuation.IsFalseReachable()) { diff --git a/src/code-stubs.cc b/src/code-stubs.cc index 6b6e25019d..5bec7e05f9 100644 --- a/src/code-stubs.cc +++ b/src/code-stubs.cc @@ -431,24 +431,24 @@ void ICCompareStub::Generate(MacroAssembler* masm) { void CompareNilICStub::Record(Handle object) { - ASSERT(types_ != Types::FullCompare()); + ASSERT(state_ != State::Generic()); if (object->IsNull()) { - types_.Add(NULL_TYPE); + state_.Add(NULL_TYPE); } else if (object->IsUndefined()) { - types_.Add(UNDEFINED); + state_.Add(UNDEFINED); } else if (object->IsUndetectableObject() || object->IsOddball() || !object->IsHeapObject()) { - types_ = Types::FullCompare(); + state_ = State::Generic(); } else if (IsMonomorphic()) { - types_ = Types::FullCompare(); + state_ = State::Generic(); } else { - types_.Add(MONOMORPHIC_MAP); + state_.Add(MONOMORPHIC_MAP); } } -void CompareNilICStub::Types::TraceTransition(Types to) const { +void CompareNilICStub::State::TraceTransition(State to) const { #ifdef DEBUG if (!FLAG_trace_ic) return; char buffer[100]; @@ -467,13 +467,13 @@ void CompareNilICStub::Types::TraceTransition(Types to) const { void CompareNilICStub::PrintName(StringStream* stream) { stream->Add("CompareNilICStub_"); - types_.Print(stream); + state_.Print(stream); stream->Add((nil_value_ == kNullValue) ? "(NullValue|": "(UndefinedValue|"); } -void CompareNilICStub::Types::Print(StringStream* stream) const { +void CompareNilICStub::State::Print(StringStream* stream) const { stream->Add("("); SimpleListPrinter printer(stream); if (IsEmpty()) printer.Add("None"); @@ -481,10 +481,40 @@ void CompareNilICStub::Types::Print(StringStream* stream) const { if (Contains(NULL_TYPE)) printer.Add("Null"); if (Contains(MONOMORPHIC_MAP)) printer.Add("MonomorphicMap"); if (Contains(UNDETECTABLE)) printer.Add("Undetectable"); + if (Contains(GENERIC)) printer.Add("Generic"); stream->Add(")"); } +Handle CompareNilICStub::StateToType( + Isolate* isolate, + State state, + Handle map) { + if (state.Contains(CompareNilICStub::GENERIC)) { + return handle(Type::Any(), isolate); + } + + Handle result(Type::None(), isolate); + if (state.Contains(CompareNilICStub::UNDEFINED)) { + result = handle(Type::Union(result, handle(Type::Undefined(), isolate)), + isolate); + } + if (state.Contains(CompareNilICStub::NULL_TYPE)) { + result = handle(Type::Union(result, handle(Type::Null(), isolate)), + isolate); + } + if (state.Contains(CompareNilICStub::UNDETECTABLE)) { + result = handle(Type::Union(result, handle(Type::Undetectable(), isolate)), + isolate); + } else if (state.Contains(CompareNilICStub::MONOMORPHIC_MAP)) { + Type* type = map.is_null() ? Type::Detectable() : Type::Class(map); + result = handle(Type::Union(result, handle(type, isolate)), isolate); + } + + return result; +} + + void InstanceofStub::PrintName(StringStream* stream) { const char* args = ""; if (HasArgsInRegisters()) { diff --git a/src/code-stubs.h b/src/code-stubs.h index 0ea7ac96b5..edbc93d142 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -1124,46 +1124,50 @@ class ICCompareStub: public PlatformCodeStub { class CompareNilICStub : public HydrogenCodeStub { public: - enum Type { + enum CompareNilType { UNDEFINED, NULL_TYPE, MONOMORPHIC_MAP, UNDETECTABLE, + GENERIC, NUMBER_OF_TYPES }; - class Types : public EnumSet { + class State : public EnumSet { public: - Types() : EnumSet(0) { } - explicit Types(byte bits) : EnumSet(bits) { } + State() : EnumSet(0) { } + explicit State(byte bits) : EnumSet(bits) { } - static Types FullCompare() { - Types set; + static State Generic() { + State set; set.Add(UNDEFINED); set.Add(NULL_TYPE); set.Add(UNDETECTABLE); + set.Add(GENERIC); return set; } void Print(StringStream* stream) const; - void TraceTransition(Types to) const; + void TraceTransition(State to) const; }; + static Handle StateToType( + Isolate* isolate, State state, Handle map = Handle()); + // At most 6 different types can be distinguished, because the Code object // only has room for a single byte to hold a set and there are two more // boolean flags we need to store. :-P STATIC_ASSERT(NUMBER_OF_TYPES <= 6); - CompareNilICStub(NilValue nil, Types types = Types()) - : types_(types) { - nil_value_ = nil; + CompareNilICStub(NilValue nil, State state = State()) + : nil_value_(nil), state_(state) { } CompareNilICStub(Code::ExtraICState ic_state, InitializationState init_state = INITIALIZED) : HydrogenCodeStub(init_state) { nil_value_ = NilValueField::decode(ic_state); - types_ = Types(ExtractTypesFromExtraICState(ic_state)); + state_ = State(ExtractTypesFromExtraICState(ic_state)); } static Handle GetUninitialized(Isolate* isolate, @@ -1183,9 +1187,9 @@ class CompareNilICStub : public HydrogenCodeStub { } virtual InlineCacheState GetICState() { - if (types_ == Types::FullCompare()) { + if (state_ == State::Generic()) { return MEGAMORPHIC; - } else if (types_.Contains(MONOMORPHIC_MAP)) { + } else if (state_.Contains(MONOMORPHIC_MAP)) { return MONOMORPHIC; } else { return PREMONOMORPHIC; @@ -1198,20 +1202,18 @@ class CompareNilICStub : public HydrogenCodeStub { // extra ic state = nil_value | type_n-1 | ... | type_0 virtual Code::ExtraICState GetExtraICState() { - return NilValueField::encode(nil_value_) | - types_.ToIntegral(); + return NilValueField::encode(nil_value_) | state_.ToIntegral(); } - static byte ExtractTypesFromExtraICState( - Code::ExtraICState state) { + static byte ExtractTypesFromExtraICState(Code::ExtraICState state) { return state & ((1 << NUMBER_OF_TYPES) - 1); } void Record(Handle object); - bool IsMonomorphic() const { return types_.Contains(MONOMORPHIC_MAP); } + bool IsMonomorphic() const { return state_.Contains(MONOMORPHIC_MAP); } NilValue GetNilValue() const { return nil_value_; } - Types GetTypes() const { return types_; } - void ClearTypes() { types_.RemoveAll(); } + State GetState() const { return state_; } + void ClearState() { state_.RemoveAll(); } virtual void PrintName(StringStream* stream); @@ -1229,7 +1231,7 @@ class CompareNilICStub : public HydrogenCodeStub { virtual int NotMissMinorKey() { return GetExtraICState(); } NilValue nil_value_; - Types types_; + State state_; DISALLOW_COPY_AND_ASSIGN(CompareNilICStub); }; diff --git a/src/compiler.cc b/src/compiler.cc index e8781c7b30..5de9d960c7 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -402,7 +402,7 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() { } // Type-check the function. - AstTyper::Type(info()); + AstTyper::Run(info()); graph_builder_ = new(info()->zone()) HOptimizedGraphBuilder(info()); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 7e46ee2607..3d0d5505ae 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -1698,39 +1698,35 @@ HValue* HGraphBuilder::BuildCloneShallowArray(HContext* context, void HGraphBuilder::BuildCompareNil( HValue* value, - CompareNilICStub::Types types, - Handle map, + Handle type, int position, HIfContinuation* continuation) { IfBuilder if_nil(this, position); bool needs_or = false; - if (types.Contains(CompareNilICStub::NULL_TYPE)) { + if (type->Maybe(Type::Null())) { if (needs_or) if_nil.Or(); if_nil.If(value, graph()->GetConstantNull()); needs_or = true; } - if (types.Contains(CompareNilICStub::UNDEFINED)) { + if (type->Maybe(Type::Undefined())) { if (needs_or) if_nil.Or(); if_nil.If(value, graph()->GetConstantUndefined()); needs_or = true; } - // Handle either undetectable or monomorphic, not both. - ASSERT(!types.Contains(CompareNilICStub::UNDETECTABLE) || - !types.Contains(CompareNilICStub::MONOMORPHIC_MAP)); - if (types.Contains(CompareNilICStub::UNDETECTABLE)) { + if (type->Maybe(Type::Undetectable())) { if (needs_or) if_nil.Or(); if_nil.If(value); } else { if_nil.Then(); if_nil.Else(); - if (!map.is_null() && types.Contains(CompareNilICStub::MONOMORPHIC_MAP)) { + if (type->NumClasses() == 1) { BuildCheckNonSmi(value); // For ICs, the map checked below is a sentinel map that gets replaced by // the monomorphic map when the code is used as a template to generate a // new IC. For optimized functions, there is no sentinel map, the map // emitted below is the actual monomorphic map. - BuildCheckMap(value, map); + BuildCheckMap(value, type->Classes().Current()); } else { if_nil.Deopt(); } @@ -5028,7 +5024,7 @@ void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { HControlInstruction* compare; if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { - if (!clause->IsSmiCompare()) { + if (!clause->compare_type()->Is(Type::Integer31())) { AddSoftDeoptimize(); } @@ -8002,7 +7998,7 @@ bool HOptimizedGraphBuilder::TryInline(CallKind call_kind, // Type-check the inlined function. ASSERT(target_shared->has_deoptimization_support()); - AstTyper::Type(&target_info); + AstTyper::Run(&target_info); // Save the pending call context. Set up new one for the inlined function. // The function state is new-allocated because we need to delete it @@ -9685,6 +9681,7 @@ void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { } +// TODO(rossberg): this should die eventually. Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) { if (info.IsUninitialized()) return Representation::None(); if (info.IsSmi()) return Representation::Integer32(); @@ -9695,6 +9692,14 @@ Representation HOptimizedGraphBuilder::ToRepresentation(TypeInfo info) { } +Representation HOptimizedGraphBuilder::ToRepresentation(Handle type) { + if (type->Is(Type::None())) return Representation::None(); + if (type->Is(Type::Integer32())) return Representation::Integer32(); + if (type->Is(Type::Number())) return Representation::Double(); + return Representation::Tagged(); +} + + void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, HTypeof* typeof_expr, Handle check) { @@ -9784,17 +9789,17 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { return ast_context()->ReturnControl(instr, expr->id()); } - TypeInfo left_type = expr->left_type(); - TypeInfo right_type = expr->right_type(); - TypeInfo overall_type = expr->overall_type(); + Handle left_type = expr->left_type(); + Handle right_type = expr->right_type(); + Handle overall_type = expr->overall_type(); Representation combined_rep = ToRepresentation(overall_type); Representation left_rep = ToRepresentation(left_type); Representation right_rep = ToRepresentation(right_type); // Check if this expression was ever executed according to type feedback. // Note that for the special typeof/null/undefined cases we get unknown here. - if (overall_type.IsUninitialized()) { + if (overall_type->Is(Type::None())) { AddSoftDeoptimize(); - overall_type = left_type = right_type = TypeInfo::Unknown(); + overall_type = left_type = right_type = handle(Type::Any(), isolate()); } CHECK_ALIVE(VisitForValue(expr->left())); @@ -9866,13 +9871,13 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { HIn* result = new(zone()) HIn(context, left, right); result->set_position(expr->position()); return ast_context()->ReturnInstruction(result, expr->id()); - } else if (overall_type.IsNonPrimitive()) { + } else if (overall_type->Is(Type::Receiver())) { switch (op) { case Token::EQ: case Token::EQ_STRICT: { // Can we get away with map check and not instance type check? - Handle map = expr->map(); - if (!map.is_null()) { + if (overall_type->IsClass()) { + Handle map = overall_type->AsClass(); AddCheckMapsWithTransitions(left, map); AddCheckMapsWithTransitions(right, map); HCompareObjectEqAndBranch* result = @@ -9893,7 +9898,7 @@ void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { default: return Bailout("Unsupported non-primitive compare"); } - } else if (overall_type.IsInternalizedString() && + } else if (overall_type->Is(Type::InternalizedString()) && Token::IsEqualityOp(op)) { BuildCheckNonSmi(left); AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); @@ -9928,8 +9933,8 @@ void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, ASSERT(!HasStackOverflow()); ASSERT(current_block() != NULL); ASSERT(current_block()->HasPredecessor()); + ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); HIfContinuation continuation; - CompareNilICStub::Types types; if (expr->op() == Token::EQ_STRICT) { IfBuilder if_nil(this); if_nil.If( @@ -9940,11 +9945,9 @@ void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, if_nil.CaptureContinuation(&continuation); return ast_context()->ReturnContinuation(&continuation, expr->id()); } - types = CompareNilICStub::Types(expr->compare_nil_types()); - if (types.IsEmpty()) types = CompareNilICStub::Types::FullCompare(); - Handle map_handle = expr->map(); - BuildCompareNil(value, types, map_handle, - expr->position(), &continuation); + Handle type = expr->compare_nil_type()->Is(Type::None()) + ? handle(Type::Any(), isolate_) : expr->compare_nil_type(); + BuildCompareNil(value, type, expr->position(), &continuation); return ast_context()->ReturnContinuation(&continuation, expr->id()); } diff --git a/src/hydrogen.h b/src/hydrogen.h index 457df7c219..3680775534 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -1364,8 +1364,7 @@ class HGraphBuilder { void BuildCompareNil( HValue* value, - CompareNilICStub::Types types, - Handle map, + Handle type, int position, HIfContinuation* continuation); @@ -1636,6 +1635,7 @@ class HOptimizedGraphBuilder: public HGraphBuilder, public AstVisitor { template HInstruction* PreProcessCall(Instruction* call); static Representation ToRepresentation(TypeInfo info); + static Representation ToRepresentation(Handle type); void SetUpScope(Scope* scope); virtual void VisitStatements(ZoneList* statements); diff --git a/src/ic.cc b/src/ic.cc index 94e8773a16..095b614986 100644 --- a/src/ic.cc +++ b/src/ic.cc @@ -2420,8 +2420,8 @@ UnaryOpIC::State UnaryOpIC::ToState(TypeInfo type_info) { } UnaryOpIC::TypeInfo UnaryOpIC::GetTypeInfo(Handle operand) { - ::v8::internal::TypeInfo operand_type = - ::v8::internal::TypeInfo::TypeFromValue(operand); + v8::internal::TypeInfo operand_type = + v8::internal::TypeInfo::FromValue(operand); if (operand_type.IsSmi()) { return SMI; } else if (operand_type.IsNumber()) { @@ -2545,8 +2545,7 @@ RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) { static BinaryOpIC::TypeInfo TypeInfoFromValue(Handle value, Token::Value op) { - ::v8::internal::TypeInfo type = - ::v8::internal::TypeInfo::TypeFromValue(value); + v8::internal::TypeInfo type = v8::internal::TypeInfo::FromValue(value); if (type.IsSmi()) return BinaryOpIC::SMI; if (type.IsInteger32()) { if (kSmiValueSize == 32) return BinaryOpIC::SMI; @@ -2767,10 +2766,39 @@ const char* CompareIC::GetStateName(State state) { case OBJECT: return "OBJECT"; case KNOWN_OBJECT: return "KNOWN_OBJECT"; case GENERIC: return "GENERIC"; - default: - UNREACHABLE(); - return NULL; } + UNREACHABLE(); + return NULL; +} + + +Handle CompareIC::StateToType( + Isolate* isolate, + CompareIC::State state, + Handle map) { + switch (state) { + case CompareIC::UNINITIALIZED: + return handle(Type::None(), isolate); + case CompareIC::SMI: + return handle(Type::Integer31(), isolate); + case CompareIC::NUMBER: + return handle(Type::Number(), isolate); + case CompareIC::STRING: + return handle(Type::String(), isolate); + case CompareIC::INTERNALIZED_STRING: + return handle(Type::InternalizedString(), isolate); + case CompareIC::UNIQUE_NAME: + return handle(Type::UniqueName(), isolate); + case CompareIC::OBJECT: + return handle(Type::Receiver(), isolate); + case CompareIC::KNOWN_OBJECT: + return handle( + map.is_null() ? Type::Receiver() : Type::Class(map), isolate); + case CompareIC::GENERIC: + return handle(Type::Any(), isolate); + } + UNREACHABLE(); + return Handle(); } @@ -2934,7 +2962,7 @@ void CompareNilIC::Clear(Address address, Code* target) { Code::ExtraICState state = target->extended_extra_ic_state(); CompareNilICStub stub(state, HydrogenCodeStub::UNINITIALIZED); - stub.ClearTypes(); + stub.ClearState(); Code* code = NULL; CHECK(stub.FindCodeInCache(&code, target->GetIsolate())); @@ -2961,9 +2989,9 @@ MaybeObject* CompareNilIC::CompareNil(Handle object) { // types must be supported as a result of the miss. bool already_monomorphic = stub.IsMonomorphic(); - CompareNilICStub::Types old_types = stub.GetTypes(); + CompareNilICStub::State old_state = stub.GetState(); stub.Record(object); - old_types.TraceTransition(stub.GetTypes()); + old_state.TraceTransition(stub.GetState()); NilValue nil = stub.GetNilValue(); diff --git a/src/ic.h b/src/ic.h index 8c448eb7fd..fc869ad865 100644 --- a/src/ic.h +++ b/src/ic.h @@ -741,6 +741,9 @@ class CompareIC: public IC { GENERIC }; + static Handle StateToType( + Isolate* isolate, State state, Handle map = Handle()); + CompareIC(Isolate* isolate, Token::Value op) : IC(EXTRA_CALL_FRAME, isolate), op_(op) { } diff --git a/src/objects.cc b/src/objects.cc index 82178e85e2..5459679982 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -10018,7 +10018,7 @@ void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) { VisitExternalReferences(p, p + 1); } -byte Code::compare_nil_types() { +byte Code::compare_nil_state() { ASSERT(is_compare_nil_ic_stub()); return CompareNilICStub::ExtractTypesFromExtraICState( extended_extra_ic_state()); diff --git a/src/objects.h b/src/objects.h index 5ff3450725..7771eb4058 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4669,7 +4669,7 @@ class Code: public HeapObject { inline byte to_boolean_state(); // [compare_nil]: For kind COMPARE_NIL_IC tells what state the stub is in. - byte compare_nil_types(); + byte compare_nil_state(); // [has_function_cache]: For kind STUB tells whether there is a function // cache is passed to the stub. diff --git a/src/type-info.cc b/src/type-info.cc index 1e14fca1cd..32aef1cc5e 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -42,20 +42,17 @@ namespace v8 { namespace internal { -TypeInfo TypeInfo::TypeFromValue(Handle value) { - TypeInfo info; +TypeInfo TypeInfo::FromValue(Handle value) { if (value->IsSmi()) { - info = TypeInfo::Smi(); + return TypeInfo::Smi(); } else if (value->IsHeapNumber()) { - info = TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value()) + return TypeInfo::IsInt32Double(HeapNumber::cast(*value)->value()) ? TypeInfo::Integer32() : TypeInfo::Double(); } else if (value->IsString()) { - info = TypeInfo::String(); - } else { - info = TypeInfo::Unknown(); + return TypeInfo::String(); } - return info; + return TypeInfo::Unknown(); } @@ -234,24 +231,6 @@ Handle TypeFeedbackOracle::StoreMonomorphicReceiverType( } -Handle TypeFeedbackOracle::CompareNilMonomorphicReceiverType( - CompareOperation* expr) { - Handle maybe_code = GetInfo(expr->CompareOperationFeedbackId()); - if (maybe_code->IsCode()) { - Map* map = Handle::cast(maybe_code)->FindFirstMap(); - if (map == NULL) return Handle(); - map = map->CurrentMapForDeprecated(); - return map == NULL || CanRetainOtherContext(map, *native_context_) - ? Handle() - : Handle(map); - } else if (maybe_code->IsMap()) { - ASSERT(!Handle::cast(maybe_code)->is_deprecated()); - return Handle::cast(maybe_code); - } - return Handle(); -} - - KeyedAccessStoreMode TypeFeedbackOracle::GetStoreMode( TypeFeedbackId ast_id) { Handle map_or_code = GetInfo(ast_id); @@ -362,69 +341,38 @@ bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) { } -static TypeInfo TypeFromCompareType(CompareIC::State state) { - switch (state) { - case CompareIC::UNINITIALIZED: - // Uninitialized means never executed. - return TypeInfo::Uninitialized(); - case CompareIC::SMI: - return TypeInfo::Smi(); - case CompareIC::NUMBER: - return TypeInfo::Number(); - case CompareIC::INTERNALIZED_STRING: - return TypeInfo::InternalizedString(); - case CompareIC::STRING: - return TypeInfo::String(); - case CompareIC::OBJECT: - case CompareIC::KNOWN_OBJECT: - // TODO(kasperl): We really need a type for JS objects here. - return TypeInfo::NonPrimitive(); - case CompareIC::GENERIC: - default: - return TypeInfo::Unknown(); - } -} +void TypeFeedbackOracle::CompareTypes(TypeFeedbackId id, + Handle* left_type, + Handle* right_type, + Handle* overall_type, + Handle* compare_nil_type) { + *left_type = *right_type = *overall_type = *compare_nil_type = + handle(Type::Any(), isolate_); + Handle info = GetInfo(id); + if (!info->IsCode()) return; + Handle code = Handle::cast(info); - -void TypeFeedbackOracle::CompareType(CompareOperation* expr, - TypeInfo* left_type, - TypeInfo* right_type, - TypeInfo* overall_type) { - Handle object = GetInfo(expr->CompareOperationFeedbackId()); - TypeInfo unknown = TypeInfo::Unknown(); - if (!object->IsCode()) { - *left_type = *right_type = *overall_type = unknown; - return; - } - Handle code = Handle::cast(object); - if (!code->is_compare_ic_stub()) { - *left_type = *right_type = *overall_type = unknown; - return; + Handle map; + Map* raw_map = code->FindFirstMap(); + if (raw_map != NULL) { + raw_map = raw_map->CurrentMapForDeprecated(); + if (!CanRetainOtherContext(raw_map, *native_context_)) { + map = handle(raw_map, isolate_); + } } - 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 = TypeFromCompareType(left_state); - *right_type = TypeFromCompareType(right_state); - *overall_type = TypeFromCompareType(handler_state); -} - - -Handle TypeFeedbackOracle::GetCompareMap(CompareOperation* expr) { - Handle object = GetInfo(expr->CompareOperationFeedbackId()); - if (!object->IsCode()) return Handle::null(); - Handle code = Handle::cast(object); - if (!code->is_compare_ic_stub()) return Handle::null(); - CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); - if (state != CompareIC::KNOWN_OBJECT) { - return Handle::null(); + 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); + } else if (code->is_compare_nil_ic_stub()) { + CompareNilICStub::State state(code->compare_nil_state()); + *compare_nil_type = CompareNilICStub::StateToType(isolate_, state, map); } - Map* map = code->FindFirstMap()->CurrentMapForDeprecated(); - return map == NULL || CanRetainOtherContext(map, *native_context_) - ? Handle::null() - : Handle(map); } @@ -495,15 +443,15 @@ void TypeFeedbackOracle::BinaryType(BinaryOperation* expr, } -TypeInfo TypeFeedbackOracle::SwitchType(CaseClause* clause) { - Handle object = GetInfo(clause->CompareId()); - TypeInfo unknown = TypeInfo::Unknown(); - if (!object->IsCode()) return unknown; - Handle code = Handle::cast(object); - if (!code->is_compare_ic_stub()) return unknown; - - CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); - return TypeFromCompareType(state); +Handle TypeFeedbackOracle::ClauseType(TypeFeedbackId id) { + Handle info = GetInfo(id); + Handle result(Type::None(), isolate_); + if (info->IsCode() && Handle::cast(info)->is_compare_ic_stub()) { + Handle code = Handle::cast(info); + CompareIC::State state = ICCompareStub::CompareState(code->stub_info()); + result = CompareIC::StateToType(isolate_, state); + } + return result; } @@ -634,17 +582,6 @@ byte TypeFeedbackOracle::ToBooleanTypes(TypeFeedbackId id) { } -byte TypeFeedbackOracle::CompareNilTypes(CompareOperation* expr) { - Handle object = GetInfo(expr->CompareOperationFeedbackId()); - if (object->IsCode() && - Handle::cast(object)->is_compare_nil_ic_stub()) { - return Handle::cast(object)->compare_nil_types(); - } else { - return CompareNilICStub::Types::FullCompare().ToIntegral(); - } -} - - // Things are a bit tricky here: The iterator for the RelocInfos and the infos // themselves are not GC-safe, so we first get all infos, then we create the // dictionary (possibly triggering GC), and finally we relocate the collected diff --git a/src/type-info.h b/src/type-info.h index 8b4b84e2ed..1262b3177c 100644 --- a/src/type-info.h +++ b/src/type-info.h @@ -30,6 +30,7 @@ #include "allocation.h" #include "globals.h" +#include "types.h" #include "zone-inl.h" namespace v8 { @@ -113,7 +114,7 @@ class TypeInfo { return false; } - static TypeInfo TypeFromValue(Handle value); + static TypeInfo FromValue(Handle value); bool Equals(const TypeInfo& other) { return type_ == other.type_; @@ -217,12 +218,12 @@ enum StringStubFeedback { // Forward declarations. +// TODO(rossberg): these should all go away eventually. class Assignment; class BinaryOperation; class Call; class CallNew; class CaseClause; -class CompareOperation; class CompilationInfo; class CountOperation; class Expression; @@ -257,7 +258,6 @@ class TypeFeedbackOracle: public ZoneObject { Handle LoadMonomorphicReceiverType(Property* expr); Handle StoreMonomorphicReceiverType(TypeFeedbackId id); - Handle CompareNilMonomorphicReceiverType(CompareOperation* expr); KeyedAccessStoreMode GetStoreMode(TypeFeedbackId ast_id); @@ -293,12 +293,7 @@ class TypeFeedbackOracle: public ZoneObject { // TODO(1571) We can't use ToBooleanStub::Types as the return value because // of various cycles in our headers. Death to tons of implementations in // headers!! :-P - byte ToBooleanTypes(TypeFeedbackId ast_id); - - // TODO(1571) We can't use CompareNilICStub::Types as the return value because - // of various cylces in our headers. Death to tons of implementations in - // headers!! :-P - byte CompareNilTypes(CompareOperation* expr); + byte ToBooleanTypes(TypeFeedbackId id); // Get type information for arithmetic operations and compares. TypeInfo UnaryType(UnaryOperation* expr); @@ -308,12 +303,15 @@ class TypeFeedbackOracle: public ZoneObject { TypeInfo* result, bool* has_fixed_right_arg, int* fixed_right_arg_value); - void CompareType(CompareOperation* expr, - TypeInfo* left_type, - TypeInfo* right_type, - TypeInfo* overall_type); - Handle GetCompareMap(CompareOperation* expr); - TypeInfo SwitchType(CaseClause* clause); + + void CompareTypes(TypeFeedbackId id, + Handle* left_type, + Handle* right_type, + Handle* overall_type, + Handle* compare_nil_type); + + Handle ClauseType(TypeFeedbackId id); + TypeInfo IncrementType(CountOperation* expr); Zone* zone() const { return zone_; } diff --git a/src/types.cc b/src/types.cc index f7fbd2d69b..20e8a4c994 100644 --- a/src/types.cc +++ b/src/types.cc @@ -30,6 +30,84 @@ namespace v8 { namespace internal { +int Type::NumClasses() { + if (is_class()) { + return 1; + } else if (is_union()) { + Handle unioned = as_union(); + int result = 0; + for (int i = 0; i < unioned->length(); ++i) { + if (union_get(unioned, i)->is_class()) ++result; + } + return result; + } else { + return 0; + } +} + + +int Type::NumConstants() { + if (is_constant()) { + return 1; + } else if (is_union()) { + Handle unioned = as_union(); + int result = 0; + for (int i = 0; i < unioned->length(); ++i) { + if (union_get(unioned, i)->is_constant()) ++result; + } + return result; + } else { + return 0; + } +} + + +template +Handle Type::Iterator::get_type() { + ASSERT(!Done()); + return type_->is_union() ? union_get(type_->as_union(), index_) : type_; +} + +template<> +Handle Type::Iterator::Current() { + return get_type()->as_class(); +} + +template<> +Handle Type::Iterator::Current() { + return get_type()->as_constant(); +} + + +template<> +bool Type::Iterator::matches(Handle type) { + return type->is_class(); +} + +template<> +bool Type::Iterator::matches(Handle type) { + return type->is_constant(); +} + + +template +void Type::Iterator::Advance() { + ++index_; + if (type_->is_union()) { + Handle unioned = type_->as_union(); + for (; index_ < unioned->length(); ++index_) { + if (matches(union_get(unioned, index_))) return; + } + } else if (index_ == 0 && matches(type_)) { + return; + } + index_ = -1; +} + +template class Type::Iterator; +template class Type::Iterator; + + // Get the smallest bitset subsuming this type. int Type::LubBitset() { if (this->is_bitset()) { @@ -46,9 +124,14 @@ int Type::LubBitset() { if (this->is_class()) { map = *this->as_class(); } else { - v8::internal::Object* value = this->as_constant()->value(); - if (value->IsSmi()) return kSmi; - map = HeapObject::cast(value)->map(); + Handle value = this->as_constant(); + if (value->IsSmi()) return kInteger31; + map = HeapObject::cast(*value)->map(); + if (map->instance_type() == ODDBALL_TYPE) { + if (value->IsUndefined()) return kUndefined; + if (value->IsNull()) return kNull; + if (value->IsTrue() || value->IsFalse()) return kBoolean; + } } switch (map->instance_type()) { case STRING_TYPE: @@ -56,6 +139,7 @@ int Type::LubBitset() { case CONS_STRING_TYPE: case CONS_ASCII_STRING_TYPE: case SLICED_STRING_TYPE: + case SLICED_ASCII_STRING_TYPE: case EXTERNAL_STRING_TYPE: case EXTERNAL_ASCII_STRING_TYPE: case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: @@ -92,6 +176,7 @@ int Type::LubBitset() { case JS_TYPED_ARRAY_TYPE: case JS_WEAK_MAP_TYPE: case JS_REGEXP_TYPE: + if (map->is_undetectable()) return kUndetectable; return kOtherObject; case JS_ARRAY_TYPE: return kArray; @@ -100,6 +185,17 @@ int Type::LubBitset() { case JS_PROXY_TYPE: case JS_FUNCTION_PROXY_TYPE: return kProxy; + case MAP_TYPE: + // When compiling stub templates, the meta map is used as a place holder + // for the actual map with which the template is later instantiated. + // We treat it as a kind of type variable whose upper bound is Any. + // TODO(rossberg): for caching of CompareNilIC stubs to work correctly, + // we must exclude Undetectable here. This makes no sense, really, + // because it means that the template isn't actually parametric. + // Also, it doesn't apply elsewhere. 8-( + // We ought to find a cleaner solution for compiling stubs parameterised + // over type or class variables, esp ones with bounds... + return kDetectable; default: UNREACHABLE(); return kNone; @@ -122,7 +218,7 @@ int Type::GlbBitset() { // Check this <= that. -bool Type::Is(Handle that) { +bool Type::Is(Type* that) { // Fast path for bitsets. if (that->is_bitset()) { return (this->LubBitset() | that->as_bitset()) == that->as_bitset(); @@ -132,8 +228,7 @@ bool Type::Is(Handle that) { return this->is_class() && *this->as_class() == *that->as_class(); } if (that->is_constant()) { - return this->is_constant() && - this->as_constant()->value() == that->as_constant()->value(); + return this->is_constant() && *this->as_constant() == *that->as_constant(); } // (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T) @@ -163,7 +258,7 @@ bool Type::Is(Handle that) { // Check this overlaps that. -bool Type::Maybe(Handle that) { +bool Type::Maybe(Type* that) { // Fast path for bitsets. if (this->is_bitset()) { return (this->as_bitset() & that->LubBitset()) != 0; @@ -176,8 +271,7 @@ bool Type::Maybe(Handle that) { return that->is_class() && *this->as_class() == *that->as_class(); } if (this->is_constant()) { - return that->is_constant() && - this->as_constant()->value() == that->as_constant()->value(); + return that->is_constant() && *this->as_constant() == *that->as_constant(); } // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T) diff --git a/src/types.h b/src/types.h index 6db9bfbb6a..883d8840e6 100644 --- a/src/types.h +++ b/src/types.h @@ -48,11 +48,15 @@ namespace internal { // T <= Any // // Oddball = Boolean \/ Null \/ Undefined -// Number = Smi \/ Double +// Number = Integer32 \/ Double +// Integer31 < Integer32 // Name = String \/ Symbol // UniqueName = InternalizedString \/ Symbol // InternalizedString < String // +// Allocated = Receiver \/ Number \/ Name +// Detectable = Allocated - Undetectable +// Undetectable < Object // Receiver = Object \/ Proxy // Array < Object // Function < Object @@ -70,8 +74,9 @@ namespace internal { // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) // -// Typically, the latter should be used to check whether a specific case needs -// handling (e.g., via T->Maybe(Number)). +// Typically, the former is to be used to select representations (e.g., via +// T->Is(Integer31())), and the to check whether a specific case needs handling +// (e.g., via T->Maybe(Number())). // // There is no functionality to discover whether a type is a leaf in the // lattice. That is intentional. It should always be possible to refine the @@ -89,6 +94,8 @@ class Type : public Object { public: static Type* None() { return from_bitset(kNone); } static Type* Any() { return from_bitset(kAny); } + static Type* Allocated() { return from_bitset(kAllocated); } + static Type* Detectable() { return from_bitset(kDetectable); } static Type* Oddball() { return from_bitset(kOddball); } static Type* Boolean() { return from_bitset(kBoolean); } @@ -96,7 +103,8 @@ class Type : public Object { static Type* Undefined() { return from_bitset(kUndefined); } static Type* Number() { return from_bitset(kNumber); } - static Type* Smi() { return from_bitset(kSmi); } + static Type* Integer31() { return from_bitset(kInteger31); } + static Type* Integer32() { return from_bitset(kInteger32); } static Type* Double() { return from_bitset(kDouble); } static Type* Name() { return from_bitset(kName); } @@ -107,6 +115,7 @@ class Type : public Object { static Type* Receiver() { return from_bitset(kReceiver); } static Type* Object() { return from_bitset(kObject); } + static Type* Undetectable() { return from_bitset(kUndetectable); } static Type* Array() { return from_bitset(kArray); } static Type* Function() { return from_bitset(kFunction); } static Type* Proxy() { return from_bitset(kProxy); } @@ -122,10 +131,49 @@ class Type : public Object { static Type* Union(Handle type1, Handle type2); static Type* Optional(Handle type); // type \/ Undefined - bool Is(Handle that); - bool Maybe(Handle that); + bool Is(Type* that); + bool Is(Handle that) { return this->Is(*that); } + bool Maybe(Type* that); + bool Maybe(Handle that) { return this->Maybe(*that); } - // TODO(rossberg): method to iterate unions? + bool IsClass() { return is_class(); } + bool IsConstant() { return is_constant(); } + Handle AsClass() { return as_class(); } + Handle AsConstant() { return as_constant(); } + + int NumClasses(); + int NumConstants(); + + template + class Iterator { + public: + bool Done() const { return index_ < 0; } + Handle Current(); + void Advance(); + + private: + friend class Type; + + Iterator() : index_(-1) {} + explicit Iterator(Handle type) : type_(type), index_(-1) { + Advance(); + } + + inline bool matches(Handle type); + inline Handle get_type(); + + Handle type_; + int index_; + }; + + Iterator Classes() { + if (this->is_bitset()) return Iterator(); + return Iterator(this->handle()); + } + Iterator Constants() { + if (this->is_bitset()) return Iterator(); + return Iterator(this->handle()); + } private: // A union is a fixed array containing types. Invariants: @@ -138,24 +186,29 @@ class Type : public Object { kNull = 1 << 0, kUndefined = 1 << 1, kBoolean = 1 << 2, - kSmi = 1 << 3, - kDouble = 1 << 4, - kSymbol = 1 << 5, - kInternalizedString = 1 << 6, - kOtherString = 1 << 7, - kArray = 1 << 8, - kFunction = 1 << 9, - kOtherObject = 1 << 10, - kProxy = 1 << 11, + kInteger31 = 1 << 3, + kOtherInteger = 1 << 4, + kDouble = 1 << 5, + kSymbol = 1 << 6, + kInternalizedString = 1 << 7, + kOtherString = 1 << 8, + kUndetectable = 1 << 9, + kArray = 1 << 10, + kFunction = 1 << 11, + kOtherObject = 1 << 12, + kProxy = 1 << 13, kOddball = kBoolean | kNull | kUndefined, - kNumber = kSmi | kDouble, + kInteger32 = kInteger31 | kOtherInteger, + kNumber = kInteger32 | kDouble, kString = kInternalizedString | kOtherString, kUniqueName = kSymbol | kInternalizedString, kName = kSymbol | kString, - kObject = kArray | kFunction | kOtherObject, + kObject = kUndetectable | kArray | kFunction | kOtherObject, kReceiver = kObject | kProxy, - kAny = kOddball | kNumber | kName | kReceiver, + kAllocated = kDouble | kName | kReceiver, + kAny = kOddball | kNumber | kAllocated, + kDetectable = kAllocated - kUndetectable, kNone = 0 }; @@ -166,7 +219,10 @@ class Type : public Object { int as_bitset() { return Smi::cast(this)->value(); } Handle as_class() { return Handle::cast(handle()); } - Handle as_constant() { return Handle::cast(handle()); } + Handle as_constant() { + Handle box = Handle::cast(handle()); + return v8::internal::handle(box->value(), box->GetIsolate()); + } Handle as_union() { return Handle::cast(handle()); } Handle handle() { return handle_via_isolate_of(this); } diff --git a/src/typing.cc b/src/typing.cc index 4ba67213a1..e1fd8aab74 100644 --- a/src/typing.cc +++ b/src/typing.cc @@ -52,7 +52,7 @@ AstTyper::AstTyper(CompilationInfo* info) } while (false) -void AstTyper::Type(CompilationInfo* info) { +void AstTyper::Run(CompilationInfo* info) { AstTyper* visitor = new(info->zone()) AstTyper(info); Scope* scope = info->scope(); diff --git a/src/typing.h b/src/typing.h index d8708c2ccb..1f172eaf59 100644 --- a/src/typing.h +++ b/src/typing.h @@ -43,7 +43,7 @@ namespace internal { class AstTyper: public AstVisitor { public: - static void Type(CompilationInfo* info); + static void Run(CompilationInfo* info); void* operator new(size_t size, Zone* zone) { return zone->New(static_cast(size)); diff --git a/test/cctest/test-compare-nil-ic-stub.cc b/test/cctest/test-compare-nil-ic-stub.cc index affb8bd637..258ab012c7 100644 --- a/test/cctest/test-compare-nil-ic-stub.cc +++ b/test/cctest/test-compare-nil-ic-stub.cc @@ -34,26 +34,26 @@ using namespace v8::internal; -#define Types CompareNilICStub::Types +typedef CompareNilICStub::State State; -TEST(TypeConstructors) { - Types types; - types.Add(CompareNilICStub::MONOMORPHIC_MAP); - Types types2(types); - CHECK_EQ(types.ToIntegral(), types2.ToIntegral()); +TEST(StateConstructors) { + State state; + state.Add(CompareNilICStub::MONOMORPHIC_MAP); + State state2(state); + CHECK_EQ(state.ToIntegral(), state2.ToIntegral()); } TEST(ExternalICStateParsing) { - Types types; - types.Add(CompareNilICStub::UNDEFINED); - CompareNilICStub stub(kUndefinedValue, types); + State state; + state.Add(CompareNilICStub::UNDEFINED); + CompareNilICStub stub(kUndefinedValue, state); CompareNilICStub stub2(stub.GetExtraICState()); CHECK_EQ(stub.GetNilValue(), stub2.GetNilValue()); - CHECK_EQ(stub.GetTypes().ToIntegral(), stub2.GetTypes().ToIntegral()); + CHECK_EQ(stub.GetState().ToIntegral(), stub2.GetState().ToIntegral()); } -TEST(SettingTypes) { - Types state; +TEST(SettingState) { + State state; CHECK(state.IsEmpty()); state.Add(CompareNilICStub::NULL_TYPE); CHECK(!state.IsEmpty()); @@ -66,20 +66,22 @@ TEST(SettingTypes) { CHECK(!state.Contains(CompareNilICStub::UNDETECTABLE)); } -TEST(ClearTypes) { - Types state; +TEST(ClearState) { + State state; state.Add(CompareNilICStub::NULL_TYPE); state.RemoveAll(); CHECK(state.IsEmpty()); } -TEST(FullCompare) { - Types state; - CHECK(Types::FullCompare() != state); +TEST(Generic) { + State state; + CHECK(State::Generic() != state); state.Add(CompareNilICStub::UNDEFINED); - CHECK(state != Types::FullCompare()); + CHECK(state != State::Generic()); state.Add(CompareNilICStub::NULL_TYPE); - CHECK(state != Types::FullCompare()); + CHECK(state != State::Generic()); state.Add(CompareNilICStub::UNDETECTABLE); - CHECK(state == Types::FullCompare()); + CHECK(state != State::Generic()); + state.Add(CompareNilICStub::GENERIC); + CHECK(state == State::Generic()); } diff --git a/test/cctest/test-types.cc b/test/cctest/test-types.cc index 3cdfdad7e4..97294888ab 100644 --- a/test/cctest/test-types.cc +++ b/test/cctest/test-types.cc @@ -51,7 +51,8 @@ class HandlifiedTypes { Null(Type::Null(), isolate), Undefined(Type::Undefined(), isolate), Number(Type::Number(), isolate), - Smi(Type::Smi(), isolate), + Integer31(Type::Integer31(), isolate), + Integer32(Type::Integer32(), isolate), Double(Type::Double(), isolate), Name(Type::Name(), isolate), UniqueName(Type::UniqueName(), isolate), @@ -72,7 +73,7 @@ class HandlifiedTypes { array = isolate->factory()->NewJSArray(20); ObjectClass = handle(Type::Class(object_map), isolate); ArrayClass = handle(Type::Class(array_map), isolate); - SmiConstant = handle(Type::Constant(smi, isolate), isolate); + Integer31Constant = handle(Type::Constant(smi, isolate), isolate); ObjectConstant1 = handle(Type::Constant(object1), isolate); ObjectConstant2 = handle(Type::Constant(object2), isolate); ArrayConstant = handle(Type::Constant(array), isolate); @@ -85,7 +86,8 @@ class HandlifiedTypes { Handle Null; Handle Undefined; Handle Number; - Handle Smi; + Handle Integer31; + Handle Integer32; Handle Double; Handle Name; Handle UniqueName; @@ -101,7 +103,7 @@ class HandlifiedTypes { Handle ObjectClass; Handle ArrayClass; - Handle SmiConstant; + Handle Integer31Constant; Handle ObjectConstant1; Handle ObjectConstant2; Handle ArrayConstant; @@ -168,12 +170,12 @@ TEST(Constant) { HandleScope scope(isolate); HandlifiedTypes T(isolate); - CHECK(IsConstant(*T.SmiConstant)); + CHECK(IsConstant(*T.Integer31Constant)); CHECK(IsConstant(*T.ObjectConstant1)); CHECK(IsConstant(*T.ObjectConstant2)); CHECK(IsConstant(*T.ArrayConstant)); - CHECK(*T.smi == AsConstant(*T.SmiConstant)); + CHECK(*T.smi == AsConstant(*T.Integer31Constant)); CHECK(*T.object1 == AsConstant(*T.ObjectConstant1)); CHECK(*T.object2 == AsConstant(*T.ObjectConstant2)); CHECK(*T.object1 != AsConstant(*T.ObjectConstant2)); @@ -224,9 +226,12 @@ TEST(Is) { CheckUnordered(T.Boolean, T.Undefined); CheckSub(T.Number, T.Any); - CheckSub(T.Smi, T.Number); + CheckSub(T.Integer31, T.Number); + CheckSub(T.Integer32, T.Number); CheckSub(T.Double, T.Number); - CheckUnordered(T.Smi, T.Double); + CheckSub(T.Integer31, T.Integer32); + CheckUnordered(T.Integer31, T.Double); + CheckUnordered(T.Integer32, T.Double); CheckSub(T.Name, T.Any); CheckSub(T.UniqueName, T.Any); @@ -255,8 +260,9 @@ TEST(Is) { CheckSub(T.ArrayClass, T.Object); CheckUnordered(T.ObjectClass, T.ArrayClass); - CheckSub(T.SmiConstant, T.Smi); - CheckSub(T.SmiConstant, T.Number); + CheckSub(T.Integer31Constant, T.Integer31); + CheckSub(T.Integer31Constant, T.Integer32); + CheckSub(T.Integer31Constant, T.Number); CheckSub(T.ObjectConstant1, T.Object); CheckSub(T.ObjectConstant2, T.Object); CheckSub(T.ArrayConstant, T.Object); @@ -308,9 +314,9 @@ TEST(Maybe) { CheckDisjoint(T.Boolean, T.Undefined); CheckOverlap(T.Number, T.Any); - CheckOverlap(T.Smi, T.Number); + CheckOverlap(T.Integer31, T.Number); CheckOverlap(T.Double, T.Number); - CheckDisjoint(T.Smi, T.Double); + CheckDisjoint(T.Integer32, T.Double); CheckOverlap(T.Name, T.Any); CheckOverlap(T.UniqueName, T.Any); @@ -340,9 +346,10 @@ TEST(Maybe) { CheckOverlap(T.ArrayClass, T.ArrayClass); CheckDisjoint(T.ObjectClass, T.ArrayClass); - CheckOverlap(T.SmiConstant, T.Smi); - CheckOverlap(T.SmiConstant, T.Number); - CheckDisjoint(T.SmiConstant, T.Double); + CheckOverlap(T.Integer31Constant, T.Integer31); + CheckOverlap(T.Integer31Constant, T.Integer32); + CheckOverlap(T.Integer31Constant, T.Number); + CheckDisjoint(T.Integer31Constant, T.Double); CheckOverlap(T.ObjectConstant1, T.Object); CheckOverlap(T.ObjectConstant2, T.Object); CheckOverlap(T.ArrayConstant, T.Object); @@ -425,21 +432,22 @@ TEST(Union) { CheckEqual(T.Union(T.ObjectClass, T.Object), T.Object); CheckSub(T.Union(T.ObjectClass, T.Number), T.Any); - CheckSub(T.Union(T.ObjectClass, T.Smi), T.Union(T.Object, T.Number)); + CheckSub(T.Union(T.ObjectClass, T.Integer31), T.Union(T.Object, T.Number)); CheckSub(T.Union(T.ObjectClass, T.Array), T.Object); CheckUnordered(T.Union(T.ObjectClass, T.String), T.Array); CheckOverlap(T.Union(T.ObjectClass, T.String), T.Object); CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number); // Bitset-constant - CHECK(IsBitset(Type::Union(T.SmiConstant, T.Number))); + CHECK(IsBitset(Type::Union(T.Integer31Constant, T.Number))); CHECK(IsBitset(Type::Union(T.ObjectConstant1, T.Object))); CHECK(IsUnion(Type::Union(T.ObjectConstant2, T.Number))); - CheckEqual(T.Union(T.SmiConstant, T.Number), T.Number); + CheckEqual(T.Union(T.Integer31Constant, T.Number), T.Number); CheckEqual(T.Union(T.ObjectConstant1, T.Object), T.Object); CheckSub(T.Union(T.ObjectConstant1, T.Number), T.Any); - CheckSub(T.Union(T.ObjectConstant1, T.Smi), T.Union(T.Object, T.Number)); + CheckSub( + T.Union(T.ObjectConstant1, T.Integer32), T.Union(T.Object, T.Number)); CheckSub(T.Union(T.ObjectConstant1, T.Array), T.Object); CheckUnordered(T.Union(T.ObjectConstant1, T.String), T.Array); CheckOverlap(T.Union(T.ObjectConstant1, T.String), T.Object); @@ -516,8 +524,8 @@ TEST(Union) { T.Union(T.ObjectConstant2, T.Union(T.ArrayConstant, T.ObjectConstant1))); // Union-union - CHECK(IsBitset( - Type::Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Smi, T.Array)))); + CHECK(IsBitset(Type::Union( + T.Union(T.Number, T.ArrayClass), T.Union(T.Integer32, T.Array)))); CheckEqual( T.Union(T.Union(T.ObjectConstant2, T.ObjectConstant1), @@ -528,6 +536,6 @@ TEST(Union) { T.Union(T.ObjectConstant1, T.ArrayConstant)), T.Union(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ArrayConstant)); CheckEqual( - T.Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Smi, T.Array)), + T.Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Integer31, T.Array)), T.Union(T.Number, T.Array)); }