8031755: Type speculation should be used to optimize explicit null checks
Feed profiling data about reference nullness to type speculation. Reviewed-by: kvn, iveresov
This commit is contained in:
parent
f5d6f0ceb8
commit
fa3b0a8f47
@ -581,14 +581,14 @@ void ciMethod::assert_call_type_ok(int bci) {
|
|||||||
* Check whether profiling provides a type for the argument i to the
|
* Check whether profiling provides a type for the argument i to the
|
||||||
* call at bci bci
|
* call at bci bci
|
||||||
*
|
*
|
||||||
* @param bci bci of the call
|
* @param [in]bci bci of the call
|
||||||
* @param i argument number
|
* @param [in]i argument number
|
||||||
* @return profiled type
|
* @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()) {
|
if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) {
|
||||||
ciProfileData* data = method_data()->bci_to_data(bci);
|
ciProfileData* data = method_data()->bci_to_data(bci);
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
@ -596,82 +596,77 @@ ciKlass* ciMethod::argument_profiled_type(int bci, int i) {
|
|||||||
assert_virtual_call_type_ok(bci);
|
assert_virtual_call_type_ok(bci);
|
||||||
ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
|
ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
|
||||||
if (i >= call->number_of_arguments()) {
|
if (i >= call->number_of_arguments()) {
|
||||||
return NULL;
|
return false;
|
||||||
}
|
|
||||||
ciKlass* type = call->valid_argument_type(i);
|
|
||||||
if (type != NULL && !call->argument_maybe_null(i)) {
|
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
type = call->valid_argument_type(i);
|
||||||
|
maybe_null = call->argument_maybe_null(i);
|
||||||
|
return true;
|
||||||
} else if (data->is_CallTypeData()) {
|
} else if (data->is_CallTypeData()) {
|
||||||
assert_call_type_ok(bci);
|
assert_call_type_ok(bci);
|
||||||
ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
|
ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
|
||||||
if (i >= call->number_of_arguments()) {
|
if (i >= call->number_of_arguments()) {
|
||||||
return NULL;
|
return false;
|
||||||
}
|
|
||||||
ciKlass* type = call->valid_argument_type(i);
|
|
||||||
if (type != NULL && !call->argument_maybe_null(i)) {
|
|
||||||
return type;
|
|
||||||
}
|
}
|
||||||
|
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
|
* Check whether profiling provides a type for the return value from
|
||||||
* the call at bci bci
|
* the call at bci bci
|
||||||
*
|
*
|
||||||
* @param bci bci of the call
|
* @param [in]bci bci of the call
|
||||||
* @return profiled type
|
* @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()) {
|
if (MethodData::profile_return() && method_data() != NULL && method_data()->is_mature()) {
|
||||||
ciProfileData* data = method_data()->bci_to_data(bci);
|
ciProfileData* data = method_data()->bci_to_data(bci);
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
if (data->is_VirtualCallTypeData()) {
|
if (data->is_VirtualCallTypeData()) {
|
||||||
assert_virtual_call_type_ok(bci);
|
assert_virtual_call_type_ok(bci);
|
||||||
ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
|
ciVirtualCallTypeData* call = (ciVirtualCallTypeData*)data->as_VirtualCallTypeData();
|
||||||
ciKlass* type = call->valid_return_type();
|
type = call->valid_return_type();
|
||||||
if (type != NULL && !call->return_maybe_null()) {
|
maybe_null = call->return_maybe_null();
|
||||||
return type;
|
return true;
|
||||||
}
|
|
||||||
} else if (data->is_CallTypeData()) {
|
} else if (data->is_CallTypeData()) {
|
||||||
assert_call_type_ok(bci);
|
assert_call_type_ok(bci);
|
||||||
ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
|
ciCallTypeData* call = (ciCallTypeData*)data->as_CallTypeData();
|
||||||
ciKlass* type = call->valid_return_type();
|
type = call->valid_return_type();
|
||||||
if (type != NULL && !call->return_maybe_null()) {
|
maybe_null = call->return_maybe_null();
|
||||||
return type;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether profiling provides a type for the parameter i
|
* Check whether profiling provides a type for the parameter i
|
||||||
*
|
*
|
||||||
* @param i parameter number
|
* @param [in]i parameter number
|
||||||
* @return profiled type
|
* @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()) {
|
if (MethodData::profile_parameters() && method_data() != NULL && method_data()->is_mature()) {
|
||||||
ciParametersTypeData* parameters = method_data()->parameters_type_data();
|
ciParametersTypeData* parameters = method_data()->parameters_type_data();
|
||||||
if (parameters != NULL && i < parameters->number_of_parameters()) {
|
if (parameters != NULL && i < parameters->number_of_parameters()) {
|
||||||
ciKlass* type = parameters->valid_parameter_type(i);
|
type = parameters->valid_parameter_type(i);
|
||||||
if (type != NULL && !parameters->parameter_maybe_null(i)) {
|
maybe_null = parameters->parameter_maybe_null(i);
|
||||||
return type;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,10 +234,10 @@ class ciMethod : public ciMetadata {
|
|||||||
ciCallProfile call_profile_at_bci(int bci);
|
ciCallProfile call_profile_at_bci(int bci);
|
||||||
int interpreter_call_site_count(int bci);
|
int interpreter_call_site_count(int bci);
|
||||||
|
|
||||||
// Does type profiling provide a useful type at this point?
|
// Does type profiling provide any useful information at this point?
|
||||||
ciKlass* argument_profiled_type(int bci, int i);
|
bool argument_profiled_type(int bci, int i, ciKlass*& type, bool& maybe_null);
|
||||||
ciKlass* parameter_profiled_type(int i);
|
bool parameter_profiled_type(int i, ciKlass*& type, bool& maybe_null);
|
||||||
ciKlass* return_profiled_type(int bci);
|
bool return_profiled_type(int bci, ciKlass*& type, bool& maybe_null);
|
||||||
|
|
||||||
ciField* get_field_at_bci( int bci, bool &will_link);
|
ciField* get_field_at_bci( int bci, bool &will_link);
|
||||||
ciMethod* get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature);
|
ciMethod* get_method_at_bci(int bci, bool &will_link, ciSignature* *declared_signature);
|
||||||
|
@ -801,6 +801,8 @@ bool MethodData::is_speculative_trap_bytecode(Bytecodes::Code code) {
|
|||||||
case Bytecodes::_invokeinterface:
|
case Bytecodes::_invokeinterface:
|
||||||
case Bytecodes::_if_acmpeq:
|
case Bytecodes::_if_acmpeq:
|
||||||
case Bytecodes::_if_acmpne:
|
case Bytecodes::_if_acmpne:
|
||||||
|
case Bytecodes::_ifnull:
|
||||||
|
case Bytecodes::_ifnonnull:
|
||||||
case Bytecodes::_invokestatic:
|
case Bytecodes::_invokestatic:
|
||||||
#ifdef COMPILER2
|
#ifdef COMPILER2
|
||||||
return UseTypeSpeculation;
|
return UseTypeSpeculation;
|
||||||
|
@ -2052,7 +2052,7 @@ public:
|
|||||||
|
|
||||||
// Whole-method sticky bits and flags
|
// Whole-method sticky bits and flags
|
||||||
enum {
|
enum {
|
||||||
_trap_hist_limit = 19, // decoupled from Deoptimization::Reason_LIMIT
|
_trap_hist_limit = 20, // decoupled from Deoptimization::Reason_LIMIT
|
||||||
_trap_hist_mask = max_jubyte,
|
_trap_hist_mask = max_jubyte,
|
||||||
_extra_data_count = 4 // extra DataLayout headers, for trap history
|
_extra_data_count = 4 // extra DataLayout headers, for trap history
|
||||||
}; // Public flag values
|
}; // Public flag values
|
||||||
|
@ -399,7 +399,7 @@ Node *ConstraintCastNode::Identity( PhaseTransform *phase ) {
|
|||||||
// Take 'join' of input and cast-up type
|
// Take 'join' of input and cast-up type
|
||||||
const Type *ConstraintCastNode::Value( PhaseTransform *phase ) const {
|
const Type *ConstraintCastNode::Value( PhaseTransform *phase ) const {
|
||||||
if( in(0) && phase->type(in(0)) == Type::TOP ) return Type::TOP;
|
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
|
#ifdef ASSERT
|
||||||
// Previous versions of this function had some special case logic,
|
// Previous versions of this function had some special case logic,
|
||||||
@ -493,7 +493,17 @@ const Type *CheckCastPPNode::Value( PhaseTransform *phase ) const {
|
|||||||
result = my_type->cast_to_ptr_type( my_type->join_ptr(in_ptr) );
|
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.
|
// JOIN NOT DONE HERE BECAUSE OF INTERFACE ISSUES.
|
||||||
// FIX THIS (DO THE JOIN) WHEN UNION TYPES APPEAR!
|
// FIX THIS (DO THE JOIN) WHEN UNION TYPES APPEAR!
|
||||||
|
@ -249,8 +249,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool
|
|||||||
}
|
}
|
||||||
CallGenerator* miss_cg;
|
CallGenerator* miss_cg;
|
||||||
Deoptimization::DeoptReason reason = morphism == 2 ?
|
Deoptimization::DeoptReason reason = morphism == 2 ?
|
||||||
Deoptimization::Reason_bimorphic :
|
Deoptimization::Reason_bimorphic : Deoptimization::reason_class_check(speculative_receiver_type != NULL);
|
||||||
(speculative_receiver_type == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check);
|
|
||||||
if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) &&
|
if ((morphism == 1 || (morphism == 2 && next_hit_cg != NULL)) &&
|
||||||
!too_many_traps(jvms->method(), jvms->bci(), reason)
|
!too_many_traps(jvms->method(), jvms->bci(), reason)
|
||||||
) {
|
) {
|
||||||
@ -631,13 +630,7 @@ void Parse::do_call() {
|
|||||||
}
|
}
|
||||||
BasicType ct = ctype->basic_type();
|
BasicType ct = ctype->basic_type();
|
||||||
if (ct == T_OBJECT || ct == T_ARRAY) {
|
if (ct == T_OBJECT || ct == T_ARRAY) {
|
||||||
ciKlass* better_type = method()->return_profiled_type(bci());
|
record_profiled_return_for_speculation();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,10 +612,10 @@ void GraphKit::builtin_throw(Deoptimization::DeoptReason reason, Node* arg) {
|
|||||||
// Usual case: Bail to interpreter.
|
// Usual case: Bail to interpreter.
|
||||||
// Reserve the right to recompile if we haven't seen anything yet.
|
// 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;
|
Deoptimization::DeoptAction action = Deoptimization::Action_maybe_recompile;
|
||||||
if (treat_throw_as_hot
|
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))) {
|
|| C->too_many_traps(reason))) {
|
||||||
// We cannot afford to take more traps here. Suffer in the interpreter.
|
// We cannot afford to take more traps here. Suffer in the interpreter.
|
||||||
if (C->log() != NULL)
|
if (C->log() != NULL)
|
||||||
@ -1181,7 +1181,8 @@ extern int explicit_null_checks_inserted,
|
|||||||
Node* GraphKit::null_check_common(Node* value, BasicType type,
|
Node* GraphKit::null_check_common(Node* value, BasicType type,
|
||||||
// optional arguments for variations:
|
// optional arguments for variations:
|
||||||
bool assert_null,
|
bool assert_null,
|
||||||
Node* *null_control) {
|
Node* *null_control,
|
||||||
|
bool speculative) {
|
||||||
assert(!assert_null || null_control == NULL, "not both at once");
|
assert(!assert_null || null_control == NULL, "not both at once");
|
||||||
if (stopped()) return top();
|
if (stopped()) return top();
|
||||||
if (!GenerateCompilerNullChecks && !assert_null && null_control == NULL) {
|
if (!GenerateCompilerNullChecks && !assert_null && null_control == NULL) {
|
||||||
@ -1291,13 +1292,13 @@ Node* GraphKit::null_check_common(Node* value, BasicType type,
|
|||||||
// Branch to failure if null
|
// Branch to failure if null
|
||||||
float ok_prob = PROB_MAX; // a priori estimate: nulls never happen
|
float ok_prob = PROB_MAX; // a priori estimate: nulls never happen
|
||||||
Deoptimization::DeoptReason reason;
|
Deoptimization::DeoptReason reason;
|
||||||
if (assert_null)
|
if (assert_null) {
|
||||||
reason = Deoptimization::Reason_null_assert;
|
reason = Deoptimization::Reason_null_assert;
|
||||||
else if (type == T_OBJECT)
|
} else if (type == T_OBJECT) {
|
||||||
reason = Deoptimization::Reason_null_check;
|
reason = Deoptimization::reason_null_check(speculative);
|
||||||
else
|
} else {
|
||||||
reason = Deoptimization::Reason_div0_check;
|
reason = Deoptimization::Reason_div0_check;
|
||||||
|
}
|
||||||
// %%% Since Reason_unhandled is not recorded on a per-bytecode basis,
|
// %%% Since Reason_unhandled is not recorded on a per-bytecode basis,
|
||||||
// ciMethodData::has_trap_at will return a conservative -1 if any
|
// ciMethodData::has_trap_at will return a conservative -1 if any
|
||||||
// must-be-null assertion has failed. This could cause performance
|
// must-be-null assertion has failed. This could cause performance
|
||||||
@ -2120,21 +2121,36 @@ void GraphKit::round_double_arguments(ciMethod* dest_method) {
|
|||||||
*
|
*
|
||||||
* @param n node that the type applies to
|
* @param n node that the type applies to
|
||||||
* @param exact_kls type from profiling
|
* @param exact_kls type from profiling
|
||||||
|
* @param maybe_null did profiling see null?
|
||||||
*
|
*
|
||||||
* @return node with improved type
|
* @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);
|
const Type* current_type = _gvn.type(n);
|
||||||
assert(UseTypeSpeculation, "type speculation must be on");
|
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())) {
|
if (current_type->would_improve_type(exact_kls, jvms()->depth())) {
|
||||||
const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls);
|
const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls);
|
||||||
const TypeOopPtr* xtype = tklass->as_instance_type();
|
const TypeOopPtr* xtype = tklass->as_instance_type();
|
||||||
assert(xtype->klass_is_exact(), "Should be exact");
|
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
|
// 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()) {
|
if (speculative != current_type->speculative()) {
|
||||||
@ -2167,7 +2183,15 @@ Node* GraphKit::record_profiled_receiver_for_speculation(Node* n) {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
ciKlass* exact_kls = profile_has_unique_klass();
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2187,9 +2211,10 @@ void GraphKit::record_profiled_arguments_for_speculation(ciMethod* dest_method,
|
|||||||
for (int j = skip, i = 0; j < nargs && i < TypeProfileArgsLimit; j++) {
|
for (int j = skip, i = 0; j < nargs && i < TypeProfileArgsLimit; j++) {
|
||||||
const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms);
|
const Type *targ = tf->_domain->field_at(j + TypeFunc::Parms);
|
||||||
if (targ->basic_type() == T_OBJECT || targ->basic_type() == T_ARRAY) {
|
if (targ->basic_type() == T_OBJECT || targ->basic_type() == T_ARRAY) {
|
||||||
ciKlass* better_type = method()->argument_profiled_type(bci(), i);
|
bool maybe_null = true;
|
||||||
if (better_type != NULL) {
|
ciKlass* better_type = NULL;
|
||||||
record_profile_for_speculation(argument(j), better_type);
|
if (method()->argument_profiled_type(bci(), i, better_type, maybe_null)) {
|
||||||
|
record_profile_for_speculation(argument(j), better_type, maybe_null);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -2206,15 +2231,34 @@ void GraphKit::record_profiled_parameters_for_speculation() {
|
|||||||
}
|
}
|
||||||
for (int i = 0, j = 0; i < method()->arg_size() ; i++) {
|
for (int i = 0, j = 0; i < method()->arg_size() ; i++) {
|
||||||
if (_gvn.type(local(i))->isa_oopptr()) {
|
if (_gvn.type(local(i))->isa_oopptr()) {
|
||||||
ciKlass* better_type = method()->parameter_profiled_type(j);
|
bool maybe_null = true;
|
||||||
if (better_type != NULL) {
|
ciKlass* better_type = NULL;
|
||||||
record_profile_for_speculation(local(i), better_type);
|
if (method()->parameter_profiled_type(j, better_type, maybe_null)) {
|
||||||
|
record_profile_for_speculation(local(i), better_type, maybe_null);
|
||||||
}
|
}
|
||||||
j++;
|
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) {
|
void GraphKit::round_double_result(ciMethod* dest_method) {
|
||||||
// A non-strict method may return a double value which has an extended
|
// 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'
|
// exponent, but this must not be visible in a caller which is 'strict'
|
||||||
@ -2294,10 +2338,12 @@ Node* GraphKit::dstore_rounding(Node* n) {
|
|||||||
// Null check oop. Set null-path control into Region in slot 3.
|
// 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.
|
// Make a cast-not-nullness use the other not-null control. Return cast.
|
||||||
Node* GraphKit::null_check_oop(Node* value, Node* *null_control,
|
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
|
// Initial NULL check taken path
|
||||||
(*null_control) = top();
|
(*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:
|
// Generate uncommon_trap:
|
||||||
if (never_see_null && (*null_control) != top()) {
|
if (never_see_null && (*null_control) != top()) {
|
||||||
@ -2308,7 +2354,8 @@ Node* GraphKit::null_check_oop(Node* value, Node* *null_control,
|
|||||||
PreserveJVMState pjvms(this);
|
PreserveJVMState pjvms(this);
|
||||||
set_control(*null_control);
|
set_control(*null_control);
|
||||||
replace_in_map(value, null());
|
replace_in_map(value, null());
|
||||||
uncommon_trap(Deoptimization::Reason_null_check,
|
Deoptimization::DeoptReason reason = Deoptimization::reason_null_check(speculative);
|
||||||
|
uncommon_trap(reason,
|
||||||
Deoptimization::Action_make_not_entrant);
|
Deoptimization::Action_make_not_entrant);
|
||||||
(*null_control) = top(); // NULL path is dead
|
(*null_control) = top(); // NULL path is dead
|
||||||
}
|
}
|
||||||
@ -2732,11 +2779,16 @@ Node* GraphKit::type_check_receiver(Node* receiver, ciKlass* klass,
|
|||||||
// recompile; the offending check will be recompiled to handle NULLs.
|
// recompile; the offending check will be recompiled to handle NULLs.
|
||||||
// If we see several offending BCIs, then all checks in the
|
// If we see several offending BCIs, then all checks in the
|
||||||
// method will be recompiled.
|
// 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 = Deoptimization::reason_null_check(speculating);
|
||||||
if (UncommonNullCast // Cutout for this technique
|
if (UncommonNullCast // Cutout for this technique
|
||||||
&& obj != null() // And not the -Xcomp stupid case?
|
&& 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)
|
if (data == NULL)
|
||||||
// Edge case: no mature data. Be optimistic here.
|
// Edge case: no mature data. Be optimistic here.
|
||||||
return true;
|
return true;
|
||||||
@ -2746,6 +2798,7 @@ bool GraphKit::seems_never_null(Node* obj, ciProfileData* data) {
|
|||||||
java_bc() == Bytecodes::_aastore, "MDO must collect null_seen bit here");
|
java_bc() == Bytecodes::_aastore, "MDO must collect null_seen bit here");
|
||||||
return !data->as_BitData()->null_seen();
|
return !data->as_BitData()->null_seen();
|
||||||
}
|
}
|
||||||
|
speculating = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2758,7 +2811,7 @@ Node* GraphKit::maybe_cast_profiled_receiver(Node* not_null_obj,
|
|||||||
bool safe_for_replace) {
|
bool safe_for_replace) {
|
||||||
if (!UseTypeProfile || !TypeProfileCasts) return NULL;
|
if (!UseTypeProfile || !TypeProfileCasts) return NULL;
|
||||||
|
|
||||||
Deoptimization::DeoptReason reason = spec_klass == NULL ? Deoptimization::Reason_class_check : Deoptimization::Reason_speculate_class_check;
|
Deoptimization::DeoptReason reason = Deoptimization::reason_class_check(spec_klass != NULL);
|
||||||
|
|
||||||
// Make sure we haven't already deoptimized from this tactic.
|
// Make sure we haven't already deoptimized from this tactic.
|
||||||
if (too_many_traps(reason))
|
if (too_many_traps(reason))
|
||||||
@ -2811,7 +2864,7 @@ Node* GraphKit::maybe_cast_profiled_obj(Node* obj,
|
|||||||
// type == NULL if profiling tells us this object is always null
|
// type == NULL if profiling tells us this object is always null
|
||||||
if (type != NULL) {
|
if (type != NULL) {
|
||||||
Deoptimization::DeoptReason class_reason = Deoptimization::Reason_speculate_class_check;
|
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) &&
|
if (!too_many_traps(null_reason) &&
|
||||||
!too_many_traps(class_reason)) {
|
!too_many_traps(class_reason)) {
|
||||||
Node* not_null_obj = NULL;
|
Node* not_null_obj = NULL;
|
||||||
@ -2819,7 +2872,7 @@ Node* GraphKit::maybe_cast_profiled_obj(Node* obj,
|
|||||||
// there's no need for a null check
|
// there's no need for a null check
|
||||||
if (!not_null) {
|
if (!not_null) {
|
||||||
Node* null_ctl = top();
|
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");
|
assert(null_ctl->is_top(), "no null control here");
|
||||||
} else {
|
} else {
|
||||||
not_null_obj = obj;
|
not_null_obj = obj;
|
||||||
@ -2867,12 +2920,13 @@ Node* GraphKit::gen_instanceof(Node* obj, Node* superklass, bool safe_for_replac
|
|||||||
if (java_bc() == Bytecodes::_instanceof) { // Only for the bytecode
|
if (java_bc() == Bytecodes::_instanceof) { // Only for the bytecode
|
||||||
data = method()->method_data()->bci_to_data(bci());
|
data = method()->method_data()->bci_to_data(bci());
|
||||||
}
|
}
|
||||||
|
bool speculative_not_null = false;
|
||||||
bool never_see_null = (ProfileDynamicTypes // aggressive use of profile
|
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
|
// Null check; get casted pointer; set region slot 3
|
||||||
Node* null_ctl = top();
|
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 not_null_obj is dead, only null-path is taken
|
||||||
if (stopped()) { // Doing instance-of on a NULL?
|
if (stopped()) { // Doing instance-of on a NULL?
|
||||||
@ -2995,12 +3049,13 @@ Node* GraphKit::gen_checkcast(Node *obj, Node* superklass,
|
|||||||
C->set_has_split_ifs(true); // Has chance for split-if optimization
|
C->set_has_split_ifs(true); // Has chance for split-if optimization
|
||||||
|
|
||||||
// Use null-cast information if it is available
|
// Use null-cast information if it is available
|
||||||
|
bool speculative_not_null = false;
|
||||||
bool never_see_null = ((failure_control == NULL) // regular case only
|
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
|
// Null check; get casted pointer; set region slot 3
|
||||||
Node* null_ctl = top();
|
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 not_null_obj is dead, only null-path is taken
|
||||||
if (stopped()) { // Doing instance-of on a NULL?
|
if (stopped()) { // Doing instance-of on a NULL?
|
||||||
|
@ -351,9 +351,11 @@ class GraphKit : public Phase {
|
|||||||
// Return the value cast to not-null.
|
// Return the value cast to not-null.
|
||||||
// Be clever about equivalent dominating null checks.
|
// Be clever about equivalent dominating null checks.
|
||||||
Node* null_check_common(Node* value, BasicType type,
|
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) {
|
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() {
|
Node* null_check_receiver() {
|
||||||
assert(argument(0)->bottom_type()->isa_ptr(), "must be");
|
assert(argument(0)->bottom_type()->isa_ptr(), "must be");
|
||||||
@ -382,10 +384,12 @@ class GraphKit : public Phase {
|
|||||||
// If safe_for_replace, then we can replace the value with the cast
|
// 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)
|
// in the parsing map (the cast is guaranteed to dominate the map)
|
||||||
Node* null_check_oop(Node* value, Node* *null_control,
|
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.
|
// 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
|
// Check for unique class for receiver at call
|
||||||
ciKlass* profile_has_unique_klass() {
|
ciKlass* profile_has_unique_klass() {
|
||||||
@ -399,10 +403,11 @@ class GraphKit : public Phase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// record type from profiling with the type system
|
// record type from profiling with the type system
|
||||||
Node* record_profile_for_speculation(Node* n, ciKlass* exact_kls);
|
Node* record_profile_for_speculation(Node* n, ciKlass* exact_kls, bool maybe_null);
|
||||||
Node* record_profiled_receiver_for_speculation(Node* n);
|
|
||||||
void record_profiled_arguments_for_speculation(ciMethod* dest_method, Bytecodes::Code bc);
|
void record_profiled_arguments_for_speculation(ciMethod* dest_method, Bytecodes::Code bc);
|
||||||
void record_profiled_parameters_for_speculation();
|
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.
|
// Use the type profile to narrow an object type.
|
||||||
Node* maybe_cast_profiled_receiver(Node* not_null_obj,
|
Node* maybe_cast_profiled_receiver(Node* not_null_obj,
|
||||||
|
@ -4658,7 +4658,7 @@ bool LibraryCallKit::inline_arraycopy() {
|
|||||||
|
|
||||||
ciKlass* src_k = NULL;
|
ciKlass* src_k = NULL;
|
||||||
if (!has_src) {
|
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()) {
|
if (src_k != NULL && src_k->is_array_klass()) {
|
||||||
could_have_src = true;
|
could_have_src = true;
|
||||||
}
|
}
|
||||||
@ -4666,7 +4666,7 @@ bool LibraryCallKit::inline_arraycopy() {
|
|||||||
|
|
||||||
ciKlass* dest_k = NULL;
|
ciKlass* dest_k = NULL;
|
||||||
if (!has_dest) {
|
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()) {
|
if (dest_k != NULL && dest_k->is_array_klass()) {
|
||||||
could_have_dest = true;
|
could_have_dest = true;
|
||||||
}
|
}
|
||||||
@ -4738,13 +4738,13 @@ bool LibraryCallKit::inline_arraycopy() {
|
|||||||
ciKlass* src_k = top_src->klass();
|
ciKlass* src_k = top_src->klass();
|
||||||
ciKlass* dest_k = top_dest->klass();
|
ciKlass* dest_k = top_dest->klass();
|
||||||
if (!src_spec) {
|
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()) {
|
if (src_k != NULL && src_k->is_array_klass()) {
|
||||||
could_have_src = true;
|
could_have_src = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!dest_spec) {
|
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()) {
|
if (dest_k != NULL && dest_k->is_array_klass()) {
|
||||||
could_have_dest = true;
|
could_have_dest = true;
|
||||||
}
|
}
|
||||||
|
@ -1288,7 +1288,7 @@ void Parse::sharpen_type_after_if(BoolTest::mask btest,
|
|||||||
(jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) {
|
(jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) {
|
||||||
TypeNode* ccast = new (C) CheckCastPPNode(control(), obj, tboth);
|
TypeNode* ccast = new (C) CheckCastPPNode(control(), obj, tboth);
|
||||||
const Type* tcc = ccast->as_Type()->type();
|
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
|
// Delay transform() call to allow recovery of pre-cast value
|
||||||
// at the control merge.
|
// at the control merge.
|
||||||
_gvn.set_type_bottom(ccast);
|
_gvn.set_type_bottom(ccast);
|
||||||
@ -1352,7 +1352,7 @@ void Parse::sharpen_type_after_if(BoolTest::mask btest,
|
|||||||
|
|
||||||
if (ccast != NULL) {
|
if (ccast != NULL) {
|
||||||
const Type* tcc = ccast->as_Type()->type();
|
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
|
// Delay transform() call to allow recovery of pre-cast value
|
||||||
// at the control merge.
|
// at the control merge.
|
||||||
ccast->set_req(0, control());
|
ccast->set_req(0, control());
|
||||||
@ -1393,7 +1393,7 @@ Node* Parse::optimize_cmp_with_klass(Node* c) {
|
|||||||
Node* addp = load_klass->in(2);
|
Node* addp = load_klass->in(2);
|
||||||
Node* obj = addp->in(AddPNode::Address);
|
Node* obj = addp->in(AddPNode::Address);
|
||||||
const TypeOopPtr* obj_type = _gvn.type(obj)->is_oopptr();
|
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();
|
ciKlass* k = obj_type->speculative_type();
|
||||||
inc_sp(2);
|
inc_sp(2);
|
||||||
obj = maybe_cast_profiled_obj(obj, k);
|
obj = maybe_cast_profiled_obj(obj, k);
|
||||||
@ -2277,6 +2277,14 @@ void Parse::do_one_bytecode() {
|
|||||||
maybe_add_safepoint(iter().get_dest());
|
maybe_add_safepoint(iter().get_dest());
|
||||||
a = null();
|
a = null();
|
||||||
b = pop();
|
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) );
|
c = _gvn.transform( new (C) CmpPNode(b, a) );
|
||||||
do_ifnull(btest, c);
|
do_ifnull(btest, c);
|
||||||
break;
|
break;
|
||||||
|
@ -330,7 +330,7 @@ void NodeHash::check_no_speculative_types() {
|
|||||||
Node *sentinel_node = sentinel();
|
Node *sentinel_node = sentinel();
|
||||||
for (uint i = 0; i < max; ++i) {
|
for (uint i = 0; i < max; ++i) {
|
||||||
Node *n = at(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();
|
TypeNode* tn = n->as_Type();
|
||||||
const Type* t = tn->type();
|
const Type* t = tn->type();
|
||||||
const Type* t_no_spec = t->remove_speculative();
|
const Type* t_no_spec = t->remove_speculative();
|
||||||
|
@ -350,9 +350,9 @@ void Type::Initialize_shared(Compile* current) {
|
|||||||
floop[1] = TypeInt::INT;
|
floop[1] = TypeInt::INT;
|
||||||
TypeTuple::LOOPBODY = TypeTuple::make( 2, floop );
|
TypeTuple::LOOPBODY = TypeTuple::make( 2, floop );
|
||||||
|
|
||||||
TypePtr::NULL_PTR= TypePtr::make( AnyPtr, TypePtr::Null, 0 );
|
TypePtr::NULL_PTR= TypePtr::make(AnyPtr, TypePtr::Null, 0);
|
||||||
TypePtr::NOTNULL = TypePtr::make( AnyPtr, TypePtr::NotNull, OffsetBot );
|
TypePtr::NOTNULL = TypePtr::make(AnyPtr, TypePtr::NotNull, OffsetBot);
|
||||||
TypePtr::BOTTOM = TypePtr::make( AnyPtr, TypePtr::BotPTR, OffsetBot );
|
TypePtr::BOTTOM = TypePtr::make(AnyPtr, TypePtr::BotPTR, OffsetBot);
|
||||||
|
|
||||||
TypeRawPtr::BOTTOM = TypeRawPtr::make( TypePtr::BotPTR );
|
TypeRawPtr::BOTTOM = TypeRawPtr::make( TypePtr::BotPTR );
|
||||||
TypeRawPtr::NOTNULL= TypeRawPtr::make( TypePtr::NotNull );
|
TypeRawPtr::NOTNULL= TypeRawPtr::make( TypePtr::NotNull );
|
||||||
@ -372,7 +372,7 @@ void Type::Initialize_shared(Compile* current) {
|
|||||||
false, 0, oopDesc::mark_offset_in_bytes());
|
false, 0, oopDesc::mark_offset_in_bytes());
|
||||||
TypeInstPtr::KLASS = TypeInstPtr::make(TypePtr::BotPTR, current->env()->Object_klass(),
|
TypeInstPtr::KLASS = TypeInstPtr::make(TypePtr::BotPTR, current->env()->Object_klass(),
|
||||||
false, 0, oopDesc::klass_offset_in_bytes());
|
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);
|
TypeMetadataPtr::BOTTOM = TypeMetadataPtr::make(TypePtr::BotPTR, NULL, OffsetBot);
|
||||||
|
|
||||||
@ -620,8 +620,8 @@ bool Type::interface_vs_oop(const Type *t) const {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Now check the speculative parts as well
|
// Now check the speculative parts as well
|
||||||
const TypeOopPtr* this_spec = isa_oopptr() != NULL ? isa_oopptr()->speculative() : NULL;
|
const TypePtr* this_spec = isa_ptr() != NULL ? is_ptr()->speculative() : NULL;
|
||||||
const TypeOopPtr* t_spec = t->isa_oopptr() != NULL ? t->isa_oopptr()->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 != NULL && t_spec != NULL) {
|
||||||
if (this_spec->interface_vs_oop_helper(t_spec)) {
|
if (this_spec->interface_vs_oop_helper(t_spec)) {
|
||||||
return true;
|
return true;
|
||||||
@ -1975,6 +1975,25 @@ const Type* TypeAry::remove_speculative() const {
|
|||||||
return make(_elem->remove_speculative(), _size, _stable);
|
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---------------------------------------
|
//----------------------interface_vs_oop---------------------------------------
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
bool TypeAry::interface_vs_oop(const Type *t) const {
|
bool TypeAry::interface_vs_oop(const Type *t) const {
|
||||||
@ -2179,15 +2198,15 @@ const TypePtr::PTR TypePtr::ptr_meet[TypePtr::lastPTR][TypePtr::lastPTR] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------make-------------------------------------------
|
//------------------------------make-------------------------------------------
|
||||||
const TypePtr *TypePtr::make( TYPES t, enum PTR ptr, int offset ) {
|
const TypePtr *TypePtr::make(TYPES t, enum PTR ptr, int offset, const TypePtr* speculative, int inline_depth) {
|
||||||
return (TypePtr*)(new TypePtr(t,ptr,offset))->hashcons();
|
return (TypePtr*)(new TypePtr(t,ptr,offset, speculative, inline_depth))->hashcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------cast_to_ptr_type-------------------------------
|
//------------------------------cast_to_ptr_type-------------------------------
|
||||||
const Type *TypePtr::cast_to_ptr_type(PTR ptr) const {
|
const Type *TypePtr::cast_to_ptr_type(PTR ptr) const {
|
||||||
assert(_base == AnyPtr, "subclass must override cast_to_ptr_type");
|
assert(_base == AnyPtr, "subclass must override cast_to_ptr_type");
|
||||||
if( ptr == _ptr ) return this;
|
if( ptr == _ptr ) return this;
|
||||||
return make(_base, ptr, _offset);
|
return make(_base, ptr, _offset, _speculative, _inline_depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------get_con----------------------------------------
|
//------------------------------get_con----------------------------------------
|
||||||
@ -2198,7 +2217,29 @@ intptr_t TypePtr::get_con() const {
|
|||||||
|
|
||||||
//------------------------------meet-------------------------------------------
|
//------------------------------meet-------------------------------------------
|
||||||
// Compute the MEET of two types. It returns a new Type object.
|
// 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.
|
// Perform a fast test for common case; meeting the same types together.
|
||||||
if( this == t ) return this; // Meeting same type-rep?
|
if( this == t ) return this; // Meeting same type-rep?
|
||||||
|
|
||||||
@ -2221,7 +2262,9 @@ const Type *TypePtr::xmeet( const Type *t ) const {
|
|||||||
|
|
||||||
case AnyPtr: { // Meeting to AnyPtrs
|
case AnyPtr: { // Meeting to AnyPtrs
|
||||||
const TypePtr *tp = t->is_ptr();
|
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 RawPtr: // For these, flip the call around to cut down
|
||||||
case OopPtr:
|
case OopPtr:
|
||||||
@ -2260,7 +2303,7 @@ const TypePtr::PTR TypePtr::ptr_dual[TypePtr::lastPTR] = {
|
|||||||
BotPTR, NotNull, Constant, Null, AnyNull, TopPTR
|
BotPTR, NotNull, Constant, Null, AnyNull, TopPTR
|
||||||
};
|
};
|
||||||
const Type *TypePtr::xdual() const {
|
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------------------------------------
|
//------------------------------xadd_offset------------------------------------
|
||||||
@ -2281,20 +2324,245 @@ int TypePtr::xadd_offset( intptr_t offset ) const {
|
|||||||
|
|
||||||
//------------------------------add_offset-------------------------------------
|
//------------------------------add_offset-------------------------------------
|
||||||
const TypePtr *TypePtr::add_offset( intptr_t offset ) const {
|
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---------------------------------------------
|
//------------------------------eq---------------------------------------------
|
||||||
// Structural equality check for Type representations
|
// Structural equality check for Type representations
|
||||||
bool TypePtr::eq( const Type *t ) const {
|
bool TypePtr::eq( const Type *t ) const {
|
||||||
const TypePtr *a = (const TypePtr*)t;
|
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-------------------------------------------
|
//------------------------------hash-------------------------------------------
|
||||||
// Type-specific hashing function.
|
// Type-specific hashing function.
|
||||||
int TypePtr::hash(void) const {
|
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------------------------------------------
|
//------------------------------dump2------------------------------------------
|
||||||
@ -2309,6 +2577,32 @@ void TypePtr::dump2( Dict &d, uint depth, outputStream *st ) const {
|
|||||||
if( _offset == OffsetTop ) st->print("+top");
|
if( _offset == OffsetTop ) st->print("+top");
|
||||||
else if( _offset == OffsetBot ) st->print("+bot");
|
else if( _offset == OffsetBot ) st->print("+bot");
|
||||||
else if( _offset ) st->print("+%d", _offset);
|
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
|
#endif
|
||||||
|
|
||||||
@ -2399,7 +2693,7 @@ const Type *TypeRawPtr::xmeet( const Type *t ) const {
|
|||||||
case TypePtr::Null:
|
case TypePtr::Null:
|
||||||
if( _ptr == TypePtr::TopPTR ) return t;
|
if( _ptr == TypePtr::TopPTR ) return t;
|
||||||
return TypeRawPtr::BOTTOM;
|
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:
|
case TypePtr::AnyNull:
|
||||||
if( _ptr == TypePtr::Constant) return this;
|
if( _ptr == TypePtr::Constant) return this;
|
||||||
return make( meet_ptr(TypePtr::AnyNull) );
|
return make( meet_ptr(TypePtr::AnyNull) );
|
||||||
@ -2463,16 +2757,15 @@ void TypeRawPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
|
|||||||
const TypeOopPtr *TypeOopPtr::BOTTOM;
|
const TypeOopPtr *TypeOopPtr::BOTTOM;
|
||||||
|
|
||||||
//------------------------------TypeOopPtr-------------------------------------
|
//------------------------------TypeOopPtr-------------------------------------
|
||||||
TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth)
|
TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset,
|
||||||
: TypePtr(t, ptr, offset),
|
int instance_id, const TypePtr* speculative, int inline_depth)
|
||||||
|
: TypePtr(t, ptr, offset, speculative, inline_depth),
|
||||||
_const_oop(o), _klass(k),
|
_const_oop(o), _klass(k),
|
||||||
_klass_is_exact(xk),
|
_klass_is_exact(xk),
|
||||||
_is_ptr_to_narrowoop(false),
|
_is_ptr_to_narrowoop(false),
|
||||||
_is_ptr_to_narrowklass(false),
|
_is_ptr_to_narrowklass(false),
|
||||||
_is_ptr_to_boxed_value(false),
|
_is_ptr_to_boxed_value(false),
|
||||||
_instance_id(instance_id),
|
_instance_id(instance_id) {
|
||||||
_speculative(speculative),
|
|
||||||
_inline_depth(inline_depth){
|
|
||||||
if (Compile::current()->eliminate_boxing() && (t == InstPtr) &&
|
if (Compile::current()->eliminate_boxing() && (t == InstPtr) &&
|
||||||
(offset > 0) && xk && (k != 0) && k->is_instance_klass()) {
|
(offset > 0) && xk && (k != 0) && k->is_instance_klass()) {
|
||||||
_is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset);
|
_is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset);
|
||||||
@ -2538,8 +2831,8 @@ TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int o
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------make-------------------------------------------
|
//------------------------------make-------------------------------------------
|
||||||
const TypeOopPtr *TypeOopPtr::make(PTR ptr,
|
const TypeOopPtr *TypeOopPtr::make(PTR ptr, int offset, int instance_id,
|
||||||
int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) {
|
const TypePtr* speculative, int inline_depth) {
|
||||||
assert(ptr != Constant, "no constant generic pointers");
|
assert(ptr != Constant, "no constant generic pointers");
|
||||||
ciKlass* k = Compile::current()->env()->Object_klass();
|
ciKlass* k = Compile::current()->env()->Object_klass();
|
||||||
bool xk = false;
|
bool xk = false;
|
||||||
@ -2582,28 +2875,6 @@ const TypeKlassPtr* TypeOopPtr::as_klass_type() const {
|
|||||||
return TypeKlassPtr::make(xk? Constant: NotNull, k, 0);
|
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-------------------------------------------
|
//------------------------------meet-------------------------------------------
|
||||||
// Compute the MEET of two types. It returns a new Type object.
|
// Compute the MEET of two types. It returns a new Type object.
|
||||||
const Type *TypeOopPtr::xmeet_helper(const Type *t) const {
|
const Type *TypeOopPtr::xmeet_helper(const Type *t) const {
|
||||||
@ -2641,19 +2912,20 @@ const Type *TypeOopPtr::xmeet_helper(const Type *t) const {
|
|||||||
const TypePtr *tp = t->is_ptr();
|
const TypePtr *tp = t->is_ptr();
|
||||||
int offset = meet_offset(tp->offset());
|
int offset = meet_offset(tp->offset());
|
||||||
PTR ptr = meet_ptr(tp->ptr());
|
PTR ptr = meet_ptr(tp->ptr());
|
||||||
|
const TypePtr* speculative = xmeet_speculative(tp);
|
||||||
|
int depth = meet_inline_depth(tp->inline_depth());
|
||||||
switch (tp->ptr()) {
|
switch (tp->ptr()) {
|
||||||
case Null:
|
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:
|
// else fall through:
|
||||||
case TopPTR:
|
case TopPTR:
|
||||||
case AnyNull: {
|
case AnyNull: {
|
||||||
int instance_id = meet_instance_id(InstanceTop);
|
int instance_id = meet_instance_id(InstanceTop);
|
||||||
const TypeOopPtr* speculative = _speculative;
|
return make(ptr, offset, instance_id, speculative, depth);
|
||||||
return make(ptr, offset, instance_id, speculative, _inline_depth);
|
|
||||||
}
|
}
|
||||||
case BotPTR:
|
case BotPTR:
|
||||||
case NotNull:
|
case NotNull:
|
||||||
return TypePtr::make(AnyPtr, ptr, offset);
|
return TypePtr::make(AnyPtr, ptr, offset, speculative, depth);
|
||||||
default: typerr(t);
|
default: typerr(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2661,7 +2933,7 @@ const Type *TypeOopPtr::xmeet_helper(const Type *t) const {
|
|||||||
case OopPtr: { // Meeting to other OopPtrs
|
case OopPtr: { // Meeting to other OopPtrs
|
||||||
const TypeOopPtr *tp = t->is_oopptr();
|
const TypeOopPtr *tp = t->is_oopptr();
|
||||||
int instance_id = meet_instance_id(tp->instance_id());
|
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());
|
int depth = meet_inline_depth(tp->inline_depth());
|
||||||
return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative, depth);
|
return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative, depth);
|
||||||
}
|
}
|
||||||
@ -2859,9 +3131,7 @@ const Type *TypeOopPtr::filter_helper(const Type *kills, bool include_speculativ
|
|||||||
bool TypeOopPtr::eq( const Type *t ) const {
|
bool TypeOopPtr::eq( const Type *t ) const {
|
||||||
const TypeOopPtr *a = (const TypeOopPtr*)t;
|
const TypeOopPtr *a = (const TypeOopPtr*)t;
|
||||||
if (_klass_is_exact != a->_klass_is_exact ||
|
if (_klass_is_exact != a->_klass_is_exact ||
|
||||||
_instance_id != a->_instance_id ||
|
_instance_id != a->_instance_id) return false;
|
||||||
!eq_speculative(a) ||
|
|
||||||
_inline_depth != a->_inline_depth) return false;
|
|
||||||
ciObject* one = const_oop();
|
ciObject* one = const_oop();
|
||||||
ciObject* two = a->const_oop();
|
ciObject* two = a->const_oop();
|
||||||
if (one == NULL || two == NULL) {
|
if (one == NULL || two == NULL) {
|
||||||
@ -2878,8 +3148,6 @@ int TypeOopPtr::hash(void) const {
|
|||||||
(const_oop() ? const_oop()->hash() : 0) +
|
(const_oop() ? const_oop()->hash() : 0) +
|
||||||
_klass_is_exact +
|
_klass_is_exact +
|
||||||
_instance_id +
|
_instance_id +
|
||||||
hash_speculative() +
|
|
||||||
_inline_depth +
|
|
||||||
TypePtr::hash();
|
TypePtr::hash();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2903,27 +3171,6 @@ void TypeOopPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
|
|||||||
dump_inline_depth(st);
|
dump_inline_depth(st);
|
||||||
dump_speculative(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
|
#endif
|
||||||
|
|
||||||
//------------------------------singleton--------------------------------------
|
//------------------------------singleton--------------------------------------
|
||||||
@ -2951,50 +3198,31 @@ const Type* TypeOopPtr::remove_speculative() const {
|
|||||||
return make(_ptr, _offset, _instance_id, NULL, _inline_depth);
|
return make(_ptr, _offset, _instance_id, NULL, _inline_depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return same type but drop speculative part if we know we won't use
|
||||||
|
* it
|
||||||
|
*/
|
||||||
|
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 TypePtr::cleanup_speculative();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return same type but with a different inline depth (used for speculation)
|
* Return same type but with a different inline depth (used for speculation)
|
||||||
*
|
*
|
||||||
* @param depth depth to meet with
|
* @param depth depth to meet with
|
||||||
*/
|
*/
|
||||||
const TypeOopPtr* TypeOopPtr::with_inline_depth(int depth) const {
|
const TypePtr* TypeOopPtr::with_inline_depth(int depth) const {
|
||||||
if (!UseInlineDepthForSpeculativeTypes) {
|
if (!UseInlineDepthForSpeculativeTypes) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
return make(_ptr, _offset, _instance_id, _speculative, depth);
|
return make(_ptr, _offset, _instance_id, _speculative, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 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;
|
|
||||||
}
|
|
||||||
assert(_speculative->inline_depth() != InlineDepthTop, "can't do the comparison");
|
|
||||||
return inline_depth < _speculative->inline_depth();
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------meet_instance_id--------------------------------
|
//------------------------------meet_instance_id--------------------------------
|
||||||
int TypeOopPtr::meet_instance_id( int instance_id ) const {
|
int TypeOopPtr::meet_instance_id( int instance_id ) const {
|
||||||
// Either is 'TOP' instance? Return the other instance!
|
// Either is 'TOP' instance? Return the other instance!
|
||||||
@ -3013,102 +3241,19 @@ int TypeOopPtr::dual_instance_id( ) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meet of the speculative parts of 2 types
|
* Check whether new profiling would improve speculative type
|
||||||
*
|
*
|
||||||
* @param other type to meet with
|
* @param exact_kls class from profiling
|
||||||
*/
|
* @param inline_depth inlining depth of profile point
|
||||||
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
|
|
||||||
*
|
*
|
||||||
* @param offset offset to add
|
* @return true if type profile is valuable
|
||||||
*/
|
*/
|
||||||
const TypeOopPtr* TypeOopPtr::add_offset_speculative(intptr_t offset) const {
|
bool TypeOopPtr::would_improve_type(ciKlass* exact_kls, int inline_depth) const {
|
||||||
if (_speculative == NULL) {
|
// no way to improve an already exact type
|
||||||
return NULL;
|
if (klass_is_exact()) {
|
||||||
}
|
|
||||||
return _speculative->add_offset(offset)->is_oopptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Are the speculative parts of 2 types equal?
|
|
||||||
*
|
|
||||||
* @param other type to compare this one to
|
|
||||||
*/
|
|
||||||
bool TypeOopPtr::eq_speculative(const TypeOopPtr* other) const {
|
|
||||||
if (_speculative == NULL || other->speculative() == NULL) {
|
|
||||||
return _speculative == other->speculative();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_speculative->base() != other->speculative()->base()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
return TypePtr::would_improve_type(exact_kls, inline_depth);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
@ -3120,8 +3265,10 @@ const TypeInstPtr *TypeInstPtr::MARK;
|
|||||||
const TypeInstPtr *TypeInstPtr::KLASS;
|
const TypeInstPtr *TypeInstPtr::KLASS;
|
||||||
|
|
||||||
//------------------------------TypeInstPtr-------------------------------------
|
//------------------------------TypeInstPtr-------------------------------------
|
||||||
TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypeOopPtr* speculative, int inline_depth)
|
TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off,
|
||||||
: TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth), _name(k->name()) {
|
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 &&
|
assert(k != NULL &&
|
||||||
(k->is_loaded() || o == NULL),
|
(k->is_loaded() || o == NULL),
|
||||||
"cannot have constants with non-loaded klass");
|
"cannot have constants with non-loaded klass");
|
||||||
@ -3134,7 +3281,7 @@ const TypeInstPtr *TypeInstPtr::make(PTR ptr,
|
|||||||
ciObject* o,
|
ciObject* o,
|
||||||
int offset,
|
int offset,
|
||||||
int instance_id,
|
int instance_id,
|
||||||
const TypeOopPtr* speculative,
|
const TypePtr* speculative,
|
||||||
int inline_depth) {
|
int inline_depth) {
|
||||||
assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance");
|
assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance");
|
||||||
// Either const_oop() is NULL or else ptr is Constant
|
// Either const_oop() is NULL or else ptr is Constant
|
||||||
@ -3217,7 +3364,7 @@ const TypeInstPtr *TypeInstPtr::xmeet_unloaded(const TypeInstPtr *tinst) const {
|
|||||||
int off = meet_offset(tinst->offset());
|
int off = meet_offset(tinst->offset());
|
||||||
PTR ptr = meet_ptr(tinst->ptr());
|
PTR ptr = meet_ptr(tinst->ptr());
|
||||||
int instance_id = meet_instance_id(tinst->instance_id());
|
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());
|
int depth = meet_inline_depth(tinst->inline_depth());
|
||||||
|
|
||||||
const TypeInstPtr *loaded = is_loaded() ? this : tinst;
|
const TypeInstPtr *loaded = is_loaded() ? this : tinst;
|
||||||
@ -3295,7 +3442,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const {
|
|||||||
int offset = meet_offset(tp->offset());
|
int offset = meet_offset(tp->offset());
|
||||||
PTR ptr = meet_ptr(tp->ptr());
|
PTR ptr = meet_ptr(tp->ptr());
|
||||||
int instance_id = meet_instance_id(tp->instance_id());
|
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());
|
int depth = meet_inline_depth(tp->inline_depth());
|
||||||
switch (ptr) {
|
switch (ptr) {
|
||||||
case TopPTR:
|
case TopPTR:
|
||||||
@ -3346,7 +3493,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const {
|
|||||||
case TopPTR:
|
case TopPTR:
|
||||||
case AnyNull: {
|
case AnyNull: {
|
||||||
int instance_id = meet_instance_id(InstanceTop);
|
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());
|
int depth = meet_inline_depth(tp->inline_depth());
|
||||||
return make(ptr, klass(), klass_is_exact(),
|
return make(ptr, klass(), klass_is_exact(),
|
||||||
(ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, depth);
|
(ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, depth);
|
||||||
@ -3354,7 +3501,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const {
|
|||||||
case NotNull:
|
case NotNull:
|
||||||
case BotPTR: {
|
case BotPTR: {
|
||||||
int instance_id = meet_instance_id(tp->instance_id());
|
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());
|
int depth = meet_inline_depth(tp->inline_depth());
|
||||||
return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth);
|
return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth);
|
||||||
}
|
}
|
||||||
@ -3367,20 +3514,21 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const {
|
|||||||
const TypePtr *tp = t->is_ptr();
|
const TypePtr *tp = t->is_ptr();
|
||||||
int offset = meet_offset(tp->offset());
|
int offset = meet_offset(tp->offset());
|
||||||
PTR ptr = meet_ptr(tp->ptr());
|
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()) {
|
switch (tp->ptr()) {
|
||||||
case Null:
|
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
|
// else fall through to AnyNull
|
||||||
case TopPTR:
|
case TopPTR:
|
||||||
case AnyNull: {
|
case AnyNull: {
|
||||||
int instance_id = meet_instance_id(InstanceTop);
|
|
||||||
const TypeOopPtr* speculative = _speculative;
|
|
||||||
return make(ptr, klass(), klass_is_exact(),
|
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 NotNull:
|
||||||
case BotPTR:
|
case BotPTR:
|
||||||
return TypePtr::make(AnyPtr, ptr, offset);
|
return TypePtr::make(AnyPtr, ptr, offset, speculative,depth);
|
||||||
default: typerr(t);
|
default: typerr(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3407,7 +3555,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const {
|
|||||||
int off = meet_offset( tinst->offset() );
|
int off = meet_offset( tinst->offset() );
|
||||||
PTR ptr = meet_ptr( tinst->ptr() );
|
PTR ptr = meet_ptr( tinst->ptr() );
|
||||||
int instance_id = meet_instance_id(tinst->instance_id());
|
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());
|
int depth = meet_inline_depth(tinst->inline_depth());
|
||||||
|
|
||||||
// Check for easy case; klasses are equal (and perhaps not loaded!)
|
// Check for easy case; klasses are equal (and perhaps not loaded!)
|
||||||
@ -3563,6 +3711,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const {
|
|||||||
// class hierarchy - which means we have to fall to at least NotNull.
|
// class hierarchy - which means we have to fall to at least NotNull.
|
||||||
if( ptr == TopPTR || ptr == AnyNull || ptr == Constant )
|
if( ptr == TopPTR || ptr == AnyNull || ptr == Constant )
|
||||||
ptr = NotNull;
|
ptr = NotNull;
|
||||||
|
|
||||||
instance_id = InstanceBot;
|
instance_id = InstanceBot;
|
||||||
|
|
||||||
// Now we find the LCA of Java classes
|
// Now we find the LCA of Java classes
|
||||||
@ -3655,7 +3804,8 @@ void TypeInstPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
|
|||||||
|
|
||||||
//------------------------------add_offset-------------------------------------
|
//------------------------------add_offset-------------------------------------
|
||||||
const TypePtr *TypeInstPtr::add_offset(intptr_t offset) const {
|
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 {
|
const Type *TypeInstPtr::remove_speculative() const {
|
||||||
@ -3663,10 +3813,11 @@ const Type *TypeInstPtr::remove_speculative() const {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth");
|
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) {
|
if (!UseInlineDepthForSpeculativeTypes) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -3687,7 +3838,8 @@ const TypeAryPtr *TypeAryPtr::FLOATS;
|
|||||||
const TypeAryPtr *TypeAryPtr::DOUBLES;
|
const TypeAryPtr *TypeAryPtr::DOUBLES;
|
||||||
|
|
||||||
//------------------------------make-------------------------------------------
|
//------------------------------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()),
|
assert(!(k == NULL && ary->_elem->isa_int()),
|
||||||
"integral arrays must be pre-equipped with a class");
|
"integral arrays must be pre-equipped with a class");
|
||||||
if (!xk) xk = ary->ary_must_be_exact();
|
if (!xk) xk = ary->ary_must_be_exact();
|
||||||
@ -3697,7 +3849,9 @@ const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------make-------------------------------------------
|
//------------------------------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()),
|
assert(!(k == NULL && ary->_elem->isa_int()),
|
||||||
"integral arrays must be pre-equipped with a class");
|
"integral arrays must be pre-equipped with a class");
|
||||||
assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" );
|
assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" );
|
||||||
@ -3807,7 +3961,7 @@ const TypeAryPtr* TypeAryPtr::cast_to_stable(bool stable, int stable_dimension)
|
|||||||
|
|
||||||
const TypeAry* new_ary = TypeAry::make(elem, size(), stable);
|
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--------------------------------
|
//-----------------------------stable_dimension--------------------------------
|
||||||
@ -3868,18 +4022,17 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
|
|||||||
int offset = meet_offset(tp->offset());
|
int offset = meet_offset(tp->offset());
|
||||||
PTR ptr = meet_ptr(tp->ptr());
|
PTR ptr = meet_ptr(tp->ptr());
|
||||||
int depth = meet_inline_depth(tp->inline_depth());
|
int depth = meet_inline_depth(tp->inline_depth());
|
||||||
|
const TypePtr* speculative = xmeet_speculative(tp);
|
||||||
switch (tp->ptr()) {
|
switch (tp->ptr()) {
|
||||||
case TopPTR:
|
case TopPTR:
|
||||||
case AnyNull: {
|
case AnyNull: {
|
||||||
int instance_id = meet_instance_id(InstanceTop);
|
int instance_id = meet_instance_id(InstanceTop);
|
||||||
const TypeOopPtr* speculative = xmeet_speculative(tp);
|
|
||||||
return make(ptr, (ptr == Constant ? const_oop() : NULL),
|
return make(ptr, (ptr == Constant ? const_oop() : NULL),
|
||||||
_ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth);
|
_ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth);
|
||||||
}
|
}
|
||||||
case BotPTR:
|
case BotPTR:
|
||||||
case NotNull: {
|
case NotNull: {
|
||||||
int instance_id = meet_instance_id(tp->instance_id());
|
int instance_id = meet_instance_id(tp->instance_id());
|
||||||
const TypeOopPtr* speculative = xmeet_speculative(tp);
|
|
||||||
return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth);
|
return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth);
|
||||||
}
|
}
|
||||||
default: ShouldNotReachHere();
|
default: ShouldNotReachHere();
|
||||||
@ -3891,20 +4044,21 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
|
|||||||
const TypePtr *tp = t->is_ptr();
|
const TypePtr *tp = t->is_ptr();
|
||||||
int offset = meet_offset(tp->offset());
|
int offset = meet_offset(tp->offset());
|
||||||
PTR ptr = meet_ptr(tp->ptr());
|
PTR ptr = meet_ptr(tp->ptr());
|
||||||
|
const TypePtr* speculative = xmeet_speculative(tp);
|
||||||
|
int depth = meet_inline_depth(tp->inline_depth());
|
||||||
switch (tp->ptr()) {
|
switch (tp->ptr()) {
|
||||||
case TopPTR:
|
case TopPTR:
|
||||||
return this;
|
return this;
|
||||||
case BotPTR:
|
case BotPTR:
|
||||||
case NotNull:
|
case NotNull:
|
||||||
return TypePtr::make(AnyPtr, ptr, offset);
|
return TypePtr::make(AnyPtr, ptr, offset, speculative, depth);
|
||||||
case Null:
|
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
|
// else fall through to AnyNull
|
||||||
case AnyNull: {
|
case AnyNull: {
|
||||||
int instance_id = meet_instance_id(InstanceTop);
|
int instance_id = meet_instance_id(InstanceTop);
|
||||||
const TypeOopPtr* speculative = _speculative;
|
|
||||||
return make(ptr, (ptr == Constant ? const_oop() : NULL),
|
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();
|
default: ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
@ -3920,7 +4074,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
|
|||||||
const TypeAry *tary = _ary->meet_speculative(tap->_ary)->is_ary();
|
const TypeAry *tary = _ary->meet_speculative(tap->_ary)->is_ary();
|
||||||
PTR ptr = meet_ptr(tap->ptr());
|
PTR ptr = meet_ptr(tap->ptr());
|
||||||
int instance_id = meet_instance_id(tap->instance_id());
|
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());
|
int depth = meet_inline_depth(tap->inline_depth());
|
||||||
ciKlass* lazy_klass = NULL;
|
ciKlass* lazy_klass = NULL;
|
||||||
if (tary->_elem->isa_int()) {
|
if (tary->_elem->isa_int()) {
|
||||||
@ -3949,7 +4103,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
|
|||||||
// 'this' is exact and super or unrelated:
|
// 'this' is exact and super or unrelated:
|
||||||
(this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) {
|
(this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) {
|
||||||
tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
|
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;
|
bool xk = false;
|
||||||
@ -4001,7 +4155,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
|
|||||||
int offset = meet_offset(tp->offset());
|
int offset = meet_offset(tp->offset());
|
||||||
PTR ptr = meet_ptr(tp->ptr());
|
PTR ptr = meet_ptr(tp->ptr());
|
||||||
int instance_id = meet_instance_id(tp->instance_id());
|
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());
|
int depth = meet_inline_depth(tp->inline_depth());
|
||||||
switch (ptr) {
|
switch (ptr) {
|
||||||
case TopPTR:
|
case TopPTR:
|
||||||
@ -4125,7 +4279,7 @@ const Type *TypeAryPtr::remove_speculative() const {
|
|||||||
return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL, _inline_depth);
|
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) {
|
if (!UseInlineDepthForSpeculativeTypes) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -4250,6 +4404,13 @@ const TypeNarrowOop* TypeNarrowOop::make(const TypePtr* type) {
|
|||||||
return (const TypeNarrowOop*)(new TypeNarrowOop(type))->hashcons();
|
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
|
#ifndef PRODUCT
|
||||||
void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const {
|
void TypeNarrowOop::dump2( Dict & d, uint depth, outputStream *st ) const {
|
||||||
@ -4376,7 +4537,7 @@ const Type *TypeMetadataPtr::xmeet( const Type *t ) const {
|
|||||||
PTR ptr = meet_ptr(tp->ptr());
|
PTR ptr = meet_ptr(tp->ptr());
|
||||||
switch (tp->ptr()) {
|
switch (tp->ptr()) {
|
||||||
case Null:
|
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:
|
// else fall through:
|
||||||
case TopPTR:
|
case TopPTR:
|
||||||
case AnyNull: {
|
case AnyNull: {
|
||||||
@ -4384,7 +4545,7 @@ const Type *TypeMetadataPtr::xmeet( const Type *t ) const {
|
|||||||
}
|
}
|
||||||
case BotPTR:
|
case BotPTR:
|
||||||
case NotNull:
|
case NotNull:
|
||||||
return TypePtr::make(AnyPtr, ptr, offset);
|
return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
|
||||||
default: typerr(t);
|
default: typerr(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4698,12 +4859,12 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const {
|
|||||||
case TopPTR:
|
case TopPTR:
|
||||||
return this;
|
return this;
|
||||||
case Null:
|
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:
|
case AnyNull:
|
||||||
return make( ptr, klass(), offset );
|
return make( ptr, klass(), offset );
|
||||||
case BotPTR:
|
case BotPTR:
|
||||||
case NotNull:
|
case NotNull:
|
||||||
return TypePtr::make(AnyPtr, ptr, offset);
|
return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth());
|
||||||
default: typerr(t);
|
default: typerr(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ public:
|
|||||||
}
|
}
|
||||||
// Variant that keeps the speculative part of the types
|
// Variant that keeps the speculative part of the types
|
||||||
const Type *meet_speculative(const Type *t) const {
|
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
|
// WIDEN: 'widens' for Ints and other range types
|
||||||
virtual const Type *widen( const Type *old, const Type* limit ) const { return this; }
|
virtual const Type *widen( const Type *old, const Type* limit ) const { return this; }
|
||||||
@ -247,7 +247,7 @@ public:
|
|||||||
}
|
}
|
||||||
// Variant that keeps the speculative part of the types
|
// Variant that keeps the speculative part of the types
|
||||||
const Type *join_speculative(const Type *t) const {
|
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.
|
// Modified version of JOIN adapted to the needs Node::Value.
|
||||||
@ -259,7 +259,7 @@ public:
|
|||||||
}
|
}
|
||||||
// Variant that keeps the speculative part of the types
|
// Variant that keeps the speculative part of the types
|
||||||
const Type *filter_speculative(const Type *kills) const {
|
const Type *filter_speculative(const Type *kills) const {
|
||||||
return filter_helper(kills, true);
|
return filter_helper(kills, true)->cleanup_speculative();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
@ -414,15 +414,18 @@ public:
|
|||||||
bool require_constant = false,
|
bool require_constant = false,
|
||||||
bool is_autobox_cache = false);
|
bool is_autobox_cache = false);
|
||||||
|
|
||||||
// Speculative type. See TypeInstPtr
|
// Speculative type helper methods. See TypePtr.
|
||||||
virtual const TypeOopPtr* speculative() const { return NULL; }
|
virtual const TypePtr* speculative() const { return NULL; }
|
||||||
virtual ciKlass* speculative_type() 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;
|
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 {
|
virtual bool maybe_null() const { return true; }
|
||||||
return exact_kls != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// support arrays
|
// support arrays
|
||||||
@ -679,6 +682,7 @@ public:
|
|||||||
virtual const Type *xdual() const; // Compute dual right now.
|
virtual const Type *xdual() const; // Compute dual right now.
|
||||||
bool ary_must_be_exact() const; // true if arrays of such are never generic
|
bool ary_must_be_exact() const; // true if arrays of such are never generic
|
||||||
virtual const Type* remove_speculative() const;
|
virtual const Type* remove_speculative() const;
|
||||||
|
virtual const Type* cleanup_speculative() const;
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
// One type is interface, the other is oop
|
// One type is interface, the other is oop
|
||||||
virtual bool interface_vs_oop(const Type *t) const;
|
virtual bool interface_vs_oop(const Type *t) const;
|
||||||
@ -761,13 +765,48 @@ class TypePtr : public Type {
|
|||||||
public:
|
public:
|
||||||
enum PTR { TopPTR, AnyNull, Constant, Null, NotNull, BotPTR, lastPTR };
|
enum PTR { TopPTR, AnyNull, Constant, Null, NotNull, BotPTR, lastPTR };
|
||||||
protected:
|
protected:
|
||||||
TypePtr( TYPES t, PTR ptr, int offset ) : Type(t), _ptr(ptr), _offset(offset) {}
|
TypePtr(TYPES t, PTR ptr, int offset,
|
||||||
virtual bool eq( const Type *t ) const;
|
const TypePtr* speculative = NULL,
|
||||||
virtual int hash() const; // Type specific hashing
|
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_meet[lastPTR][lastPTR];
|
||||||
static const PTR ptr_dual[lastPTR];
|
static const PTR ptr_dual[lastPTR];
|
||||||
static const char * const ptr_msg[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:
|
public:
|
||||||
const int _offset; // Offset into oop, with TOP & BOT
|
const int _offset; // Offset into oop, with TOP & BOT
|
||||||
const PTR _ptr; // Pointer equivalence class
|
const PTR _ptr; // Pointer equivalence class
|
||||||
@ -775,7 +814,9 @@ public:
|
|||||||
const int offset() const { return _offset; }
|
const int offset() const { return _offset; }
|
||||||
const PTR ptr() const { return _ptr; }
|
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
|
// Return a 'ptr' version of this type
|
||||||
virtual const Type *cast_to_ptr_type(PTR ptr) const;
|
virtual const Type *cast_to_ptr_type(PTR ptr) const;
|
||||||
@ -784,10 +825,13 @@ public:
|
|||||||
|
|
||||||
int xadd_offset( intptr_t offset ) const;
|
int xadd_offset( intptr_t offset ) const;
|
||||||
virtual const TypePtr *add_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 singleton(void) const; // TRUE if type is a singleton
|
||||||
virtual bool empty(void) const; // TRUE if type is vacuous
|
virtual bool empty(void) const; // TRUE if type is vacuous
|
||||||
virtual const Type *xmeet( const Type *t ) const;
|
virtual const Type *xmeet( const Type *t ) const;
|
||||||
|
virtual const Type *xmeet_helper( const Type *t ) const;
|
||||||
int meet_offset( int offset ) const;
|
int meet_offset( int offset ) const;
|
||||||
int dual_offset( ) const;
|
int dual_offset( ) const;
|
||||||
virtual const Type *xdual() const; // Compute dual right now.
|
virtual const Type *xdual() const; // Compute dual right now.
|
||||||
@ -802,6 +846,20 @@ public:
|
|||||||
return ptr_dual[ ptr_meet[ ptr_dual[in_ptr] ] [ dual_ptr() ] ];
|
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:
|
// Tests for relation to centerline of type lattice:
|
||||||
static bool above_centerline(PTR ptr) { return (ptr <= AnyNull); }
|
static bool above_centerline(PTR ptr) { return (ptr <= AnyNull); }
|
||||||
static bool below_centerline(PTR ptr) { return (ptr >= NotNull); }
|
static bool below_centerline(PTR ptr) { return (ptr >= NotNull); }
|
||||||
@ -850,7 +908,8 @@ public:
|
|||||||
// Some kind of oop (Java pointer), either klass or instance or array.
|
// Some kind of oop (Java pointer), either klass or instance or array.
|
||||||
class TypeOopPtr : public TypePtr {
|
class TypeOopPtr : public TypePtr {
|
||||||
protected:
|
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:
|
public:
|
||||||
virtual bool eq( const Type *t ) const;
|
virtual bool eq( const Type *t ) const;
|
||||||
virtual int hash() const; // Type specific hashing
|
virtual int hash() const; // Type specific hashing
|
||||||
@ -861,10 +920,6 @@ public:
|
|||||||
};
|
};
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
enum {
|
|
||||||
InlineDepthBottom = INT_MAX,
|
|
||||||
InlineDepthTop = -InlineDepthBottom
|
|
||||||
};
|
|
||||||
// Oop is NULL, unless this is a constant oop.
|
// Oop is NULL, unless this is a constant oop.
|
||||||
ciObject* _const_oop; // Constant oop
|
ciObject* _const_oop; // Constant oop
|
||||||
// If _klass is NULL, then so is _sig. This is an unloaded klass.
|
// If _klass is NULL, then so is _sig. This is an unloaded klass.
|
||||||
@ -880,38 +935,11 @@ protected:
|
|||||||
// This is the the node index of the allocation node creating this instance.
|
// This is the the node index of the allocation node creating this instance.
|
||||||
int _instance_id;
|
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);
|
static const TypeOopPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact);
|
||||||
|
|
||||||
int dual_instance_id() const;
|
int dual_instance_id() const;
|
||||||
int meet_instance_id(int uid) 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.
|
// Do not allow interface-vs.-noninterface joins to collapse to top.
|
||||||
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
|
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
|
||||||
|
|
||||||
@ -941,7 +969,9 @@ public:
|
|||||||
bool not_null_elements = false);
|
bool not_null_elements = false);
|
||||||
|
|
||||||
// Make a generic (unclassed) pointer to an oop.
|
// 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; }
|
ciObject* const_oop() const { return _const_oop; }
|
||||||
virtual ciKlass* klass() const { return _klass; }
|
virtual ciKlass* klass() const { return _klass; }
|
||||||
@ -955,7 +985,6 @@ public:
|
|||||||
bool is_known_instance() const { return _instance_id > 0; }
|
bool is_known_instance() const { return _instance_id > 0; }
|
||||||
int instance_id() const { return _instance_id; }
|
int instance_id() const { return _instance_id; }
|
||||||
bool is_known_instance_field() const { return is_known_instance() && _offset >= 0; }
|
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;
|
virtual intptr_t get_con() const;
|
||||||
|
|
||||||
@ -969,10 +998,13 @@ public:
|
|||||||
const TypeKlassPtr* as_klass_type() const;
|
const TypeKlassPtr* as_klass_type() const;
|
||||||
|
|
||||||
virtual const TypePtr *add_offset( intptr_t offset ) const;
|
virtual const TypePtr *add_offset( intptr_t offset ) const;
|
||||||
// Return same type without a speculative part
|
|
||||||
virtual const Type* remove_speculative() const;
|
|
||||||
|
|
||||||
virtual const Type *xmeet(const Type *t) const;
|
// 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 *xdual() const; // Compute dual right now.
|
virtual const Type *xdual() const; // Compute dual right now.
|
||||||
// the core of the computation of the meet for TypeOopPtr and for its subclasses
|
// the core of the computation of the meet for TypeOopPtr and for its subclasses
|
||||||
virtual const Type *xmeet_helper(const Type *t) const;
|
virtual const Type *xmeet_helper(const Type *t) const;
|
||||||
@ -982,29 +1014,14 @@ public:
|
|||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
|
virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
|
||||||
#endif
|
#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------------------------------------
|
//------------------------------TypeInstPtr------------------------------------
|
||||||
// Class of Java object pointers, pointing either to non-array Java instances
|
// Class of Java object pointers, pointing either to non-array Java instances
|
||||||
// or to a Klass* (including array klasses).
|
// or to a Klass* (including array klasses).
|
||||||
class TypeInstPtr : public TypeOopPtr {
|
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 bool eq( const Type *t ) const;
|
||||||
virtual int hash() const; // Type specific hashing
|
virtual int hash() const; // Type specific hashing
|
||||||
|
|
||||||
@ -1040,7 +1057,10 @@ class TypeInstPtr : public TypeOopPtr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make a pointer to an oop.
|
// 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 */
|
/** Create constant type for a constant boxed value */
|
||||||
const Type* get_const_boxed_value() const;
|
const Type* get_const_boxed_value() const;
|
||||||
@ -1057,9 +1077,10 @@ class TypeInstPtr : public TypeOopPtr {
|
|||||||
virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
|
virtual const TypeOopPtr *cast_to_instance_id(int instance_id) const;
|
||||||
|
|
||||||
virtual const TypePtr *add_offset( intptr_t offset ) 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* 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
|
// the core of the computation of the meet of 2 types
|
||||||
virtual const Type *xmeet_helper(const Type *t) const;
|
virtual const Type *xmeet_helper(const Type *t) const;
|
||||||
@ -1081,7 +1102,8 @@ class TypeInstPtr : public TypeOopPtr {
|
|||||||
// Class of Java array pointers
|
// Class of Java array pointers
|
||||||
class TypeAryPtr : public TypeOopPtr {
|
class TypeAryPtr : public TypeOopPtr {
|
||||||
TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk,
|
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),
|
: TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative, inline_depth),
|
||||||
_ary(ary),
|
_ary(ary),
|
||||||
_is_autobox_cache(is_autobox_cache)
|
_is_autobox_cache(is_autobox_cache)
|
||||||
@ -1120,9 +1142,15 @@ public:
|
|||||||
|
|
||||||
bool is_autobox_cache() const { return _is_autobox_cache; }
|
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
|
// 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
|
// Return a 'ptr' version of this type
|
||||||
virtual const Type *cast_to_ptr_type(PTR ptr) const;
|
virtual const Type *cast_to_ptr_type(PTR ptr) const;
|
||||||
@ -1136,9 +1164,10 @@ public:
|
|||||||
|
|
||||||
virtual bool empty(void) const; // TRUE if type is vacuous
|
virtual bool empty(void) const; // TRUE if type is vacuous
|
||||||
virtual const TypePtr *add_offset( intptr_t offset ) 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* 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
|
// the core of the computation of the meet of 2 types
|
||||||
virtual const Type *xmeet_helper(const Type *t) const;
|
virtual const Type *xmeet_helper(const Type *t) const;
|
||||||
@ -1367,9 +1396,8 @@ public:
|
|||||||
static const TypeNarrowOop *BOTTOM;
|
static const TypeNarrowOop *BOTTOM;
|
||||||
static const TypeNarrowOop *NULL_PTR;
|
static const TypeNarrowOop *NULL_PTR;
|
||||||
|
|
||||||
virtual const Type* remove_speculative() const {
|
virtual const Type* remove_speculative() const;
|
||||||
return make(_ptrtype->remove_speculative()->is_ptr());
|
virtual const Type* cleanup_speculative() const;
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
|
virtual void dump2( Dict &d, uint depth, outputStream *st ) const;
|
||||||
|
@ -3801,10 +3801,6 @@ jint Arguments::apply_ergo() {
|
|||||||
AlwaysIncrementalInline = false;
|
AlwaysIncrementalInline = false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (IncrementalInline && FLAG_IS_DEFAULT(MaxNodeLimit)) {
|
|
||||||
// incremental inlining: bump MaxNodeLimit
|
|
||||||
FLAG_SET_DEFAULT(MaxNodeLimit, (intx)75000);
|
|
||||||
}
|
|
||||||
if (!UseTypeSpeculation && FLAG_IS_DEFAULT(TypeProfileLevel)) {
|
if (!UseTypeSpeculation && FLAG_IS_DEFAULT(TypeProfileLevel)) {
|
||||||
// nothing to use the profiling, turn if off
|
// nothing to use the profiling, turn if off
|
||||||
FLAG_SET_DEFAULT(TypeProfileLevel, 0);
|
FLAG_SET_DEFAULT(TypeProfileLevel, 0);
|
||||||
|
@ -1839,6 +1839,7 @@ const char* Deoptimization::_trap_reason_name[Reason_LIMIT] = {
|
|||||||
"predicate",
|
"predicate",
|
||||||
"loop_limit_check",
|
"loop_limit_check",
|
||||||
"speculate_class_check",
|
"speculate_class_check",
|
||||||
|
"speculate_null_check",
|
||||||
"rtm_state_change"
|
"rtm_state_change"
|
||||||
};
|
};
|
||||||
const char* Deoptimization::_trap_action_name[Action_LIMIT] = {
|
const char* Deoptimization::_trap_action_name[Action_LIMIT] = {
|
||||||
|
@ -60,6 +60,7 @@ class Deoptimization : AllStatic {
|
|||||||
Reason_predicate, // compiler generated predicate failed
|
Reason_predicate, // compiler generated predicate failed
|
||||||
Reason_loop_limit_check, // compiler generated loop limits check failed
|
Reason_loop_limit_check, // compiler generated loop limits check failed
|
||||||
Reason_speculate_class_check, // saw unexpected object class from type speculation
|
Reason_speculate_class_check, // saw unexpected object class from type speculation
|
||||||
|
Reason_speculate_null_check, // saw unexpected null from type speculation
|
||||||
Reason_rtm_state_change, // rtm state change detected
|
Reason_rtm_state_change, // rtm state change detected
|
||||||
Reason_LIMIT,
|
Reason_LIMIT,
|
||||||
// Note: Keep this enum in sync. with _trap_reason_name.
|
// Note: Keep this enum in sync. with _trap_reason_name.
|
||||||
@ -315,17 +316,27 @@ class Deoptimization : AllStatic {
|
|||||||
return Reason_null_check; // recorded per BCI as a null check
|
return Reason_null_check; // recorded per BCI as a null check
|
||||||
else if (reason == Reason_speculate_class_check)
|
else if (reason == Reason_speculate_class_check)
|
||||||
return Reason_class_check;
|
return Reason_class_check;
|
||||||
|
else if (reason == Reason_speculate_null_check)
|
||||||
|
return Reason_null_check;
|
||||||
else
|
else
|
||||||
return Reason_none;
|
return Reason_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool reason_is_speculate(int reason) {
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DeoptReason reason_null_check(bool speculative) {
|
||||||
|
return speculative ? Deoptimization::Reason_speculate_null_check : Deoptimization::Reason_null_check;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DeoptReason reason_class_check(bool speculative) {
|
||||||
|
return speculative ? Deoptimization::Reason_speculate_class_check : Deoptimization::Reason_class_check;
|
||||||
|
}
|
||||||
|
|
||||||
static uint per_method_trap_limit(int reason) {
|
static uint per_method_trap_limit(int reason) {
|
||||||
return reason_is_speculate(reason) ? (uint)PerMethodSpecTrapLimit : (uint)PerMethodTrapLimit;
|
return reason_is_speculate(reason) ? (uint)PerMethodSpecTrapLimit : (uint)PerMethodTrapLimit;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user