--- a/hotspot/src/share/vm/opto/type.cpp Mon May 06 19:49:23 2013 -0700
+++ b/hotspot/src/share/vm/opto/type.cpp Wed May 08 15:08:01 2013 -0700
@@ -2372,7 +2372,12 @@
_klass_is_exact(xk),
_is_ptr_to_narrowoop(false),
_is_ptr_to_narrowklass(false),
+ _is_ptr_to_boxed_value(false),
_instance_id(instance_id) {
+ if (Compile::current()->eliminate_boxing() && (t == InstPtr) &&
+ (offset > 0) && xk && (k != 0) && k->is_instance_klass()) {
+ _is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset);
+ }
#ifdef _LP64
if (_offset != 0) {
if (_offset == oopDesc::klass_offset_in_bytes()) {
@@ -2613,44 +2618,50 @@
//------------------------------make_from_constant-----------------------------
// Make a java pointer from an oop constant
-const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_constant) {
- assert(!o->is_null_object(), "null object not yet handled here.");
- ciKlass* klass = o->klass();
- if (klass->is_instance_klass()) {
- // Element is an instance
- if (require_constant) {
- if (!o->can_be_constant()) return NULL;
- } else if (!o->should_be_constant()) {
- return TypeInstPtr::make(TypePtr::NotNull, klass, true, NULL, 0);
- }
- return TypeInstPtr::make(o);
- } else if (klass->is_obj_array_klass()) {
- // Element is an object array. Recursively call ourself.
- const Type *etype =
+const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o,
+ bool require_constant,
+ bool is_autobox_cache) {
+ assert(!o->is_null_object(), "null object not yet handled here.");
+ ciKlass* klass = o->klass();
+ if (klass->is_instance_klass()) {
+ // Element is an instance
+ if (require_constant) {
+ if (!o->can_be_constant()) return NULL;
+ } else if (!o->should_be_constant()) {
+ return TypeInstPtr::make(TypePtr::NotNull, klass, true, NULL, 0);
+ }
+ return TypeInstPtr::make(o);
+ } else if (klass->is_obj_array_klass()) {
+ // Element is an object array. Recursively call ourself.
+ const TypeOopPtr *etype =
TypeOopPtr::make_from_klass_raw(klass->as_obj_array_klass()->element_klass());
- const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length()));
- // We used to pass NotNull in here, asserting that the sub-arrays
- // are all not-null. This is not true in generally, as code can
- // slam NULLs down in the subarrays.
- if (require_constant) {
- if (!o->can_be_constant()) return NULL;
- } else if (!o->should_be_constant()) {
- return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0);
- }
- const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
+ if (is_autobox_cache) {
+ // The pointers in the autobox arrays are always non-null.
+ etype = etype->cast_to_ptr_type(TypePtr::NotNull)->is_oopptr();
+ }
+ const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length()));
+ // We used to pass NotNull in here, asserting that the sub-arrays
+ // are all not-null. This is not true in generally, as code can
+ // slam NULLs down in the subarrays.
+ if (require_constant) {
+ if (!o->can_be_constant()) return NULL;
+ } else if (!o->should_be_constant()) {
+ return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0);
+ }
+ const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, is_autobox_cache);
return arr;
- } else if (klass->is_type_array_klass()) {
- // Element is an typeArray
+ } else if (klass->is_type_array_klass()) {
+ // Element is an typeArray
const Type* etype =
(Type*)get_const_basic_type(klass->as_type_array_klass()->element_type());
- const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length()));
- // We used to pass NotNull in here, asserting that the array pointer
- // is not-null. That was not true in general.
- if (require_constant) {
- if (!o->can_be_constant()) return NULL;
- } else if (!o->should_be_constant()) {
- return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0);
- }
+ const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length()));
+ // We used to pass NotNull in here, asserting that the array pointer
+ // is not-null. That was not true in general.
+ if (require_constant) {
+ if (!o->can_be_constant()) return NULL;
+ } else if (!o->should_be_constant()) {
+ return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0);
+ }
const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0);
return arr;
}
@@ -2856,6 +2867,28 @@
return result;
}
+/**
+ * Create constant type for a constant boxed value
+ */
+const Type* TypeInstPtr::get_const_boxed_value() const {
+ assert(is_ptr_to_boxed_value(), "should be called only for boxed value");
+ assert((const_oop() != NULL), "should be called only for constant object");
+ ciConstant constant = const_oop()->as_instance()->field_value_by_offset(offset());
+ BasicType bt = constant.basic_type();
+ switch (bt) {
+ case T_BOOLEAN: return TypeInt::make(constant.as_boolean());
+ case T_INT: return TypeInt::make(constant.as_int());
+ case T_CHAR: return TypeInt::make(constant.as_char());
+ case T_BYTE: return TypeInt::make(constant.as_byte());
+ case T_SHORT: return TypeInt::make(constant.as_short());
+ case T_FLOAT: return TypeF::make(constant.as_float());
+ case T_DOUBLE: return TypeD::make(constant.as_double());
+ case T_LONG: return TypeLong::make(constant.as_long());
+ default: break;
+ }
+ fatal(err_msg_res("Invalid boxed value type '%s'", type2name(bt)));
+ return NULL;
+}
//------------------------------cast_to_ptr_type-------------------------------
const Type *TypeInstPtr::cast_to_ptr_type(PTR ptr) const {
@@ -3330,18 +3363,18 @@
if (!xk) xk = ary->ary_must_be_exact();
assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed");
if (!UseExactTypes) xk = (ptr == Constant);
- return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id))->hashcons();
+ return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false))->hashcons();
}
//------------------------------make-------------------------------------------
-const TypeAryPtr *TypeAryPtr::make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id ) {
+const TypeAryPtr *TypeAryPtr::make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, bool is_autobox_cache) {
assert(!(k == NULL && ary->_elem->isa_int()),
"integral arrays must be pre-equipped with a class");
assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" );
if (!xk) xk = (o != NULL) || ary->ary_must_be_exact();
assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed");
if (!UseExactTypes) xk = (ptr == Constant);
- return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id))->hashcons();
+ return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache))->hashcons();
}
//------------------------------cast_to_ptr_type-------------------------------
@@ -3397,8 +3430,20 @@
jint max_hi = max_array_length(elem()->basic_type());
//if (index_not_size) --max_hi; // type of a valid array index, FTR
bool chg = false;
- if (lo < min_lo) { lo = min_lo; chg = true; }
- if (hi > max_hi) { hi = max_hi; chg = true; }
+ if (lo < min_lo) {
+ lo = min_lo;
+ if (size->is_con()) {
+ hi = lo;
+ }
+ chg = true;
+ }
+ if (hi > max_hi) {
+ hi = max_hi;
+ if (size->is_con()) {
+ lo = hi;
+ }
+ chg = true;
+ }
// Negative length arrays will produce weird intermediate dead fast-path code
if (lo > hi)
return TypeInt::ZERO;
@@ -3630,7 +3675,7 @@
//------------------------------xdual------------------------------------------
// Dual: compute field-by-field dual
const Type *TypeAryPtr::xdual() const {
- return new TypeAryPtr( dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id() );
+ return new TypeAryPtr( dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache() );
}
//----------------------interface_vs_oop---------------------------------------