--- old/src/share/vm/oops/methodData.cpp 2014-03-20 12:32:00.285045997 +0100 +++ new/src/share/vm/oops/methodData.cpp 2014-03-20 12:31:59.933698091 +0100 @@ -800,6 +800,8 @@ case Bytecodes::_invokeinterface: case Bytecodes::_if_acmpeq: case Bytecodes::_if_acmpne: + case Bytecodes::_ifnull: + case Bytecodes::_ifnonnull: case Bytecodes::_invokestatic: #ifdef COMPILER2 return UseTypeSpeculation; --- old/src/share/vm/ci/ciMethod.cpp 2014-03-20 12:32:00.310288507 +0100 +++ new/src/share/vm/ci/ciMethod.cpp 2014-03-20 12:31:59.983745458 +0100 @@ -581,14 +581,14 @@ * Check whether profiling provides a type for the argument i to the * call at bci bci * - * @param bci bci of the call - * @param i argument number - * @return profiled type + * @param [in]bci bci of the call + * @param [in]i argument number + * @param [out]type profiled type of argument, NULL if none + * @param [out]maybe_null true if null was seen for argument + * @return true if profiling exists * - * If the profile reports that the argument may be null, return false - * at least for now. */ -ciKlass* ciMethod::argument_profiled_type(int bci, int i) { +bool ciMethod::argument_profiled_type(int bci, int i, ciKlass*& type, bool& maybe_null) { if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) { ciProfileData* data = method_data()->bci_to_data(bci); if (data != NULL) { @@ -596,82 +596,77 @@ assert_virtual_call_type_ok(bci); ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData(); if (i >= call->number_of_arguments()) { - return NULL; - } - ciKlass* type = call->valid_argument_type(i); - if (type != NULL && !call->argument_maybe_null(i)) { - return type; + return false; } + type = call->valid_argument_type(i); + maybe_null = call->argument_maybe_null(i); + return true; } else if (data->is_CallTypeData()) { assert_call_type_ok(bci); ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData(); if (i >= call->number_of_arguments()) { - return NULL; - } - ciKlass* type = call->valid_argument_type(i); - if (type != NULL && !call->argument_maybe_null(i)) { - return type; + return false; } + type = call->valid_argument_type(i); + maybe_null = call->argument_maybe_null(i); + return true; } } } - return NULL; + return false; } /** * Check whether profiling provides a type for the return value from * the call at bci bci * - * @param bci bci of the call - * @return profiled type + * @param [in]bci bci of the call + * @param [out]type profiled type of argument, NULL if none + * @param [out]maybe_null true if null was seen for argument + * @return true if profiling exists * - * If the profile reports that the argument may be null, return false - * at least for now. */ -ciKlass* ciMethod::return_profiled_type(int bci) { +bool ciMethod::return_profiled_type(int bci, ciKlass*& type, bool& maybe_null) { if (MethodData::profile_return() && method_data() != NULL && method_data()->is_mature()) { ciProfileData* data = method_data()->bci_to_data(bci); if (data != NULL) { if (data->is_VirtualCallTypeData()) { assert_virtual_call_type_ok(bci); ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData(); - ciKlass* type = call->valid_return_type(); - if (type != NULL && !call->return_maybe_null()) { - return type; - } + type = call->valid_return_type(); + maybe_null = call->return_maybe_null(); + return true; } else if (data->is_CallTypeData()) { assert_call_type_ok(bci); ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData(); - ciKlass* type = call->valid_return_type(); - if (type != NULL && !call->return_maybe_null()) { - return type; - } + type = call->valid_return_type(); + maybe_null = call->return_maybe_null(); + return true; } } } - return NULL; + return false; } /** * Check whether profiling provides a type for the parameter i * - * @param i parameter number - * @return profiled type + * @param [in]i parameter number + * @param [out]type profiled type of parameter, NULL if none + * @param [out]maybe_null true if null was seen for parameter + * @return true if profiling exists * - * If the profile reports that the argument may be null, return false - * at least for now. */ -ciKlass* ciMethod::parameter_profiled_type(int i) { +bool ciMethod::parameter_profiled_type(int i, ciKlass*& type, bool& maybe_null) { if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) { ciParametersTypeData* parameters = method_data()->parameters_type_data(); if (parameters != NULL && i < parameters->number_of_parameters()) { - ciKlass* type = parameters->valid_parameter_type(i); - if (type != NULL && !parameters->parameter_maybe_null(i)) { - return type; - } + type = parameters->valid_parameter_type(i); + maybe_null = parameters->parameter_maybe_null(i); + return true; } } - return NULL; + return false; } --- old/src/share/vm/opto/graphKit.hpp 2014-03-20 12:32:00.333024639 +0100 +++ new/src/share/vm/opto/graphKit.hpp 2014-03-20 12:31:59.911260399 +0100 @@ -350,9 +350,11 @@ // Return the value cast to not-null. // Be clever about equivalent dominating null checks. Node* null_check_common(Node* value, BasicType type, - bool assert_null = false, Node* *null_control = NULL); + bool assert_null = false, + Node* *null_control = NULL, + bool speculative = false); Node* null_check(Node* value, BasicType type = T_OBJECT) { - return null_check_common(value, type); + return null_check_common(value, type, false, NULL, !_gvn.type(value)->speculative_maybe_null()); } Node* null_check_receiver() { assert(argument(0)->bottom_type()->isa_ptr(), "must be"); @@ -381,10 +383,12 @@ // If safe_for_replace, then we can replace the value with the cast // in the parsing map (the cast is guaranteed to dominate the map) Node* null_check_oop(Node* value, Node* *null_control, - bool never_see_null = false, bool safe_for_replace = false); + bool never_see_null = false, + bool safe_for_replace = false, + bool speculative = false); // Check the null_seen bit. - bool seems_never_null(Node* obj, ciProfileData* data); + bool seems_never_null(Node* obj, ciProfileData* data, bool& speculating); // Check for unique class for receiver at call ciKlass* profile_has_unique_klass() { @@ -398,10 +402,11 @@ } // record type from profiling with the type system - Node* record_profile_for_speculation(Node* n, ciKlass* exact_kls); - Node* record_profiled_receiver_for_speculation(Node* n); + Node* record_profile_for_speculation(Node* n, ciKlass* exact_kls, bool maybe_null); void record_profiled_arguments_for_speculation(ciMethod* dest_method, Bytecodes::Code bc); void record_profiled_parameters_for_speculation(); + void record_profiled_return_for_speculation(); + Node* record_profiled_receiver_for_speculation(Node* n); // Use the type profile to narrow an object type. Node* maybe_cast_profiled_receiver(Node* not_null_obj, --- old/src/share/vm/ci/ciMethod.hpp 2014-03-20 12:32:00.332362870 +0100 +++ new/src/share/vm/ci/ciMethod.hpp 2014-03-20 12:32:00.061125426 +0100 @@ -234,10 +234,10 @@ ciCallProfile call_profile_at_bci(int bci); int interpreter_call_site_count(int bci); - // Does type profiling provide a useful type at this point? - ciKlass* argument_profiled_type(int bci, int i); - ciKlass* parameter_profiled_type(int i); - ciKlass* return_profiled_type(int bci); + // Does type profiling provide any useful information at this point? + bool argument_profiled_type(int bci, int i, ciKlass*& type, bool& maybe_null); + bool parameter_profiled_type(int i, ciKlass*& type, bool& maybe_null); + bool return_profiled_type(int bci, ciKlass*& type, bool& maybe_null); ciField* get_field_at_bci( int bci, bool &will_link); ciMethod* get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature); --- old/src/share/vm/oops/methodData.hpp 2014-03-20 12:32:00.333703800 +0100 +++ new/src/share/vm/oops/methodData.hpp 2014-03-20 12:32:00.034233312 +0100 @@ -2052,7 +2052,7 @@ // Whole-method sticky bits and flags enum { - _trap_hist_limit = 18, // decoupled from Deoptimization::Reason_LIMIT + _trap_hist_limit = 19, // decoupled from Deoptimization::Reason_LIMIT _trap_hist_mask = max_jubyte, _extra_data_count = 4 // extra DataLayout headers, for trap history }; // Public flag values --- old/src/share/vm/opto/phaseX.cpp 2014-03-20 12:32:00.358791380 +0100 +++ new/src/share/vm/opto/phaseX.cpp 2014-03-20 12:31:59.961803539 +0100 @@ -330,7 +330,7 @@ Node *sentinel_node = sentinel(); for (uint i = 0; i < max; ++i) { Node *n = at(i); - if(n != NULL && n != sentinel_node && n->is_Type()) { + if(n != NULL && n != sentinel_node && n->is_Type() && n->outcnt() > 0) { TypeNode* tn = n->as_Type(); const Type* t = tn->type(); const Type* t_no_spec = t->remove_speculative(); --- old/src/share/vm/opto/connode.cpp 2014-03-20 12:32:00.356970095 +0100 +++ new/src/share/vm/opto/connode.cpp 2014-03-20 12:32:00.009140628 +0100 @@ -399,7 +399,7 @@ // Take 'join' of input and cast-up type const Type *ConstraintCastNode::Value( PhaseTransform *phase ) const { if( in(0) && phase->type(in(0)) == Type::TOP ) return Type::TOP; -const Type* ft = phase->type(in(1))->filter_speculative(_type); + const Type* ft = phase->type(in(1))->filter_speculative(_type); #ifdef ASSERT // Previous versions of this function had some special case logic, @@ -493,7 +493,17 @@ result = my_type->cast_to_ptr_type( my_type->join_ptr(in_ptr) ); } } - return result; + + // This is the code from TypePtr::xmeet() that prevents us from + // having 2 ways to represent the same type. We have to replicate it + // here because we don't go through meet/join. + if (result->remove_speculative() == result->speculative()) { + result = result->remove_speculative(); + } + + // Same as above: because we don't go through meet/join, remove the + // speculative type if we know we won't use it. + return result->cleanup_speculative(); // JOIN NOT DONE HERE BECAUSE OF INTERFACE ISSUES. // FIX THIS (DO THE JOIN) WHEN UNION TYPES APPEAR! --- old/src/share/vm/opto/library_call.cpp 2014-03-20 12:32:00.414634257 +0100 +++ new/src/share/vm/opto/library_call.cpp 2014-03-20 12:32:00.089913253 +0100 @@ -4658,7 +4658,7 @@ ciKlass* src_k = NULL; if (!has_src) { - src_k = src_type->speculative_type(); + src_k = src_type->speculative_type_not_null(); if (src_k != NULL && src_k->is_array_klass()) { could_have_src = true; } @@ -4666,7 +4666,7 @@ ciKlass* dest_k = NULL; if (!has_dest) { - dest_k = dest_type->speculative_type(); + dest_k = dest_type->speculative_type_not_null(); if (dest_k != NULL && dest_k->is_array_klass()) { could_have_dest = true; } @@ -4738,13 +4738,13 @@ ciKlass* src_k = top_src->klass(); ciKlass* dest_k = top_dest->klass(); if (!src_spec) { - src_k = src_type->speculative_type(); + src_k = src_type->speculative_type_not_null(); if (src_k != NULL && src_k->is_array_klass()) { could_have_src = true; } } if (!dest_spec) { - dest_k = dest_type->speculative_type(); + dest_k = dest_type->speculative_type_not_null(); if (dest_k != NULL && dest_k->is_array_klass()) { could_have_dest = true; } --- old/src/share/vm/opto/doCall.cpp 2014-03-20 12:32:00.476489717 +0100 +++ new/src/share/vm/opto/doCall.cpp 2014-03-20 12:32:00.204932351 +0100 @@ -631,13 +631,7 @@ } BasicType ct = ctype->basic_type(); if (ct == T_OBJECT || ct == T_ARRAY) { - ciKlass* better_type = method()->return_profiled_type(bci()); - if (UseTypeSpeculation && better_type != NULL) { - // If profiling reports a single type for the return value, - // feed it to the type system so it can propagate it as a - // speculative type - record_profile_for_speculation(stack(sp()-1), better_type); - } + record_profiled_return_for_speculation(); } } --- old/src/share/vm/opto/type.cpp 2014-03-20 12:32:00.565557946 +0100 +++ new/src/share/vm/opto/type.cpp 2014-03-20 12:32:00.148370873 +0100 @@ -350,9 +350,9 @@ floop[1] = TypeInt::INT; TypeTuple::LOOPBODY = TypeTuple::make( 2, floop ); - TypePtr::NULL_PTR= TypePtr::make( AnyPtr, TypePtr::Null, 0 ); - TypePtr::NOTNULL = TypePtr::make( AnyPtr, TypePtr::NotNull, OffsetBot ); - TypePtr::BOTTOM = TypePtr::make( AnyPtr, TypePtr::BotPTR, OffsetBot ); + TypePtr::NULL_PTR= TypePtr::make(AnyPtr, TypePtr::Null, 0); + TypePtr::NOTNULL = TypePtr::make(AnyPtr, TypePtr::NotNull, OffsetBot); + TypePtr::BOTTOM = TypePtr::make(AnyPtr, TypePtr::BotPTR, OffsetBot); TypeRawPtr::BOTTOM = TypeRawPtr::make( TypePtr::BotPTR ); TypeRawPtr::NOTNULL= TypeRawPtr::make( TypePtr::NotNull ); @@ -372,7 +372,7 @@ false, 0, oopDesc::mark_offset_in_bytes()); TypeInstPtr::KLASS = TypeInstPtr::make(TypePtr::BotPTR, current->env()->Object_klass(), false, 0, oopDesc::klass_offset_in_bytes()); - TypeOopPtr::BOTTOM = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot, NULL); + TypeOopPtr::BOTTOM = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot); TypeMetadataPtr::BOTTOM = TypeMetadataPtr::make(TypePtr::BotPTR, NULL, OffsetBot); @@ -620,8 +620,8 @@ return true; } // Now check the speculative parts as well - const TypeOopPtr* this_spec = isa_oopptr() != NULL ? isa_oopptr()->speculative() : NULL; - const TypeOopPtr* t_spec = t->isa_oopptr() != NULL ? t->isa_oopptr()->speculative() : NULL; + const TypePtr* this_spec = isa_ptr() != NULL ? is_ptr()->speculative() : NULL; + const TypePtr* t_spec = t->isa_ptr() != NULL ? t->is_ptr()->speculative() : NULL; if (this_spec != NULL && t_spec != NULL) { if (this_spec->interface_vs_oop_helper(t_spec)) { return true; @@ -1975,6 +1975,25 @@ return make(_elem->remove_speculative(), _size, _stable); } +/** + * Return same type with cleaned up speculative part of element + */ +const Type* TypeAry::cleanup_speculative() const { + return make(_elem->cleanup_speculative(), _size, _stable); +} + +/** + * Return same type but with a different inline depth (used for speculation) + * + * @param depth depth to meet with + */ +const TypePtr* TypePtr::with_inline_depth(int depth) const { + if (!UseInlineDepthForSpeculativeTypes) { + return this; + } + return make(AnyPtr, _ptr, _offset, _speculative, depth); +} + //----------------------interface_vs_oop--------------------------------------- #ifdef ASSERT bool TypeAry::interface_vs_oop(const Type *t) const { @@ -2179,15 +2198,15 @@ }; //------------------------------make------------------------------------------- -const TypePtr *TypePtr::make( TYPES t, enum PTR ptr, int offset ) { - return (TypePtr*)(new TypePtr(t,ptr,offset))->hashcons(); +const TypePtr *TypePtr::make(TYPES t, enum PTR ptr, int offset, const TypePtr* speculative, int inline_depth) { + return (TypePtr*)(new TypePtr(t,ptr,offset, speculative, inline_depth))->hashcons(); } //------------------------------cast_to_ptr_type------------------------------- const Type *TypePtr::cast_to_ptr_type(PTR ptr) const { assert(_base == AnyPtr, "subclass must override cast_to_ptr_type"); if( ptr == _ptr ) return this; - return make(_base, ptr, _offset); + return make(_base, ptr, _offset, _speculative, _inline_depth); } //------------------------------get_con---------------------------------------- @@ -2198,7 +2217,29 @@ //------------------------------meet------------------------------------------- // Compute the MEET of two types. It returns a new Type object. -const Type *TypePtr::xmeet( const Type *t ) const { +const Type *TypePtr::xmeet(const Type *t) const { + const Type* res = xmeet_helper(t); + if (res->isa_ptr() == NULL) { + return res; + } + + const TypePtr* res_ptr = res->is_ptr(); + if (res_ptr->speculative() != NULL) { + // type->speculative() == NULL means that speculation is no better + // than type, i.e. type->speculative() == type. So there are 2 + // ways to represent the fact that we have no useful speculative + // data and we should use a single one to be able to test for + // equality between types. Check whether type->speculative() == + // type and set speculative to NULL if it is the case. + if (res_ptr->remove_speculative() == res_ptr->speculative()) { + return res_ptr->remove_speculative(); + } + } + + return res; +} + +const Type *TypePtr::xmeet_helper(const Type *t) const { // Perform a fast test for common case; meeting the same types together. if( this == t ) return this; // Meeting same type-rep? @@ -2221,7 +2262,9 @@ case AnyPtr: { // Meeting to AnyPtrs const TypePtr *tp = t->is_ptr(); - return make( AnyPtr, meet_ptr(tp->ptr()), meet_offset(tp->offset()) ); + const TypePtr* speculative = xmeet_speculative(tp); + int depth = meet_inline_depth(tp->inline_depth()); + return make(AnyPtr, meet_ptr(tp->ptr()), meet_offset(tp->offset()), speculative, depth); } case RawPtr: // For these, flip the call around to cut down case OopPtr: @@ -2260,7 +2303,7 @@ BotPTR, NotNull, Constant, Null, AnyNull, TopPTR }; const Type *TypePtr::xdual() const { - return new TypePtr( AnyPtr, dual_ptr(), dual_offset() ); + return new TypePtr(AnyPtr, dual_ptr(), dual_offset(), dual_speculative(), dual_inline_depth()); } //------------------------------xadd_offset------------------------------------ @@ -2281,20 +2324,245 @@ //------------------------------add_offset------------------------------------- const TypePtr *TypePtr::add_offset( intptr_t offset ) const { - return make( AnyPtr, _ptr, xadd_offset(offset) ); + return make(AnyPtr, _ptr, xadd_offset(offset), _speculative, _inline_depth); } //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypePtr::eq( const Type *t ) const { const TypePtr *a = (const TypePtr*)t; - return _ptr == a->ptr() && _offset == a->offset(); + return _ptr == a->ptr() && _offset == a->offset() && eq_speculative(a) && _inline_depth == a->_inline_depth; } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypePtr::hash(void) const { - return _ptr + _offset; + return _ptr + _offset + hash_speculative() + _inline_depth; +; +} + +/** + * Return same type without a speculative part + */ +const Type* TypePtr::remove_speculative() const { + if (_speculative == NULL) { + return this; + } + assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth"); + return make(AnyPtr, _ptr, _offset, NULL, _inline_depth); +} + +/** + * Return same type but drop speculative part if we know we won't use + * it + */ +const Type* TypePtr::cleanup_speculative() const { + if (speculative() == NULL) { + return this; + } + const Type* no_spec = remove_speculative(); + // If this is NULL_PTR then we don't need the speculative type + // (with_inline_depth in case the current type inline depth is + // InlineDepthTop) + if (no_spec == NULL_PTR->with_inline_depth(inline_depth())) { + return no_spec; + } + if (above_centerline(speculative()->ptr())) { + return no_spec; + } + const TypeOopPtr* spec_oopptr = speculative()->isa_oopptr(); + // If the speculative may be null and is an inexact klass then it + // doesn't help + if (speculative()->maybe_null() && (spec_oopptr == NULL || !spec_oopptr->klass_is_exact())) { + return no_spec; + } + return this; +} + +/** + * dual of the speculative part of the type + */ +const TypePtr* TypePtr::dual_speculative() const { + if (_speculative == NULL) { + return NULL; + } + return _speculative->dual()->is_ptr(); +} + +/** + * meet of the speculative parts of 2 types + * + * @param other type to meet with + */ +const TypePtr* TypePtr::xmeet_speculative(const TypePtr* other) const { + bool this_has_spec = (_speculative != NULL); + bool other_has_spec = (other->speculative() != NULL); + + if (!this_has_spec && !other_has_spec) { + return NULL; + } + + // If we are at a point where control flow meets and one branch has + // a speculative type and the other has not, we meet the speculative + // type of one branch with the actual type of the other. If the + // actual type is exact and the speculative is as well, then the + // result is a speculative type which is exact and we can continue + // speculation further. + const TypePtr* this_spec = _speculative; + const TypePtr* other_spec = other->speculative(); + + if (!this_has_spec) { + this_spec = this; + } + + if (!other_has_spec) { + other_spec = other; + } + + return this_spec->meet(other_spec)->is_ptr(); +} + +/** + * dual of the inline depth for this type (used for speculation) + */ +int TypePtr::dual_inline_depth() const { + return -inline_depth(); +} + +/** + * meet of 2 inline depths (used for speculation) + * + * @param depth depth to meet with + */ +int TypePtr::meet_inline_depth(int depth) const { + return MAX2(inline_depth(), depth); +} + +/** + * Are the speculative parts of 2 types equal? + * + * @param other type to compare this one to + */ +bool TypePtr::eq_speculative(const TypePtr* other) const { + if (_speculative == NULL || other->speculative() == NULL) { + return _speculative == other->speculative(); + } + + if (_speculative->base() != other->speculative()->base()) { + return false; + } + + return _speculative->eq(other->speculative()); +} + +/** + * Hash of the speculative part of the type + */ +int TypePtr::hash_speculative() const { + if (_speculative == NULL) { + return 0; + } + + return _speculative->hash(); +} + +/** + * add offset to the speculative part of the type + * + * @param offset offset to add + */ +const TypePtr* TypePtr::add_offset_speculative(intptr_t offset) const { + if (_speculative == NULL) { + return NULL; + } + return _speculative->add_offset(offset)->is_ptr(); +} + +/** + * return exact klass from the speculative type if there's one + */ +ciKlass* TypePtr::speculative_type() const { + if (_speculative != NULL && _speculative->isa_oopptr()) { + const TypeOopPtr* speculative = _speculative->join(this)->is_oopptr(); + if (speculative->klass_is_exact()) { + return speculative->klass(); + } + } + return NULL; +} + +/** + * return true if speculative type may be null + */ +bool TypePtr::speculative_maybe_null() const { + if (_speculative != NULL) { + const TypePtr* speculative = _speculative->join(this)->is_ptr(); + return speculative->maybe_null(); + } + return true; +} + +/** + * Same as TypePtr::speculative_type() but return the klass only if + * the speculative tells us is not null + */ +ciKlass* TypePtr::speculative_type_not_null() const { + if (speculative_maybe_null()) { + return NULL; + } + return speculative_type(); +} + +/** + * Check whether new profiling would improve speculative type + * + * @param exact_kls class from profiling + * @param inline_depth inlining depth of profile point + * + * @return true if type profile is valuable + */ +bool TypePtr::would_improve_type(ciKlass* exact_kls, int inline_depth) const { + // no profiling? + if (exact_kls == NULL) { + return false; + } + // no speculative type or non exact speculative type? + if (speculative_type() == NULL) { + return true; + } + // If the node already has an exact speculative type keep it, + // unless it was provided by profiling that is at a deeper + // inlining level. Profiling at a higher inlining depth is + // expected to be less accurate. + if (_speculative->inline_depth() == InlineDepthBottom) { + return false; + } + assert(_speculative->inline_depth() != InlineDepthTop, "can't do the comparison"); + return inline_depth < _speculative->inline_depth(); +} + +/** + * Check whether new profiling would improve ptr (= tells us it is non + * null) + * + * @param maybe_null true if profiling tells the ptr may be null + * + * @return true if ptr profile is valuable + */ +bool TypePtr::would_improve_ptr(bool maybe_null) const { + // profiling doesn't tell us anything useful + if (maybe_null) { + return false; + } + // We already know this is not be null + if (!this->maybe_null()) { + return false; + } + // We already know the speculative type cannot be null + if (!speculative_maybe_null()) { + return false; + } + return true; } //------------------------------dump2------------------------------------------ @@ -2309,6 +2577,32 @@ if( _offset == OffsetTop ) st->print("+top"); else if( _offset == OffsetBot ) st->print("+bot"); else if( _offset ) st->print("+%d", _offset); + dump_inline_depth(st); + dump_speculative(st); +} + +/** + *dump the speculative part of the type + */ +void TypePtr::dump_speculative(outputStream *st) const { + if (_speculative != NULL) { + st->print(" (speculative="); + _speculative->dump_on(st); + st->print(")"); + } +} + +/** + *dump the inline depth of the type + */ +void TypePtr::dump_inline_depth(outputStream *st) const { + if (_inline_depth != InlineDepthBottom) { + if (_inline_depth == InlineDepthTop) { + st->print(" (inline_depth=InlineDepthTop)"); + } else { + st->print(" (inline_depth=%d)", _inline_depth); + } + } } #endif @@ -2399,7 +2693,7 @@ case TypePtr::Null: if( _ptr == TypePtr::TopPTR ) return t; return TypeRawPtr::BOTTOM; - case TypePtr::NotNull: return TypePtr::make( AnyPtr, meet_ptr(TypePtr::NotNull), tp->meet_offset(0) ); + case TypePtr::NotNull: return TypePtr::make(AnyPtr, meet_ptr(TypePtr::NotNull), tp->meet_offset(0), tp->speculative(), tp->inline_depth()); case TypePtr::AnyNull: if( _ptr == TypePtr::Constant) return this; return make( meet_ptr(TypePtr::AnyNull) ); @@ -2463,16 +2757,15 @@ const TypeOopPtr *TypeOopPtr::BOTTOM; //------------------------------TypeOopPtr------------------------------------- -TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) - : TypePtr(t, ptr, offset), +TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, + int instance_id, const TypePtr* speculative, int inline_depth) + : TypePtr(t, ptr, offset, speculative, inline_depth), _const_oop(o), _klass(k), _klass_is_exact(xk), _is_ptr_to_narrowoop(false), _is_ptr_to_narrowklass(false), _is_ptr_to_boxed_value(false), - _instance_id(instance_id), - _speculative(speculative), - _inline_depth(inline_depth){ + _instance_id(instance_id) { if (Compile::current()->eliminate_boxing() && (t == InstPtr) && (offset > 0) && xk && (k != 0) && k->is_instance_klass()) { _is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset); @@ -2538,8 +2831,8 @@ } //------------------------------make------------------------------------------- -const TypeOopPtr *TypeOopPtr::make(PTR ptr, - int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) { +const TypeOopPtr *TypeOopPtr::make(PTR ptr, int offset, int instance_id, + const TypePtr* speculative, int inline_depth) { assert(ptr != Constant, "no constant generic pointers"); ciKlass* k = Compile::current()->env()->Object_klass(); bool xk = false; @@ -2582,28 +2875,6 @@ return TypeKlassPtr::make(xk? Constant: NotNull, k, 0); } -const Type *TypeOopPtr::xmeet(const Type *t) const { - const Type* res = xmeet_helper(t); - if (res->isa_oopptr() == NULL) { - return res; - } - - const TypeOopPtr* res_oopptr = res->is_oopptr(); - if (res_oopptr->speculative() != NULL) { - // type->speculative() == NULL means that speculation is no better - // than type, i.e. type->speculative() == type. So there are 2 - // ways to represent the fact that we have no useful speculative - // data and we should use a single one to be able to test for - // equality between types. Check whether type->speculative() == - // type and set speculative to NULL if it is the case. - if (res_oopptr->remove_speculative() == res_oopptr->speculative()) { - return res_oopptr->remove_speculative(); - } - } - - return res; -} - //------------------------------meet------------------------------------------- // Compute the MEET of two types. It returns a new Type object. const Type *TypeOopPtr::xmeet_helper(const Type *t) const { @@ -2641,19 +2912,20 @@ const TypePtr *tp = t->is_ptr(); int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); + const TypePtr* speculative = xmeet_speculative(tp); + int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) { case Null: - if (ptr == Null) return TypePtr::make(AnyPtr, ptr, offset); + if (ptr == Null) return TypePtr::make(AnyPtr, ptr, offset, speculative, depth); // else fall through: case TopPTR: case AnyNull: { int instance_id = meet_instance_id(InstanceTop); - const TypeOopPtr* speculative = _speculative; - return make(ptr, offset, instance_id, speculative, _inline_depth); + return make(ptr, offset, instance_id, speculative, depth); } case BotPTR: case NotNull: - return TypePtr::make(AnyPtr, ptr, offset); + return TypePtr::make(AnyPtr, ptr, offset, speculative, depth); default: typerr(t); } } @@ -2661,7 +2933,7 @@ case OopPtr: { // Meeting to other OopPtrs const TypeOopPtr *tp = t->is_oopptr(); int instance_id = meet_instance_id(tp->instance_id()); - const TypeOopPtr* speculative = xmeet_speculative(tp); + const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative, depth); } @@ -2859,9 +3131,7 @@ bool TypeOopPtr::eq( const Type *t ) const { const TypeOopPtr *a = (const TypeOopPtr*)t; if (_klass_is_exact != a->_klass_is_exact || - _instance_id != a->_instance_id || - !eq_speculative(a) || - _inline_depth != a->_inline_depth) return false; + _instance_id != a->_instance_id) return false; ciObject* one = const_oop(); ciObject* two = a->const_oop(); if (one == NULL || two == NULL) { @@ -2878,8 +3148,6 @@ (const_oop() ? const_oop()->hash() : 0) + _klass_is_exact + _instance_id + - hash_speculative() + - _inline_depth + TypePtr::hash(); } @@ -2903,27 +3171,6 @@ dump_inline_depth(st); dump_speculative(st); } - -/** - *dump the speculative part of the type - */ -void TypeOopPtr::dump_speculative(outputStream *st) const { - if (_speculative != NULL) { - st->print(" (speculative="); - _speculative->dump_on(st); - st->print(")"); - } -} - -void TypeOopPtr::dump_inline_depth(outputStream *st) const { - if (_inline_depth != InlineDepthBottom) { - if (_inline_depth == InlineDepthTop) { - st->print(" (inline_depth=InlineDepthTop)"); - } else { - st->print(" (inline_depth=%d)", _inline_depth); - } - } -} #endif //------------------------------singleton-------------------------------------- @@ -2952,47 +3199,28 @@ } /** - * Return same type but with a different inline depth (used for speculation) - * - * @param depth depth to meet with + * Return same type but drop speculative part if we know we won't use + * it */ -const TypeOopPtr* TypeOopPtr::with_inline_depth(int depth) const { - if (!UseInlineDepthForSpeculativeTypes) { - return this; +const Type* TypeOopPtr::cleanup_speculative() const { + // If the klass is exact and the ptr is not null then there's + // nothing that the speculative type can help us with + if (klass_is_exact() && !maybe_null()) { + return remove_speculative(); } - return make(_ptr, _offset, _instance_id, _speculative, depth); + return TypePtr::cleanup_speculative(); } /** - * Check whether new profiling would improve speculative type - * - * @param exact_kls class from profiling - * @param inline_depth inlining depth of profile point + * Return same type but with a different inline depth (used for speculation) * - * @return true if type profile is valuable + * @param depth depth to meet with */ -bool TypeOopPtr::would_improve_type(ciKlass* exact_kls, int inline_depth) const { - // no way to improve an already exact type - if (klass_is_exact()) { - return false; - } - // no profiling? - if (exact_kls == NULL) { - return false; - } - // no speculative type or non exact speculative type? - if (speculative_type() == NULL) { - return true; - } - // If the node already has an exact speculative type keep it, - // unless it was provided by profiling that is at a deeper - // inlining level. Profiling at a higher inlining depth is - // expected to be less accurate. - if (_speculative->inline_depth() == InlineDepthBottom) { - return false; +const TypePtr* TypeOopPtr::with_inline_depth(int depth) const { + if (!UseInlineDepthForSpeculativeTypes) { + return this; } - assert(_speculative->inline_depth() != InlineDepthTop, "can't do the comparison"); - return inline_depth < _speculative->inline_depth(); + return make(_ptr, _offset, _instance_id, _speculative, depth); } //------------------------------meet_instance_id-------------------------------- @@ -3013,102 +3241,19 @@ } /** - * meet of the speculative parts of 2 types - * - * @param other type to meet with - */ -const TypeOopPtr* TypeOopPtr::xmeet_speculative(const TypeOopPtr* other) const { - bool this_has_spec = (_speculative != NULL); - bool other_has_spec = (other->speculative() != NULL); - - if (!this_has_spec && !other_has_spec) { - return NULL; - } - - // If we are at a point where control flow meets and one branch has - // a speculative type and the other has not, we meet the speculative - // type of one branch with the actual type of the other. If the - // actual type is exact and the speculative is as well, then the - // result is a speculative type which is exact and we can continue - // speculation further. - const TypeOopPtr* this_spec = _speculative; - const TypeOopPtr* other_spec = other->speculative(); - - if (!this_has_spec) { - this_spec = this; - } - - if (!other_has_spec) { - other_spec = other; - } - - return this_spec->meet_speculative(other_spec)->is_oopptr(); -} - -/** - * dual of the speculative part of the type - */ -const TypeOopPtr* TypeOopPtr::dual_speculative() const { - if (_speculative == NULL) { - return NULL; - } - return _speculative->dual()->is_oopptr(); -} - -/** - * add offset to the speculative part of the type + * Check whether new profiling would improve speculative type * - * @param offset offset to add - */ -const TypeOopPtr* TypeOopPtr::add_offset_speculative(intptr_t offset) const { - if (_speculative == NULL) { - return NULL; - } - return _speculative->add_offset(offset)->is_oopptr(); -} - -/** - * Are the speculative parts of 2 types equal? + * @param exact_kls class from profiling + * @param inline_depth inlining depth of profile point * - * @param other type to compare this one to + * @return true if type profile is valuable */ -bool TypeOopPtr::eq_speculative(const TypeOopPtr* other) const { - if (_speculative == NULL || other->speculative() == NULL) { - return _speculative == other->speculative(); - } - - if (_speculative->base() != other->speculative()->base()) { +bool TypeOopPtr::would_improve_type(ciKlass* exact_kls, int inline_depth) const { + // no way to improve an already exact type + if (klass_is_exact()) { return false; } - - return _speculative->eq(other->speculative()); -} - -/** - * Hash of the speculative part of the type - */ -int TypeOopPtr::hash_speculative() const { - if (_speculative == NULL) { - return 0; - } - - return _speculative->hash(); -} - -/** - * dual of the inline depth for this type (used for speculation) - */ -int TypeOopPtr::dual_inline_depth() const { - return -inline_depth(); -} - -/** - * meet of 2 inline depth (used for speculation) - * - * @param depth depth to meet with - */ -int TypeOopPtr::meet_inline_depth(int depth) const { - return MAX2(inline_depth(), depth); + return TypePtr::would_improve_type(exact_kls, inline_depth); } //============================================================================= @@ -3120,8 +3265,10 @@ const TypeInstPtr *TypeInstPtr::KLASS; //------------------------------TypeInstPtr------------------------------------- -TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypeOopPtr* speculative, int inline_depth) - : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth), _name(k->name()) { +TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, + int instance_id, const TypePtr* speculative, int inline_depth) + : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth), + _name(k->name()) { assert(k != NULL && (k->is_loaded() || o == NULL), "cannot have constants with non-loaded klass"); @@ -3134,7 +3281,7 @@ ciObject* o, int offset, int instance_id, - const TypeOopPtr* speculative, + const TypePtr* speculative, int inline_depth) { assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance"); // Either const_oop() is NULL or else ptr is Constant @@ -3217,7 +3364,7 @@ int off = meet_offset(tinst->offset()); PTR ptr = meet_ptr(tinst->ptr()); int instance_id = meet_instance_id(tinst->instance_id()); - const TypeOopPtr* speculative = xmeet_speculative(tinst); + const TypePtr* speculative = xmeet_speculative(tinst); int depth = meet_inline_depth(tinst->inline_depth()); const TypeInstPtr *loaded = is_loaded() ? this : tinst; @@ -3295,7 +3442,7 @@ int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); - const TypeOopPtr* speculative = xmeet_speculative(tp); + const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (ptr) { case TopPTR: @@ -3346,7 +3493,7 @@ case TopPTR: case AnyNull: { int instance_id = meet_instance_id(InstanceTop); - const TypeOopPtr* speculative = xmeet_speculative(tp); + const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); return make(ptr, klass(), klass_is_exact(), (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, depth); @@ -3354,7 +3501,7 @@ case NotNull: case BotPTR: { int instance_id = meet_instance_id(tp->instance_id()); - const TypeOopPtr* speculative = xmeet_speculative(tp); + const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth); } @@ -3367,20 +3514,21 @@ const TypePtr *tp = t->is_ptr(); int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); + int instance_id = meet_instance_id(InstanceTop); + const TypePtr* speculative = xmeet_speculative(tp); + int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) { case Null: - if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset); + if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, speculative, depth); // else fall through to AnyNull case TopPTR: case AnyNull: { - int instance_id = meet_instance_id(InstanceTop); - const TypeOopPtr* speculative = _speculative; return make(ptr, klass(), klass_is_exact(), - (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, _inline_depth); + (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, depth); } case NotNull: case BotPTR: - return TypePtr::make(AnyPtr, ptr, offset); + return TypePtr::make(AnyPtr, ptr, offset, speculative,depth); default: typerr(t); } } @@ -3407,7 +3555,7 @@ int off = meet_offset( tinst->offset() ); PTR ptr = meet_ptr( tinst->ptr() ); int instance_id = meet_instance_id(tinst->instance_id()); - const TypeOopPtr* speculative = xmeet_speculative(tinst); + const TypePtr* speculative = xmeet_speculative(tinst); int depth = meet_inline_depth(tinst->inline_depth()); // Check for easy case; klasses are equal (and perhaps not loaded!) @@ -3563,6 +3711,7 @@ // class hierarchy - which means we have to fall to at least NotNull. if( ptr == TopPTR || ptr == AnyNull || ptr == Constant ) ptr = NotNull; + instance_id = InstanceBot; // Now we find the LCA of Java classes @@ -3655,7 +3804,8 @@ //------------------------------add_offset------------------------------------- const TypePtr *TypeInstPtr::add_offset(intptr_t offset) const { - return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset), _instance_id, add_offset_speculative(offset)); + return make(_ptr, klass(), klass_is_exact(), const_oop(), xadd_offset(offset), + _instance_id, add_offset_speculative(offset), _inline_depth); } const Type *TypeInstPtr::remove_speculative() const { @@ -3663,10 +3813,11 @@ return this; } assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth"); - return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL, _inline_depth); + return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, + _instance_id, NULL, _inline_depth); } -const TypeOopPtr *TypeInstPtr::with_inline_depth(int depth) const { +const TypePtr *TypeInstPtr::with_inline_depth(int depth) const { if (!UseInlineDepthForSpeculativeTypes) { return this; } @@ -3687,7 +3838,8 @@ const TypeAryPtr *TypeAryPtr::DOUBLES; //------------------------------make------------------------------------------- -const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) { +const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, + int instance_id, const TypePtr* speculative, int inline_depth) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); if (!xk) xk = ary->ary_must_be_exact(); @@ -3697,7 +3849,9 @@ } //------------------------------make------------------------------------------- -const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth, bool is_autobox_cache) { +const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, + int instance_id, const TypePtr* speculative, int inline_depth, + bool is_autobox_cache) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" ); @@ -3807,7 +3961,7 @@ const TypeAry* new_ary = TypeAry::make(elem, size(), stable); - return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id); + return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth); } //-----------------------------stable_dimension-------------------------------- @@ -3868,18 +4022,17 @@ int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int depth = meet_inline_depth(tp->inline_depth()); + const TypePtr* speculative = xmeet_speculative(tp); switch (tp->ptr()) { case TopPTR: case AnyNull: { int instance_id = meet_instance_id(InstanceTop); - const TypeOopPtr* speculative = xmeet_speculative(tp); return make(ptr, (ptr == Constant ? const_oop() : NULL), _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } case BotPTR: case NotNull: { int instance_id = meet_instance_id(tp->instance_id()); - const TypeOopPtr* speculative = xmeet_speculative(tp); return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth); } default: ShouldNotReachHere(); @@ -3891,20 +4044,21 @@ const TypePtr *tp = t->is_ptr(); int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); + const TypePtr* speculative = xmeet_speculative(tp); + int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) { case TopPTR: return this; case BotPTR: case NotNull: - return TypePtr::make(AnyPtr, ptr, offset); + return TypePtr::make(AnyPtr, ptr, offset, speculative, depth); case Null: - if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset); + if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, speculative, depth); // else fall through to AnyNull case AnyNull: { int instance_id = meet_instance_id(InstanceTop); - const TypeOopPtr* speculative = _speculative; return make(ptr, (ptr == Constant ? const_oop() : NULL), - _ary, _klass, _klass_is_exact, offset, instance_id, speculative, _inline_depth); + _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } default: ShouldNotReachHere(); } @@ -3920,7 +4074,7 @@ const TypeAry *tary = _ary->meet_speculative(tap->_ary)->is_ary(); PTR ptr = meet_ptr(tap->ptr()); int instance_id = meet_instance_id(tap->instance_id()); - const TypeOopPtr* speculative = xmeet_speculative(tap); + const TypePtr* speculative = xmeet_speculative(tap); int depth = meet_inline_depth(tap->inline_depth()); ciKlass* lazy_klass = NULL; if (tary->_elem->isa_int()) { @@ -3949,7 +4103,7 @@ // 'this' is exact and super or unrelated: (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) { tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable); - return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot); + return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot, speculative, depth); } bool xk = false; @@ -4001,7 +4155,7 @@ int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); - const TypeOopPtr* speculative = xmeet_speculative(tp); + const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (ptr) { case TopPTR: @@ -4125,7 +4279,7 @@ return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL, _inline_depth); } -const TypeOopPtr *TypeAryPtr::with_inline_depth(int depth) const { +const TypePtr *TypeAryPtr::with_inline_depth(int depth) const { if (!UseInlineDepthForSpeculativeTypes) { return this; } @@ -4250,6 +4404,13 @@ return (const TypeNarrowOop*)(new TypeNarrowOop(type))->hashcons(); } +const Type* TypeNarrowOop::remove_speculative() const { + return make(_ptrtype->remove_speculative()->is_ptr()); +} + +const Type* TypeNarrowOop::cleanup_speculative() const { + return make(_ptrtype->cleanup_speculative()->is_ptr()); +} #ifndef PRODUCT void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const { @@ -4376,7 +4537,7 @@ PTR ptr = meet_ptr(tp->ptr()); switch (tp->ptr()) { case Null: - if (ptr == Null) return TypePtr::make(AnyPtr, ptr, offset); + if (ptr == Null) return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); // else fall through: case TopPTR: case AnyNull: { @@ -4384,7 +4545,7 @@ } case BotPTR: case NotNull: - return TypePtr::make(AnyPtr, ptr, offset); + return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); default: typerr(t); } } @@ -4698,12 +4859,12 @@ case TopPTR: return this; case Null: - if( ptr == Null ) return TypePtr::make( AnyPtr, ptr, offset ); + if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); case AnyNull: return make( ptr, klass(), offset ); case BotPTR: case NotNull: - return TypePtr::make(AnyPtr, ptr, offset); + return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); default: typerr(t); } } --- old/src/share/vm/opto/parse2.cpp 2014-03-20 12:32:00.545207325 +0100 +++ new/src/share/vm/opto/parse2.cpp 2014-03-20 12:32:00.121477247 +0100 @@ -1288,7 +1288,7 @@ (jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) { TypeNode* ccast = new (C) CheckCastPPNode(control(), obj, tboth); const Type* tcc = ccast->as_Type()->type(); - assert(tcc != obj_type && tcc->higher_equal_speculative(obj_type), "must improve"); + assert(tcc != obj_type && tcc->higher_equal(obj_type), "must improve"); // Delay transform() call to allow recovery of pre-cast value // at the control merge. _gvn.set_type_bottom(ccast); @@ -1352,7 +1352,7 @@ if (ccast != NULL) { const Type* tcc = ccast->as_Type()->type(); - assert(tcc != tval && tcc->higher_equal_speculative(tval), "must improve"); + assert(tcc != tval && tcc->higher_equal(tval), "must improve"); // Delay transform() call to allow recovery of pre-cast value // at the control merge. ccast->set_req(0, control()); @@ -1393,7 +1393,7 @@ Node* addp = load_klass->in(2); Node* obj = addp->in(AddPNode::Address); const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr(); - if (obj_type->speculative_type() != NULL) { + if (obj_type->speculative_type_not_null() != NULL) { ciKlass* k = obj_type->speculative_type(); inc_sp(2); obj = maybe_cast_profiled_obj(obj, k); @@ -2277,6 +2277,14 @@ maybe_add_safepoint(iter().get_dest()); a = null(); b = pop(); + if (!_gvn.type(b)->speculative_maybe_null() && + !too_many_traps(Deoptimization::Reason_speculate_null_check)) { + inc_sp(1); + Node* null_ctl = top(); + b = null_check_oop(b, &null_ctl, true, true, true); + assert(null_ctl->is_top(), "no null control here"); + dec_sp(1); + } c = _gvn.transform( new (C) CmpPNode(b, a) ); do_ifnull(btest, c); break; --- old/src/share/vm/opto/graphKit.cpp 2014-03-20 12:32:00.513934282 +0100 +++ new/src/share/vm/opto/graphKit.cpp 2014-03-20 12:32:00.174047683 +0100 @@ -612,10 +612,10 @@ // Usual case: Bail to interpreter. // Reserve the right to recompile if we haven't seen anything yet. - assert(!Deoptimization::reason_is_speculate(reason), "unsupported"); + ciMethod* m = Deoptimization::reason_is_speculate(reason) ? C->method() : NULL; Deoptimization::DeoptAction action = Deoptimization::Action_maybe_recompile; if (treat_throw_as_hot - && (method()->method_data()->trap_recompiled_at(bci(), NULL) + && (method()->method_data()->trap_recompiled_at(bci(), m) || C->too_many_traps(reason))) { // We cannot afford to take more traps here. Suffer in the interpreter. if (C->log() != NULL) @@ -1170,7 +1170,8 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, // optional arguments for variations: bool assert_null, - Node* *null_control) { + Node* *null_control, + bool speculative) { assert(!assert_null || null_control == NULL, "not both at once"); if (stopped()) return top(); if (!GenerateCompilerNullChecks && !assert_null && null_control == NULL) { @@ -1280,13 +1281,13 @@ // Branch to failure if null float ok_prob = PROB_MAX; // a priori estimate: nulls never happen Deoptimization::DeoptReason reason; - if (assert_null) + if (assert_null) { reason = Deoptimization::Reason_null_assert; - else if (type == T_OBJECT) - reason = Deoptimization::Reason_null_check; - else + } else if (type == T_OBJECT) { + reason = speculative ? Deoptimization::Reason_speculate_null_check : Deoptimization::Reason_null_check; + } else { reason = Deoptimization::Reason_div0_check; - + } // %%% Since Reason_unhandled is not recorded on a per-bytecode basis, // ciMethodData::has_trap_at will return a conservative -1 if any // must-be-null assertion has failed. This could cause performance @@ -2109,21 +2110,36 @@ * * @param n node that the type applies to * @param exact_kls type from profiling + * @param maybe_null did profiling see null? * * @return node with improved type */ -Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls) { +Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls, bool maybe_null) { const Type* current_type = _gvn.type(n); assert(UseTypeSpeculation, "type speculation must be on"); - const TypeOopPtr* speculative = current_type->speculative(); + const TypePtr* speculative = current_type->speculative(); + // Should the klass from the profile be recorded in the speculative type? if (current_type->would_improve_type(exact_kls, jvms()->depth())) { const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls); const TypeOopPtr* xtype = tklass->as_instance_type(); assert(xtype->klass_is_exact(), "Should be exact"); + // Any reason to believe n is not null (from this profiling or a previous one)? + const TypePtr* ptr = (maybe_null && current_type->speculative_maybe_null()) ? TypePtr::BOTTOM : TypePtr::NOTNULL; // record the new speculative type's depth - speculative = xtype->with_inline_depth(jvms()->depth()); + speculative = xtype->cast_to_ptr_type(ptr->ptr())->is_ptr(); + speculative = speculative->with_inline_depth(jvms()->depth()); + } else if (current_type->would_improve_ptr(maybe_null)) { + // Profiling report that null was never seen so we can change the + // speculative type to non null ptr. + assert(!maybe_null, "nothing to improve"); + if (speculative == NULL) { + speculative = TypePtr::NOTNULL; + } else { + const TypePtr* ptr = TypePtr::NOTNULL; + speculative = speculative->cast_to_ptr_type(ptr->ptr())->is_ptr(); + } } if (speculative != current_type->speculative()) { @@ -2156,7 +2172,15 @@ return n; } ciKlass* exact_kls = profile_has_unique_klass(); - return record_profile_for_speculation(n, exact_kls); + bool maybe_null = true; + if (java_bc() == Bytecodes::_checkcast || + java_bc() == Bytecodes::_instanceof || + java_bc() == Bytecodes::_aastore) { + ciProfileData* data = method()->method_data()->bci_to_data(bci()); + bool maybe_null = data == NULL ? true : data->as_BitData()->null_seen(); + } + return record_profile_for_speculation(n, exact_kls, maybe_null); + return n; } /** @@ -2176,9 +2200,10 @@ for (int j = skip, i = 0; j < nargs && i < TypeProfileArgsLimit; j++) { const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms); if (targ->basic_type() == T_OBJECT || targ->basic_type() == T_ARRAY) { - ciKlass* better_type = method()->argument_profiled_type(bci(), i); - if (better_type != NULL) { - record_profile_for_speculation(argument(j), better_type); + bool maybe_null = true; + ciKlass* better_type = NULL; + if (method()->argument_profiled_type(bci(), i, better_type, maybe_null)) { + record_profile_for_speculation(argument(j), better_type, maybe_null); } i++; } @@ -2195,15 +2220,34 @@ } for (int i = 0, j = 0; i < method()->arg_size() ; i++) { if (_gvn.type(local(i))->isa_oopptr()) { - ciKlass* better_type = method()->parameter_profiled_type(j); - if (better_type != NULL) { - record_profile_for_speculation(local(i), better_type); + bool maybe_null = true; + ciKlass* better_type = NULL; + if (method()->parameter_profiled_type(j, better_type, maybe_null)) { + record_profile_for_speculation(local(i), better_type, maybe_null); } j++; } } } +/** + * Record profiling data from return value profiling at an invoke with + * the type system so that it can propagate it (speculation) + */ +void GraphKit::record_profiled_return_for_speculation() { + if (!UseTypeSpeculation) { + return; + } + bool maybe_null = true; + ciKlass* better_type = NULL; + if (method()->return_profiled_type(bci(), better_type, maybe_null)) { + // If profiling reports a single type for the return value, + // feed it to the type system so it can propagate it as a + // speculative type + record_profile_for_speculation(stack(sp()-1), better_type, maybe_null); + } +} + void GraphKit::round_double_result(ciMethod* dest_method) { // A non-strict method may return a double value which has an extended // exponent, but this must not be visible in a caller which is 'strict' @@ -2283,10 +2327,12 @@ // Null check oop. Set null-path control into Region in slot 3. // Make a cast-not-nullness use the other not-null control. Return cast. Node* GraphKit::null_check_oop(Node* value, Node* *null_control, - bool never_see_null, bool safe_for_replace) { + bool never_see_null, + bool safe_for_replace, + bool speculative) { // Initial NULL check taken path (*null_control) = top(); - Node* cast = null_check_common(value, T_OBJECT, false, null_control); + Node* cast = null_check_common(value, T_OBJECT, false, null_control, speculative); // Generate uncommon_trap: if (never_see_null && (*null_control) != top()) { @@ -2297,7 +2343,8 @@ PreserveJVMState pjvms(this); set_control(*null_control); replace_in_map(value, null()); - uncommon_trap(Deoptimization::Reason_null_check, + Deoptimization::DeoptReason reason = speculative ? Deoptimization::Reason_speculate_null_check : Deoptimization::Reason_null_check; + uncommon_trap(reason, Deoptimization::Action_make_not_entrant); (*null_control) = top(); // NULL path is dead } @@ -2721,11 +2768,16 @@ // recompile; the offending check will be recompiled to handle NULLs. // If we see several offending BCIs, then all checks in the // method will be recompiled. -bool GraphKit::seems_never_null(Node* obj, ciProfileData* data) { +bool GraphKit::seems_never_null(Node* obj, ciProfileData* data, bool& speculating) { + speculating = !_gvn.type(obj)->speculative_maybe_null(); + Deoptimization::DeoptReason reason = speculating ? Deoptimization::Reason_speculate_null_check : Deoptimization::Reason_null_check; if (UncommonNullCast // Cutout for this technique && obj != null() // And not the -Xcomp stupid case? - && !too_many_traps(Deoptimization::Reason_null_check) + && !too_many_traps(reason) ) { + if (speculating) { + return true; + } if (data == NULL) // Edge case: no mature data. Be optimistic here. return true; @@ -2735,6 +2787,7 @@ java_bc() == Bytecodes::_aastore, "MDO must collect null_seen bit here"); return !data->as_BitData()->null_seen(); } + speculating = false; return false; } @@ -2800,7 +2853,7 @@ // type == NULL if profiling tells us this object is always null if (type != NULL) { Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check; - Deoptimization::DeoptReason null_reason = Deoptimization::Reason_null_check; + Deoptimization::DeoptReason null_reason = Deoptimization::Reason_speculate_null_check; if (!too_many_traps(null_reason) && !too_many_traps(class_reason)) { Node* not_null_obj = NULL; @@ -2808,7 +2861,7 @@ // there's no need for a null check if (!not_null) { Node* null_ctl = top(); - not_null_obj = null_check_oop(obj, &null_ctl, true, true); + not_null_obj = null_check_oop(obj, &null_ctl, true, true, true); assert(null_ctl->is_top(), "no null control here"); } else { not_null_obj = obj; @@ -2856,12 +2909,13 @@ if (java_bc() == Bytecodes::_instanceof) { // Only for the bytecode data = method()->method_data()->bci_to_data(bci()); } + bool speculative_not_null = false; bool never_see_null = (ProfileDynamicTypes // aggressive use of profile - && seems_never_null(obj, data)); + && seems_never_null(obj, data, speculative_not_null)); // Null check; get casted pointer; set region slot 3 Node* null_ctl = top(); - Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace); + Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace, speculative_not_null); // If not_null_obj is dead, only null-path is taken if (stopped()) { // Doing instance-of on a NULL? @@ -2984,12 +3038,13 @@ C->set_has_split_ifs(true); // Has chance for split-if optimization // Use null-cast information if it is available + bool speculative_not_null = false; bool never_see_null = ((failure_control == NULL) // regular case only - && seems_never_null(obj, data)); + && seems_never_null(obj, data, speculative_not_null)); // Null check; get casted pointer; set region slot 3 Node* null_ctl = top(); - Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace); + Node* not_null_obj = null_check_oop(obj, &null_ctl, never_see_null, safe_for_replace, speculative_not_null); // If not_null_obj is dead, only null-path is taken if (stopped()) { // Doing instance-of on a NULL? --- old/src/share/vm/runtime/arguments.cpp 2014-03-20 12:32:03.464057444 +0100 +++ new/src/share/vm/runtime/arguments.cpp 2014-03-20 12:32:03.270952208 +0100 @@ -3796,10 +3796,6 @@ AlwaysIncrementalInline = false; } #endif - if (IncrementalInline && FLAG_IS_DEFAULT(MaxNodeLimit)) { - // incremental inlining: bump MaxNodeLimit - FLAG_SET_DEFAULT(MaxNodeLimit, (intx)75000); - } if (!UseTypeSpeculation && FLAG_IS_DEFAULT(TypeProfileLevel)) { // nothing to use the profiling, turn if off FLAG_SET_DEFAULT(TypeProfileLevel, 0); --- old/src/share/vm/runtime/deoptimization.hpp 2014-03-20 12:32:03.532391529 +0100 +++ new/src/share/vm/runtime/deoptimization.hpp 2014-03-20 12:32:03.340308914 +0100 @@ -60,6 +60,7 @@ Reason_predicate, // compiler generated predicate failed Reason_loop_limit_check, // compiler generated loop limits check failed Reason_speculate_class_check, // saw unexpected object class from type speculation + Reason_speculate_null_check, // saw unexpected null from type speculation Reason_LIMIT, // Note: Keep this enum in sync. with _trap_reason_name. Reason_RECORDED_LIMIT = Reason_bimorphic // some are not recorded per bc @@ -314,12 +315,14 @@ return Reason_null_check; // recorded per BCI as a null check else if (reason == Reason_speculate_class_check) return Reason_class_check; + else if (reason == Reason_speculate_null_check) + return Reason_null_check; else return Reason_none; } static bool reason_is_speculate(int reason) { - if (reason == Reason_speculate_class_check) { + if (reason == Reason_speculate_class_check || reason == Reason_speculate_null_check) { return true; } return false; --- old/src/share/vm/runtime/deoptimization.cpp 2014-03-20 12:32:03.535631917 +0100 +++ new/src/share/vm/runtime/deoptimization.cpp 2014-03-20 12:32:03.310227028 +0100 @@ -1826,7 +1826,8 @@ "age", "predicate", "loop_limit_check", - "speculate_class_check" + "speculate_class_check", + "speculate_null_check" }; const char* Deoptimization::_trap_action_name[Action_LIMIT] = { // Note: Keep this in sync. with enum DeoptAction. --- old/src/share/vm/opto/type.hpp 2014-03-20 12:32:03.715988637 +0100 +++ new/src/share/vm/opto/type.hpp 2014-03-20 12:32:03.499930740 +0100 @@ -224,7 +224,7 @@ } // Variant that keeps the speculative part of the types const Type *meet_speculative(const Type *t) const { - return meet_helper(t, true); + return meet_helper(t, true)->cleanup_speculative(); } // WIDEN: 'widens' for Ints and other range types virtual const Type *widen( const Type *old, const Type* limit ) const { return this; } @@ -247,7 +247,7 @@ } // Variant that keeps the speculative part of the types const Type *join_speculative(const Type *t) const { - return join_helper(t, true); + return join_helper(t, true)->cleanup_speculative(); } // Modified version of JOIN adapted to the needs Node::Value. @@ -259,7 +259,7 @@ } // Variant that keeps the speculative part of the types const Type *filter_speculative(const Type *kills) const { - return filter_helper(kills, true); + return filter_helper(kills, true)->cleanup_speculative(); } #ifdef ASSERT @@ -414,15 +414,18 @@ bool require_constant = false, bool is_autobox_cache = false); - // Speculative type. See TypeInstPtr - virtual const TypeOopPtr* speculative() const { return NULL; } - virtual ciKlass* speculative_type() const { return NULL; } + // Speculative type helper methods. See TypePtr. + virtual const TypePtr* speculative() const { return NULL; } + virtual ciKlass* speculative_type() const { return NULL; } + virtual ciKlass* speculative_type_not_null() const { return NULL; } + virtual bool speculative_maybe_null() const { return true; } + virtual const Type* remove_speculative() const { return this; } + virtual const Type* cleanup_speculative() const { return this; } + virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const { return exact_kls != NULL; } + virtual bool would_improve_ptr(bool maybe_null) const { return !maybe_null; } const Type* maybe_remove_speculative(bool include_speculative) const; - virtual const Type* remove_speculative() const { return this; } - virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const { - return exact_kls != NULL; - } + virtual bool maybe_null() const { return true; } private: // support arrays @@ -679,6 +682,7 @@ virtual const Type *xdual() const; // Compute dual right now. bool ary_must_be_exact() const; // true if arrays of such are never generic virtual const Type* remove_speculative() const; + virtual const Type* cleanup_speculative() const; #ifdef ASSERT // One type is interface, the other is oop virtual bool interface_vs_oop(const Type *t) const; @@ -761,13 +765,48 @@ public: enum PTR { TopPTR, AnyNull, Constant, Null, NotNull, BotPTR, lastPTR }; protected: - TypePtr( TYPES t, PTR ptr, int offset ) : Type(t), _ptr(ptr), _offset(offset) {} - virtual bool eq( const Type *t ) const; - virtual int hash() const; // Type specific hashing + TypePtr(TYPES t, PTR ptr, int offset, + const TypePtr* speculative = NULL, + int inline_depth = InlineDepthBottom) : + Type(t), _ptr(ptr), _offset(offset), _speculative(speculative), + _inline_depth(inline_depth) {} static const PTR ptr_meet[lastPTR][lastPTR]; static const PTR ptr_dual[lastPTR]; static const char * const ptr_msg[lastPTR]; + enum { + InlineDepthBottom = INT_MAX, + InlineDepthTop = -InlineDepthBottom + }; + + // Extra type information profiling gave us. We propagate it the + // same way the rest of the type info is propagated. If we want to + // use it, then we have to emit a guard: this part of the type is + // not something we know but something we speculate about the type. + const TypePtr* _speculative; + // For speculative types, we record at what inlining depth the + // profiling point that provided the data is. We want to favor + // profile data coming from outer scopes which are likely better for + // the current compilation. + int _inline_depth; + + // utility methods to work on the speculative part of the type + const TypePtr* dual_speculative() const; + const TypePtr* xmeet_speculative(const TypePtr* other) const; + bool eq_speculative(const TypePtr* other) const; + int hash_speculative() const; + const TypePtr* add_offset_speculative(intptr_t offset) const; +#ifndef PRODUCT + void dump_speculative(outputStream *st) const; +#endif + + // utility methods to work on the inline depth of the type + int dual_inline_depth() const; + int meet_inline_depth(int depth) const; +#ifndef PRODUCT + void dump_inline_depth(outputStream *st) const; +#endif + public: const int _offset; // Offset into oop, with TOP & BOT const PTR _ptr; // Pointer equivalence class @@ -775,7 +814,9 @@ const int offset() const { return _offset; } const PTR ptr() const { return _ptr; } - static const TypePtr *make( TYPES t, PTR ptr, int offset ); + static const TypePtr *make(TYPES t, PTR ptr, int offset, + const TypePtr* speculative = NULL, + int inline_depth = InlineDepthBottom); // Return a 'ptr' version of this type virtual const Type *cast_to_ptr_type(PTR ptr) const; @@ -784,10 +825,13 @@ int xadd_offset( intptr_t offset ) const; virtual const TypePtr *add_offset( intptr_t offset ) const; + virtual bool eq(const Type *t) const; + virtual int hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton virtual bool empty(void) const; // TRUE if type is vacuous virtual const Type *xmeet( const Type *t ) const; + virtual const Type *xmeet_helper( const Type *t ) const; int meet_offset( int offset ) const; int dual_offset( ) const; virtual const Type *xdual() const; // Compute dual right now. @@ -802,6 +846,20 @@ return ptr_dual[ ptr_meet[ ptr_dual[in_ptr] ] [ dual_ptr() ] ]; } + // Speculative type helper methods. + virtual const TypePtr* speculative() const { return _speculative; } + int inline_depth() const { return _inline_depth; } + virtual ciKlass* speculative_type() const; + virtual ciKlass* speculative_type_not_null() const; + virtual bool speculative_maybe_null() const; + virtual const Type* remove_speculative() const; + virtual const Type* cleanup_speculative() const; + virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const; + virtual bool would_improve_ptr(bool maybe_null) const; + virtual const TypePtr* with_inline_depth(int depth) const; + + virtual bool maybe_null() const { return meet_ptr(Null) == ptr(); } + // Tests for relation to centerline of type lattice: static bool above_centerline(PTR ptr) { return (ptr <= AnyNull); } static bool below_centerline(PTR ptr) { return (ptr >= NotNull); } @@ -850,7 +908,8 @@ // Some kind of oop (Java pointer), either klass or instance or array. class TypeOopPtr : public TypePtr { protected: - TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth); + TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, + const TypePtr* speculative, int inline_depth); public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing @@ -861,10 +920,6 @@ }; protected: - enum { - InlineDepthBottom = INT_MAX, - InlineDepthTop = -InlineDepthBottom - }; // Oop is NULL, unless this is a constant oop. ciObject* _const_oop; // Constant oop // If _klass is NULL, then so is _sig. This is an unloaded klass. @@ -880,38 +935,11 @@ // This is the the node index of the allocation node creating this instance. int _instance_id; - // Extra type information profiling gave us. We propagate it the - // same way the rest of the type info is propagated. If we want to - // use it, then we have to emit a guard: this part of the type is - // not something we know but something we speculate about the type. - const TypeOopPtr* _speculative; - // For speculative types, we record at what inlining depth the - // profiling point that provided the data is. We want to favor - // profile data coming from outer scopes which are likely better for - // the current compilation. - int _inline_depth; - static const TypeOopPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact); int dual_instance_id() const; int meet_instance_id(int uid) const; - // utility methods to work on the speculative part of the type - const TypeOopPtr* dual_speculative() const; - const TypeOopPtr* xmeet_speculative(const TypeOopPtr* other) const; - bool eq_speculative(const TypeOopPtr* other) const; - int hash_speculative() const; - const TypeOopPtr* add_offset_speculative(intptr_t offset) const; -#ifndef PRODUCT - void dump_speculative(outputStream *st) const; -#endif - // utility methods to work on the inline depth of the type - int dual_inline_depth() const; - int meet_inline_depth(int depth) const; -#ifndef PRODUCT - void dump_inline_depth(outputStream *st) const; -#endif - // Do not allow interface-vs.-noninterface joins to collapse to top. virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; @@ -941,7 +969,9 @@ bool not_null_elements = false); // Make a generic (unclassed) pointer to an oop. - static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); + static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, + const TypePtr* speculative = NULL, + int inline_depth = InlineDepthBottom); ciObject* const_oop() const { return _const_oop; } virtual ciKlass* klass() const { return _klass; } @@ -955,7 +985,6 @@ bool is_known_instance() const { return _instance_id > 0; } int instance_id() const { return _instance_id; } bool is_known_instance_field() const { return is_known_instance() && _offset >= 0; } - virtual const TypeOopPtr* speculative() const { return _speculative; } virtual intptr_t get_con() const; @@ -969,10 +998,13 @@ const TypeKlassPtr* as_klass_type() const; virtual const TypePtr *add_offset( intptr_t offset ) const; - // Return same type without a speculative part + + // Speculative type helper methods. virtual const Type* remove_speculative() const; + virtual const Type* cleanup_speculative() const; + virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const; + virtual const TypePtr* with_inline_depth(int depth) const; - virtual const Type *xmeet(const Type *t) const; virtual const Type *xdual() const; // Compute dual right now. // the core of the computation of the meet for TypeOopPtr and for its subclasses virtual const Type *xmeet_helper(const Type *t) const; @@ -982,29 +1014,14 @@ #ifndef PRODUCT virtual void dump2( Dict &d, uint depth, outputStream *st ) const; #endif - - // Return the speculative type if any - ciKlass* speculative_type() const { - if (_speculative != NULL) { - const TypeOopPtr* speculative = _speculative->join(this)->is_oopptr(); - if (speculative->klass_is_exact()) { - return speculative->klass(); - } - } - return NULL; - } - int inline_depth() const { - return _inline_depth; - } - virtual const TypeOopPtr* with_inline_depth(int depth) const; - virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const; }; //------------------------------TypeInstPtr------------------------------------ // Class of Java object pointers, pointing either to non-array Java instances // or to a Klass* (including array klasses). class TypeInstPtr : public TypeOopPtr { - TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth); + TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, + const TypePtr* speculative, int inline_depth); virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing @@ -1040,7 +1057,10 @@ } // Make a pointer to an oop. - static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); + static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, + int instance_id = InstanceBot, + const TypePtr* speculative = NULL, + int inline_depth = InlineDepthBottom); /** Create constant type for a constant boxed value */ const Type* get_const_boxed_value() const; @@ -1057,9 +1077,10 @@ virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const; virtual const TypePtr *add_offset( intptr_t offset ) const; - // Return same type without a speculative part + + // Speculative type helper methods. virtual const Type* remove_speculative() const; - virtual const TypeOopPtr* with_inline_depth(int depth) const; + virtual const TypePtr* with_inline_depth(int depth) const; // the core of the computation of the meet of 2 types virtual const Type *xmeet_helper(const Type *t) const; @@ -1081,7 +1102,8 @@ // Class of Java array pointers class TypeAryPtr : public TypeOopPtr { TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, - int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* speculative, int inline_depth) + int offset, int instance_id, bool is_autobox_cache, + const TypePtr* speculative, int inline_depth) : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative, inline_depth), _ary(ary), _is_autobox_cache(is_autobox_cache) @@ -1120,9 +1142,15 @@ bool is_autobox_cache() const { return _is_autobox_cache; } - static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); + static const TypeAryPtr *make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, + int instance_id = InstanceBot, + const TypePtr* speculative = NULL, + int inline_depth = InlineDepthBottom); // Constant pointer to array - static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom, bool is_autobox_cache= false); + static const TypeAryPtr *make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, + int instance_id = InstanceBot, + const TypePtr* speculative = NULL, + int inline_depth = InlineDepthBottom, bool is_autobox_cache = false); // Return a 'ptr' version of this type virtual const Type *cast_to_ptr_type(PTR ptr) const; @@ -1136,9 +1164,10 @@ virtual bool empty(void) const; // TRUE if type is vacuous virtual const TypePtr *add_offset( intptr_t offset ) const; - // Return same type without a speculative part + + // Speculative type helper methods. virtual const Type* remove_speculative() const; - virtual const TypeOopPtr* with_inline_depth(int depth) const; + virtual const TypePtr* with_inline_depth(int depth) const; // the core of the computation of the meet of 2 types virtual const Type *xmeet_helper(const Type *t) const; @@ -1367,9 +1396,8 @@ static const TypeNarrowOop *BOTTOM; static const TypeNarrowOop *NULL_PTR; - virtual const Type* remove_speculative() const { - return make(_ptrtype->remove_speculative()->is_ptr()); - } + virtual const Type* remove_speculative() const; + virtual const Type* cleanup_speculative() const; #ifndef PRODUCT virtual void dump2( Dict &d, uint depth, outputStream *st ) const;