< prev index next >
src/hotspot/share/ci/ciTypeFlow.cpp
Print this page
*** 29,38 ****
--- 29,39 ----
#include "ci/ciMethodData.hpp"
#include "ci/ciObjArrayKlass.hpp"
#include "ci/ciStreams.hpp"
#include "ci/ciTypeArrayKlass.hpp"
#include "ci/ciTypeFlow.hpp"
+ #include "ci/ciValueKlass.hpp"
#include "compiler/compileLog.hpp"
#include "interpreter/bytecode.hpp"
#include "interpreter/bytecodes.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
*** 269,278 ****
--- 270,280 ----
// interface, or array class. The meet of two types of the same
// kind is their least common ancestor. The meet of two types of
// different kinds is always java.lang.Object.
ciType* ciTypeFlow::StateVector::type_meet_internal(ciType* t1, ciType* t2, ciTypeFlow* analyzer) {
assert(t1 != t2, "checked in caller");
+
if (t1->equals(top_type())) {
return t2;
} else if (t2->equals(top_type())) {
return t1;
} else if (t1->is_primitive_type() || t2->is_primitive_type()) {
*** 289,299 ****
}
// At least one of the two types is a non-top primitive type.
// The other type is not equal to it. Fall to bottom.
return bottom_type();
! } else {
// Both types are non-top non-primitive types. That is,
// both types are either instanceKlasses or arrayKlasses.
ciKlass* object_klass = analyzer->env()->Object_klass();
ciKlass* k1 = t1->as_klass();
ciKlass* k2 = t2->as_klass();
--- 291,308 ----
}
// At least one of the two types is a non-top primitive type.
// The other type is not equal to it. Fall to bottom.
return bottom_type();
! }
!
! // Unwrap the types after gathering nullness information
! bool never_null1 = t1->is_never_null();
! bool never_null2 = t2->is_never_null();
! t1 = t1->unwrap();
! t2 = t2->unwrap();
!
// Both types are non-top non-primitive types. That is,
// both types are either instanceKlasses or arrayKlasses.
ciKlass* object_klass = analyzer->env()->Object_klass();
ciKlass* k1 = t1->as_klass();
ciKlass* k2 = t2->as_klass();
*** 324,342 ****
assert(k2 == ciObjArrayKlass::make(elem), "shortcut is OK");
return k2;
} else {
return ciObjArrayKlass::make(elem);
}
} else {
return object_klass;
}
} else {
// Must be two plain old instance klasses.
assert(k1->is_instance_klass(), "previous cases handle non-instances");
assert(k2->is_instance_klass(), "previous cases handle non-instances");
! return k1->least_common_ancestor(k2);
}
}
}
// ------------------------------------------------------------------
--- 333,360 ----
assert(k2 == ciObjArrayKlass::make(elem), "shortcut is OK");
return k2;
} else {
return ciObjArrayKlass::make(elem);
}
+ } else if (k1->is_value_array_klass() || k2->is_value_array_klass()) {
+ ciKlass* elem1 = k1->as_array_klass()->element_klass();
+ ciKlass* elem2 = k2->as_array_klass()->element_klass();
+ ciKlass* elem = type_meet_internal(elem1, elem2, analyzer)->as_klass();
+ return ciArrayKlass::make(elem);
} else {
return object_klass;
}
} else {
// Must be two plain old instance klasses.
assert(k1->is_instance_klass(), "previous cases handle non-instances");
assert(k2->is_instance_klass(), "previous cases handle non-instances");
! ciType* result = k1->least_common_ancestor(k2);
! if (never_null1 && never_null2 && result->is_valuetype()) {
! // Both value types are never null, mark the result as never null
! result = analyzer->mark_as_never_null(result);
}
+ return result;
}
}
// ------------------------------------------------------------------
*** 394,410 ****
// even if it were possible for an OSR entry point to be at bci zero.
}
// "Push" the method signature into the first few locals.
state->set_stack_size(-max_locals());
if (!method()->is_static()) {
! state->push(method()->holder());
assert(state->tos() == state->local(0), "");
}
for (ciSignatureStream str(method()->signature());
!str.at_return_type();
str.next()) {
! state->push_translate(str.type());
}
// Set the rest of the locals to bottom.
Cell cell = state->next_cell(state->tos());
state->set_stack_size(0);
int limit = state->limit_cell();
--- 412,437 ----
// even if it were possible for an OSR entry point to be at bci zero.
}
// "Push" the method signature into the first few locals.
state->set_stack_size(-max_locals());
if (!method()->is_static()) {
! ciType* holder = method()->holder();
! if (holder->is_valuetype()) {
! // The receiver is never null
! holder = mark_as_never_null(holder);
! }
! state->push(holder);
assert(state->tos() == state->local(0), "");
}
for (ciSignatureStream str(method()->signature());
!str.at_return_type();
str.next()) {
! ciType* arg = str.type();
! if (str.is_never_null()) {
! arg = mark_as_never_null(arg);
! }
! state->push_translate(arg);
}
// Set the rest of the locals to bottom.
Cell cell = state->next_cell(state->tos());
state->set_stack_size(0);
int limit = state->limit_cell();
*** 546,561 ****
}
}
}
// ------------------------------------------------------------------
! // ciTypeFlow::StateVector::do_aaload
! void ciTypeFlow::StateVector::do_aaload(ciBytecodeStream* str) {
pop_int();
! ciObjArrayKlass* array_klass = pop_objArray();
if (array_klass == NULL) {
! // Did aaload on a null reference; push a null and ignore the exception.
// This instruction will never continue normally. All we have to do
// is report a value that will meet correctly with any downstream
// reference types on paths that will truly be executed. This null type
// meets with any reference type to yield that same reference type.
// (The compiler will generate an unconditional exception here.)
--- 573,588 ----
}
}
}
// ------------------------------------------------------------------
! // ciTypeFlow::StateVector::do_aload
! void ciTypeFlow::StateVector::do_aload(ciBytecodeStream* str) {
pop_int();
! ciArrayKlass* array_klass = pop_objOrValueArray();
if (array_klass == NULL) {
! // Did aload on a null reference; push a null and ignore the exception.
// This instruction will never continue normally. All we have to do
// is report a value that will meet correctly with any downstream
// reference types on paths that will truly be executed. This null type
// meets with any reference type to yield that same reference type.
// (The compiler will generate an unconditional exception here.)
*** 576,587 ****
--- 603,619 ----
trap(str, element_klass,
Deoptimization::make_trap_request
(Deoptimization::Reason_unloaded,
Deoptimization::Action_reinterpret));
} else {
+ if (element_klass->is_valuetype()) {
+ // Value type array elements are never null
+ push(outer()->mark_as_never_null(element_klass));
+ } else {
push_object(element_klass);
}
+ }
}
// ------------------------------------------------------------------
// ciTypeFlow::StateVector::do_checkcast
*** 595,606 ****
--- 627,644 ----
// 2) C2 does an OSR compile in a later block (see bug 4778368).
pop_object();
do_null_assert(klass);
} else {
pop_object();
+ if (str->is_klass_never_null()) {
+ // Casting to a Q-Type contains a NULL check
+ assert(klass->is_valuetype(), "must be a value type");
+ push(outer()->mark_as_never_null(klass));
+ } else {
push_object(klass);
}
+ }
}
// ------------------------------------------------------------------
// ciTypeFlow::StateVector::do_getfield
void ciTypeFlow::StateVector::do_getfield(ciBytecodeStream* str) {
*** 637,646 ****
--- 675,688 ----
// here can make an OSR entry point unreachable, triggering the
// assert on non_osr_block in ciTypeFlow::get_start_state.
// (See bug 4379915.)
do_null_assert(field_type->as_klass());
} else {
+ if (field->is_flattenable()) {
+ // A flattenable field is never null
+ field_type = outer()->mark_as_never_null(field_type);
+ }
push_translate(field_type);
}
}
}
*** 704,713 ****
--- 746,758 ----
// ever sees a non-null value, loading has occurred.
//
// See do_getstatic() for similar explanation, as well as bug 4684993.
do_null_assert(return_type->as_klass());
} else {
+ if (sigstr.is_never_null()) {
+ return_type = outer()->mark_as_never_null(return_type);
+ }
push_translate(return_type);
}
}
}
}
*** 727,743 ****
// OutOfMemoryError in the CI while loading constant
push_null();
outer()->record_failure("ldc did not link");
return;
}
! if (basic_type == T_OBJECT || basic_type == T_ARRAY) {
ciObject* obj = con.as_object();
if (obj->is_null_object()) {
push_null();
} else {
assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass");
! push_object(obj->klass());
}
} else {
push_translate(ciType::make(basic_type));
}
}
--- 772,792 ----
// OutOfMemoryError in the CI while loading constant
push_null();
outer()->record_failure("ldc did not link");
return;
}
! if (basic_type == T_OBJECT || basic_type == T_VALUETYPE || basic_type == T_ARRAY) {
ciObject* obj = con.as_object();
if (obj->is_null_object()) {
push_null();
} else {
assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass");
! ciType* type = obj->klass();
! if (type->is_valuetype()) {
! type = outer()->mark_as_never_null(type);
! }
! push(type);
}
} else {
push_translate(ciType::make(basic_type));
}
}
*** 769,778 ****
--- 818,863 ----
push_object(klass);
}
}
// ------------------------------------------------------------------
+ // ciTypeFlow::StateVector::do_defaultvalue
+ void ciTypeFlow::StateVector::do_defaultvalue(ciBytecodeStream* str) {
+ bool will_link;
+ ciKlass* klass = str->get_klass(will_link);
+ if (!will_link) {
+ trap(str, klass, str->get_klass_index());
+ } else {
+ // The default value type is never null
+ push(outer()->mark_as_never_null(klass));
+ }
+ }
+
+ // ------------------------------------------------------------------
+ // ciTypeFlow::StateVector::do_withfield
+ void ciTypeFlow::StateVector::do_withfield(ciBytecodeStream* str) {
+ bool will_link;
+ ciField* field = str->get_field(will_link);
+ ciKlass* klass = field->holder();
+ if (!will_link) {
+ trap(str, klass, str->get_field_holder_index());
+ } else {
+ ciType* type = pop_value();
+ ciType* field_type = field->type();
+ assert(field_type->is_loaded(), "field type must be loaded");
+ if (field_type->is_two_word()) {
+ ciType* type2 = pop_value();
+ assert(type2->is_two_word(), "must be 2nd half");
+ assert(type == half_type(type2), "must be 2nd half");
+ }
+ pop_object();
+ // The newly created value type can never be null
+ push(outer()->mark_as_never_null(klass));
+ }
+ }
+
+ // ------------------------------------------------------------------
// ciTypeFlow::StateVector::do_newarray
void ciTypeFlow::StateVector::do_newarray(ciBytecodeStream* str) {
pop_int();
ciKlass* klass = ciTypeArrayKlass::make((BasicType)str->get_index());
push_object(klass);
*** 873,889 ****
tty->print_cr(">> Interpreting bytecode %d:%s", str->cur_bci(),
Bytecodes::name(str->cur_bc()));
}
switch(str->cur_bc()) {
! case Bytecodes::_aaload: do_aaload(str); break;
case Bytecodes::_aastore:
{
pop_object();
pop_int();
! pop_objArray();
break;
}
case Bytecodes::_aconst_null:
{
push_null();
--- 958,974 ----
tty->print_cr(">> Interpreting bytecode %d:%s", str->cur_bci(),
Bytecodes::name(str->cur_bc()));
}
switch(str->cur_bc()) {
! case Bytecodes::_aaload: do_aload(str); break;
case Bytecodes::_aastore:
{
pop_object();
pop_int();
! pop_objOrValueArray();
break;
}
case Bytecodes::_aconst_null:
{
push_null();
*** 901,911 ****
bool will_link;
ciKlass* element_klass = str->get_klass(will_link);
if (!will_link) {
trap(str, element_klass, str->get_klass_index());
} else {
! push_object(ciObjArrayKlass::make(element_klass));
}
break;
}
case Bytecodes::_areturn:
case Bytecodes::_ifnonnull:
--- 986,996 ----
bool will_link;
ciKlass* element_klass = str->get_klass(will_link);
if (!will_link) {
trap(str, element_klass, str->get_klass_index());
} else {
! push_object(ciArrayKlass::make(element_klass));
}
break;
}
case Bytecodes::_areturn:
case Bytecodes::_ifnonnull:
*** 1433,1442 ****
--- 1518,1530 ----
case Bytecodes::_multianewarray: do_multianewarray(str); break;
case Bytecodes::_new: do_new(str); break;
+ case Bytecodes::_defaultvalue: do_defaultvalue(str); break;
+ case Bytecodes::_withfield: do_withfield(str); break;
+
case Bytecodes::_newarray: do_newarray(str); break;
case Bytecodes::_pop:
{
pop();
*** 1460,1469 ****
--- 1548,1558 ----
ciType* value2 = pop_value();
push(value1);
push(value2);
break;
}
+
case Bytecodes::_wide:
default:
{
// The iterator should skip this.
ShouldNotReachHere();
*** 1743,1755 ****
_successors->append_if_missing(block);
}
break;
}
! case Bytecodes::_athrow: case Bytecodes::_ireturn:
! case Bytecodes::_lreturn: case Bytecodes::_freturn:
! case Bytecodes::_dreturn: case Bytecodes::_areturn:
case Bytecodes::_return:
_successors =
new (arena) GrowableArray<Block*>(arena, 1, 0, NULL);
// No successors
break;
--- 1832,1847 ----
_successors->append_if_missing(block);
}
break;
}
! case Bytecodes::_athrow:
! case Bytecodes::_ireturn:
! case Bytecodes::_lreturn:
! case Bytecodes::_freturn:
! case Bytecodes::_dreturn:
! case Bytecodes::_areturn:
case Bytecodes::_return:
_successors =
new (arena) GrowableArray<Block*>(arena, 1, 0, NULL);
// No successors
break;
*** 2976,2985 ****
--- 3068,3082 ----
// Record the first failure reason.
_failure_reason = reason;
}
}
+ ciType* ciTypeFlow::mark_as_never_null(ciType* type) {
+ // Wrap the type to carry the information that it is never null
+ return env()->make_never_null_wrapper(type);
+ }
+
#ifndef PRODUCT
// ------------------------------------------------------------------
// ciTypeFlow::print_on
void ciTypeFlow::print_on(outputStream* st) const {
// Walk through CI blocks
< prev index next >