< prev index next >

src/hotspot/share/opto/type.cpp

Print this page

        

*** 21,32 **** --- 21,34 ---- * questions. * */ #include "precompiled.hpp" + #include "ci/ciField.hpp" #include "ci/ciMethodData.hpp" #include "ci/ciTypeFlow.hpp" + #include "ci/ciValueKlass.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "compiler/compileLog.hpp" #include "libadt/dict.hpp" #include "memory/oopFactory.hpp"
*** 44,53 **** --- 46,101 ---- // Optimization - Graph Style // Dictionary of types shared among compilations. Dict* Type::_shared_type_dict = NULL; + const Type::Offset Type::Offset::top(Type::OffsetTop); + const Type::Offset Type::Offset::bottom(Type::OffsetBot); + + const Type::Offset Type::Offset::meet(const Type::Offset other) const { + // Either is 'TOP' offset? Return the other offset! + int offset = other._offset; + if (_offset == OffsetTop) return Offset(offset); + if (offset == OffsetTop) return Offset(_offset); + // If either is different, return 'BOTTOM' offset + if (_offset != offset) return bottom; + return Offset(_offset); + } + + const Type::Offset Type::Offset::dual() const { + if (_offset == OffsetTop) return bottom;// Map 'TOP' into 'BOTTOM' + if (_offset == OffsetBot) return top;// Map 'BOTTOM' into 'TOP' + return Offset(_offset); // Map everything else into self + } + + const Type::Offset Type::Offset::add(intptr_t offset) const { + // Adding to 'TOP' offset? Return 'TOP'! + if (_offset == OffsetTop || offset == OffsetTop) return top; + // Adding to 'BOTTOM' offset? Return 'BOTTOM'! + if (_offset == OffsetBot || offset == OffsetBot) return bottom; + // Addition overflows or "accidentally" equals to OffsetTop? Return 'BOTTOM'! + offset += (intptr_t)_offset; + if (offset != (int)offset || offset == OffsetTop) return bottom; + + // assert( _offset >= 0 && _offset+offset >= 0, "" ); + // It is possible to construct a negative offset during PhaseCCP + + return Offset((int)offset); // Sum valid offsets + } + + void Type::Offset::dump2(outputStream *st) const { + if (_offset == 0) { + return; + } else if (_offset == OffsetTop) { + st->print("+top"); + } + else if (_offset == OffsetBot) { + st->print("+bot"); + } else if (_offset) { + st->print("+%d", _offset); + } + } // Array which maps compiler types to Basic Types const Type::TypeInfo Type::_type_info[Type::lastype] = { { Bad, T_ILLEGAL, "bad", false, Node::NotAMachineReg, relocInfo::none }, // Bad { Control, T_ILLEGAL, "control", false, 0, relocInfo::none }, // Control
*** 83,92 **** --- 131,141 ---- { Bad, T_ILLEGAL, "vectord:", false, Op_VecD, relocInfo::none }, // VectorD { Bad, T_ILLEGAL, "vectorx:", false, Op_VecX, relocInfo::none }, // VectorX { Bad, T_ILLEGAL, "vectory:", false, Op_VecY, relocInfo::none }, // VectorY { Bad, T_ILLEGAL, "vectorz:", false, Op_VecZ, relocInfo::none }, // VectorZ #endif + { Bad, T_VALUETYPE, "value:", false, Node::NotAMachineReg, relocInfo::none }, // ValueType { Bad, T_ADDRESS, "anyptr:", false, Op_RegP, relocInfo::none }, // AnyPtr { Bad, T_ADDRESS, "rawptr:", false, Op_RegP, relocInfo::none }, // RawPtr { Bad, T_OBJECT, "oop:", true, Op_RegP, relocInfo::oop_type }, // OopPtr { Bad, T_OBJECT, "inst:", true, Op_RegP, relocInfo::oop_type }, // InstPtr { Bad, T_OBJECT, "ary:", true, Op_RegP, relocInfo::oop_type }, // AryPtr
*** 213,222 **** --- 262,281 ---- case T_ADDRESS: assert(type->is_return_address(), ""); return TypeRawPtr::make((address)(intptr_t)type->as_return_address()->bci()); + case T_VALUETYPE: { + bool is_never_null = type->is_never_null(); + ciValueKlass* vk = type->unwrap()->as_value_klass(); + if (vk->is_scalarizable() && is_never_null) { + return TypeValueType::make(vk); + } else { + return TypeOopPtr::make_from_klass(vk)->join_speculative(is_never_null ? TypePtr::NOTNULL : TypePtr::BOTTOM); + } + } + default: // make sure we did not mix up the cases: assert(type != ciTypeFlow::StateVector::bottom_type(), ""); assert(type != ciTypeFlow::StateVector::top_type(), ""); assert(type != ciTypeFlow::StateVector::null_type(), "");
*** 241,250 **** --- 300,310 ---- case T_INT: return TypeInt::make(constant.as_int()); case T_LONG: return TypeLong::make(constant.as_long()); case T_FLOAT: return TypeF::make(constant.as_float()); case T_DOUBLE: return TypeD::make(constant.as_double()); case T_ARRAY: + case T_VALUETYPE: case T_OBJECT: { const Type* con_type = NULL; ciObject* oop_constant = constant.as_object(); if (oop_constant->is_null_object()) { con_type = Type::get_zero_type(T_OBJECT);
*** 278,293 **** --- 338,355 ---- static ciConstant check_mismatched_access(ciConstant con, BasicType loadbt, bool is_unsigned) { BasicType conbt = con.basic_type(); switch (conbt) { case T_BOOLEAN: conbt = T_BYTE; break; case T_ARRAY: conbt = T_OBJECT; break; + case T_VALUETYPE: conbt = T_OBJECT; break; default: break; } switch (loadbt) { case T_BOOLEAN: loadbt = T_BYTE; break; case T_NARROWOOP: loadbt = T_OBJECT; break; case T_ARRAY: loadbt = T_OBJECT; break; + case T_VALUETYPE: loadbt = T_OBJECT; break; case T_ADDRESS: loadbt = T_OBJECT; break; default: break; } if (conbt == loadbt) { if (is_unsigned && conbt == T_BYTE) {
*** 521,533 **** const Type **floop =(const Type**)shared_type_arena->Amalloc_4(2*sizeof(Type*)); floop[0] = Type::CONTROL; floop[1] = TypeInt::INT; TypeTuple::LOOPBODY = TypeTuple::make( 2, floop ); ! TypePtr::NULL_PTR= TypePtr::make(AnyPtr, TypePtr::Null, 0); ! TypePtr::NOTNULL = TypePtr::make(AnyPtr, TypePtr::NotNull, OffsetBot); ! TypePtr::BOTTOM = TypePtr::make(AnyPtr, TypePtr::BotPTR, OffsetBot); TypeRawPtr::BOTTOM = TypeRawPtr::make( TypePtr::BotPTR ); TypeRawPtr::NOTNULL= TypeRawPtr::make( TypePtr::NotNull ); const Type **fmembar = TypeTuple::fields(0); --- 583,595 ---- const Type **floop =(const Type**)shared_type_arena->Amalloc_4(2*sizeof(Type*)); floop[0] = Type::CONTROL; floop[1] = TypeInt::INT; TypeTuple::LOOPBODY = TypeTuple::make( 2, floop ); ! TypePtr::NULL_PTR= TypePtr::make(AnyPtr, TypePtr::Null, Offset(0)); ! TypePtr::NOTNULL = TypePtr::make(AnyPtr, TypePtr::NotNull, Offset::bottom); ! TypePtr::BOTTOM = TypePtr::make(AnyPtr, TypePtr::BotPTR, Offset::bottom); TypeRawPtr::BOTTOM = TypeRawPtr::make( TypePtr::BotPTR ); TypeRawPtr::NOTNULL= TypeRawPtr::make( TypePtr::NotNull ); const Type **fmembar = TypeTuple::fields(0);
*** 540,555 **** TypeInstPtr::NOTNULL = TypeInstPtr::make(TypePtr::NotNull, current->env()->Object_klass()); TypeInstPtr::BOTTOM = TypeInstPtr::make(TypePtr::BotPTR, current->env()->Object_klass()); TypeInstPtr::MIRROR = TypeInstPtr::make(TypePtr::NotNull, current->env()->Class_klass()); TypeInstPtr::MARK = TypeInstPtr::make(TypePtr::BotPTR, current->env()->Object_klass(), ! false, 0, oopDesc::mark_offset_in_bytes()); TypeInstPtr::KLASS = TypeInstPtr::make(TypePtr::BotPTR, current->env()->Object_klass(), ! false, 0, oopDesc::klass_offset_in_bytes()); ! TypeOopPtr::BOTTOM = TypeOopPtr::make(TypePtr::BotPTR, OffsetBot, TypeOopPtr::InstanceBot); ! TypeMetadataPtr::BOTTOM = TypeMetadataPtr::make(TypePtr::BotPTR, NULL, OffsetBot); TypeNarrowOop::NULL_PTR = TypeNarrowOop::make( TypePtr::NULL_PTR ); TypeNarrowOop::BOTTOM = TypeNarrowOop::make( TypeInstPtr::BOTTOM ); TypeNarrowKlass::NULL_PTR = TypeNarrowKlass::make( TypePtr::NULL_PTR ); --- 602,619 ---- TypeInstPtr::NOTNULL = TypeInstPtr::make(TypePtr::NotNull, current->env()->Object_klass()); TypeInstPtr::BOTTOM = TypeInstPtr::make(TypePtr::BotPTR, current->env()->Object_klass()); TypeInstPtr::MIRROR = TypeInstPtr::make(TypePtr::NotNull, current->env()->Class_klass()); TypeInstPtr::MARK = TypeInstPtr::make(TypePtr::BotPTR, current->env()->Object_klass(), ! false, 0, Offset(oopDesc::mark_offset_in_bytes())); TypeInstPtr::KLASS = TypeInstPtr::make(TypePtr::BotPTR, current->env()->Object_klass(), ! false, 0, Offset(oopDesc::klass_offset_in_bytes())); ! TypeOopPtr::BOTTOM = TypeOopPtr::make(TypePtr::BotPTR, Offset::bottom, TypeOopPtr::InstanceBot); ! ! TypeMetadataPtr::BOTTOM = TypeMetadataPtr::make(TypePtr::BotPTR, NULL, Offset::bottom); ! TypeValueType::BOTTOM = TypeValueType::make(NULL); TypeNarrowOop::NULL_PTR = TypeNarrowOop::make( TypePtr::NULL_PTR ); TypeNarrowOop::BOTTOM = TypeNarrowOop::make( TypeInstPtr::BOTTOM ); TypeNarrowKlass::NULL_PTR = TypeNarrowKlass::make( TypePtr::NULL_PTR );
*** 562,608 **** mreg2type[Op_RegF] = Type::FLOAT; mreg2type[Op_RegD] = Type::DOUBLE; mreg2type[Op_RegL] = TypeLong::LONG; mreg2type[Op_RegFlags] = TypeInt::CC; ! TypeAryPtr::RANGE = TypeAryPtr::make( TypePtr::BotPTR, TypeAry::make(Type::BOTTOM,TypeInt::POS), NULL /* current->env()->Object_klass() */, false, arrayOopDesc::length_offset_in_bytes()); ! TypeAryPtr::NARROWOOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeNarrowOop::BOTTOM, TypeInt::POS), NULL /*ciArrayKlass::make(o)*/, false, Type::OffsetBot); #ifdef _LP64 if (UseCompressedOops) { assert(TypeAryPtr::NARROWOOPS->is_ptr_to_narrowoop(), "array of narrow oops must be ptr to narrow oop"); TypeAryPtr::OOPS = TypeAryPtr::NARROWOOPS; } else #endif { // There is no shared klass for Object[]. See note in TypeAryPtr::klass(). ! TypeAryPtr::OOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInstPtr::BOTTOM,TypeInt::POS), NULL /*ciArrayKlass::make(o)*/, false, Type::OffsetBot); } ! TypeAryPtr::BYTES = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::BYTE ,TypeInt::POS), ciTypeArrayKlass::make(T_BYTE), true, Type::OffsetBot); ! TypeAryPtr::SHORTS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::SHORT ,TypeInt::POS), ciTypeArrayKlass::make(T_SHORT), true, Type::OffsetBot); ! TypeAryPtr::CHARS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::CHAR ,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, Type::OffsetBot); ! TypeAryPtr::INTS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::INT ,TypeInt::POS), ciTypeArrayKlass::make(T_INT), true, Type::OffsetBot); ! TypeAryPtr::LONGS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeLong::LONG ,TypeInt::POS), ciTypeArrayKlass::make(T_LONG), true, Type::OffsetBot); ! TypeAryPtr::FLOATS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::FLOAT ,TypeInt::POS), ciTypeArrayKlass::make(T_FLOAT), true, Type::OffsetBot); ! TypeAryPtr::DOUBLES = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::DOUBLE ,TypeInt::POS), ciTypeArrayKlass::make(T_DOUBLE), true, Type::OffsetBot); // Nobody should ask _array_body_type[T_NARROWOOP]. Use NULL as assert. TypeAryPtr::_array_body_type[T_NARROWOOP] = NULL; TypeAryPtr::_array_body_type[T_OBJECT] = TypeAryPtr::OOPS; TypeAryPtr::_array_body_type[T_ARRAY] = TypeAryPtr::OOPS; // arrays are stored in oop arrays TypeAryPtr::_array_body_type[T_BYTE] = TypeAryPtr::BYTES; TypeAryPtr::_array_body_type[T_BOOLEAN] = TypeAryPtr::BYTES; // boolean[] is a byte array TypeAryPtr::_array_body_type[T_SHORT] = TypeAryPtr::SHORTS; TypeAryPtr::_array_body_type[T_CHAR] = TypeAryPtr::CHARS; TypeAryPtr::_array_body_type[T_INT] = TypeAryPtr::INTS; TypeAryPtr::_array_body_type[T_LONG] = TypeAryPtr::LONGS; TypeAryPtr::_array_body_type[T_FLOAT] = TypeAryPtr::FLOATS; TypeAryPtr::_array_body_type[T_DOUBLE] = TypeAryPtr::DOUBLES; ! TypeKlassPtr::OBJECT = TypeKlassPtr::make( TypePtr::NotNull, current->env()->Object_klass(), 0 ); ! TypeKlassPtr::OBJECT_OR_NULL = TypeKlassPtr::make( TypePtr::BotPTR, current->env()->Object_klass(), 0 ); const Type **fi2c = TypeTuple::fields(2); fi2c[TypeFunc::Parms+0] = TypeInstPtr::BOTTOM; // Method* fi2c[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // argument pointer TypeTuple::START_I2C = TypeTuple::make(TypeFunc::Parms+2, fi2c); --- 626,674 ---- mreg2type[Op_RegF] = Type::FLOAT; mreg2type[Op_RegD] = Type::DOUBLE; mreg2type[Op_RegL] = TypeLong::LONG; mreg2type[Op_RegFlags] = TypeInt::CC; ! TypeAryPtr::RANGE = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::BOTTOM,TypeInt::POS), NULL /* current->env()->Object_klass() */, false, Offset(arrayOopDesc::length_offset_in_bytes())); ! TypeAryPtr::NARROWOOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeNarrowOop::BOTTOM, TypeInt::POS), NULL /*ciArrayKlass::make(o)*/, false, Offset::bottom); #ifdef _LP64 if (UseCompressedOops) { assert(TypeAryPtr::NARROWOOPS->is_ptr_to_narrowoop(), "array of narrow oops must be ptr to narrow oop"); TypeAryPtr::OOPS = TypeAryPtr::NARROWOOPS; } else #endif { // There is no shared klass for Object[]. See note in TypeAryPtr::klass(). ! TypeAryPtr::OOPS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInstPtr::BOTTOM,TypeInt::POS), NULL /*ciArrayKlass::make(o)*/, false, Offset::bottom); } ! TypeAryPtr::BYTES = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::BYTE ,TypeInt::POS), ciTypeArrayKlass::make(T_BYTE), true, Offset::bottom); ! TypeAryPtr::SHORTS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::SHORT ,TypeInt::POS), ciTypeArrayKlass::make(T_SHORT), true, Offset::bottom); ! TypeAryPtr::CHARS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::CHAR ,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, Offset::bottom); ! TypeAryPtr::INTS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeInt::INT ,TypeInt::POS), ciTypeArrayKlass::make(T_INT), true, Offset::bottom); ! TypeAryPtr::LONGS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeLong::LONG ,TypeInt::POS), ciTypeArrayKlass::make(T_LONG), true, Offset::bottom); ! TypeAryPtr::FLOATS = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::FLOAT ,TypeInt::POS), ciTypeArrayKlass::make(T_FLOAT), true, Offset::bottom); ! TypeAryPtr::DOUBLES = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(Type::DOUBLE ,TypeInt::POS), ciTypeArrayKlass::make(T_DOUBLE), true, Offset::bottom); ! TypeAryPtr::VALUES = TypeAryPtr::make(TypePtr::BotPTR, TypeAry::make(TypeValueType::BOTTOM,TypeInt::POS), NULL, false, Offset::bottom); // Nobody should ask _array_body_type[T_NARROWOOP]. Use NULL as assert. TypeAryPtr::_array_body_type[T_NARROWOOP] = NULL; TypeAryPtr::_array_body_type[T_OBJECT] = TypeAryPtr::OOPS; + TypeAryPtr::_array_body_type[T_VALUETYPE] = TypeAryPtr::OOPS; TypeAryPtr::_array_body_type[T_ARRAY] = TypeAryPtr::OOPS; // arrays are stored in oop arrays TypeAryPtr::_array_body_type[T_BYTE] = TypeAryPtr::BYTES; TypeAryPtr::_array_body_type[T_BOOLEAN] = TypeAryPtr::BYTES; // boolean[] is a byte array TypeAryPtr::_array_body_type[T_SHORT] = TypeAryPtr::SHORTS; TypeAryPtr::_array_body_type[T_CHAR] = TypeAryPtr::CHARS; TypeAryPtr::_array_body_type[T_INT] = TypeAryPtr::INTS; TypeAryPtr::_array_body_type[T_LONG] = TypeAryPtr::LONGS; TypeAryPtr::_array_body_type[T_FLOAT] = TypeAryPtr::FLOATS; TypeAryPtr::_array_body_type[T_DOUBLE] = TypeAryPtr::DOUBLES; ! TypeKlassPtr::OBJECT = TypeKlassPtr::make(TypePtr::NotNull, current->env()->Object_klass(), Offset(0) ); ! TypeKlassPtr::OBJECT_OR_NULL = TypeKlassPtr::make(TypePtr::BotPTR, current->env()->Object_klass(), Offset(0) ); const Type **fi2c = TypeTuple::fields(2); fi2c[TypeFunc::Parms+0] = TypeInstPtr::BOTTOM; // Method* fi2c[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // argument pointer TypeTuple::START_I2C = TypeTuple::make(TypeFunc::Parms+2, fi2c);
*** 637,646 **** --- 703,713 ---- _const_basic_type[T_LONG] = TypeLong::LONG; _const_basic_type[T_FLOAT] = Type::FLOAT; _const_basic_type[T_DOUBLE] = Type::DOUBLE; _const_basic_type[T_OBJECT] = TypeInstPtr::BOTTOM; _const_basic_type[T_ARRAY] = TypeInstPtr::BOTTOM; // there is no separate bottom for arrays + _const_basic_type[T_VALUETYPE] = TypeInstPtr::BOTTOM; _const_basic_type[T_VOID] = TypePtr::NULL_PTR; // reflection represents void this way _const_basic_type[T_ADDRESS] = TypeRawPtr::BOTTOM; // both interpreter return addresses & random raw ptrs _const_basic_type[T_CONFLICT] = Type::BOTTOM; // why not? _zero_type[T_NARROWOOP] = TypeNarrowOop::NULL_PTR;
*** 653,662 **** --- 720,730 ---- _zero_type[T_LONG] = TypeLong::ZERO; _zero_type[T_FLOAT] = TypeF::ZERO; _zero_type[T_DOUBLE] = TypeD::ZERO; _zero_type[T_OBJECT] = TypePtr::NULL_PTR; _zero_type[T_ARRAY] = TypePtr::NULL_PTR; // null array is null oop + _zero_type[T_VALUETYPE] = TypePtr::NULL_PTR; _zero_type[T_ADDRESS] = TypePtr::NULL_PTR; // raw pointers use the same null _zero_type[T_VOID] = Type::TOP; // the only void value is no value at all // get_zero_type() should not happen for T_CONFLICT _zero_type[T_CONFLICT]= NULL;
*** 905,914 **** --- 973,985 ---- return t->xmeet(this); case NarrowKlass: return t->xmeet(this); + case ValueType: + return t->xmeet(this); + case Bad: // Type check default: // Bogus type not in lattice typerr(t); return Type::BOTTOM;
*** 972,981 **** --- 1043,1053 ---- Bad, // VectorS - handled in v-call Bad, // VectorD - handled in v-call Bad, // VectorX - handled in v-call Bad, // VectorY - handled in v-call Bad, // VectorZ - handled in v-call + Bad, // ValueType - handled in v-call Bad, // AnyPtr - handled in v-call Bad, // RawPtr - handled in v-call Bad, // OopPtr - handled in v-call Bad, // InstPtr - handled in v-call
*** 1867,1882 **** const TypeTuple *TypeTuple::INT_PAIR; const TypeTuple *TypeTuple::LONG_PAIR; const TypeTuple *TypeTuple::INT_CC_PAIR; const TypeTuple *TypeTuple::LONG_CC_PAIR; //------------------------------make------------------------------------------- // Make a TypeTuple from the range of a method signature ! const TypeTuple *TypeTuple::make_range(ciSignature* sig) { ciType* return_type = sig->return_type(); uint arg_cnt = return_type->size(); const Type **field_array = fields(arg_cnt); switch (return_type->basic_type()) { case T_LONG: field_array[TypeFunc::Parms] = TypeLong::LONG; field_array[TypeFunc::Parms+1] = Type::HALF; --- 1939,1976 ---- const TypeTuple *TypeTuple::INT_PAIR; const TypeTuple *TypeTuple::LONG_PAIR; const TypeTuple *TypeTuple::INT_CC_PAIR; const TypeTuple *TypeTuple::LONG_CC_PAIR; + static void collect_value_fields(ciValueKlass* vk, const Type** field_array, uint& pos, ExtendedSignature& sig_cc) { + for (int j = 0; j < vk->nof_nonstatic_fields(); j++) { + ciField* field = vk->nonstatic_field_at(j); + BasicType bt = field->type()->basic_type(); + const Type* ft = Type::get_const_type(field->type()); + field_array[pos++] = ft; + if (type2size[bt] == 2) { + field_array[pos++] = Type::HALF; + } + // Skip reserved arguments + while (SigEntry::next_is_reserved(sig_cc, bt)) { + field_array[pos++] = Type::get_const_basic_type(bt); + if (type2size[bt] == 2) { + field_array[pos++] = Type::HALF; + } + } + } + } //------------------------------make------------------------------------------- // Make a TypeTuple from the range of a method signature ! const TypeTuple *TypeTuple::make_range(ciSignature* sig, bool ret_vt_fields) { ciType* return_type = sig->return_type(); uint arg_cnt = return_type->size(); + if (ret_vt_fields) { + arg_cnt = return_type->as_value_klass()->value_arg_slots() + 1; + } + const Type **field_array = fields(arg_cnt); switch (return_type->basic_type()) { case T_LONG: field_array[TypeFunc::Parms] = TypeLong::LONG; field_array[TypeFunc::Parms+1] = Type::HALF;
*** 1893,1930 **** case T_BYTE: case T_SHORT: case T_INT: field_array[TypeFunc::Parms] = get_const_type(return_type); break; case T_VOID: break; default: ShouldNotReachHere(); } return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt, field_array))->hashcons(); } // Make a TypeTuple from the domain of a method signature ! const TypeTuple *TypeTuple::make_domain(ciInstanceKlass* recv, ciSignature* sig) { ! uint arg_cnt = sig->size(); uint pos = TypeFunc::Parms; ! const Type **field_array; ! if (recv != NULL) { ! arg_cnt++; ! field_array = fields(arg_cnt); ! // Use get_const_type here because it respects UseUniqueSubclasses: ! field_array[pos++] = get_const_type(recv)->join_speculative(TypePtr::NOTNULL); ! } else { ! field_array = fields(arg_cnt); } int i = 0; while (pos < TypeFunc::Parms + arg_cnt) { ciType* type = sig->type_at(i); ! switch (type->basic_type()) { case T_LONG: field_array[pos++] = TypeLong::LONG; field_array[pos++] = Type::HALF; break; case T_DOUBLE: --- 1987,2049 ---- case T_BYTE: case T_SHORT: case T_INT: field_array[TypeFunc::Parms] = get_const_type(return_type); break; + case T_VALUETYPE: + if (ret_vt_fields) { + uint pos = TypeFunc::Parms; + field_array[pos] = TypePtr::BOTTOM; + pos++; + ExtendedSignature sig = ExtendedSignature(NULL, SigEntryFilter()); + collect_value_fields(return_type->as_value_klass(), field_array, pos, sig); + } else { + field_array[TypeFunc::Parms] = get_const_type(return_type)->join_speculative(sig->returns_never_null() ? TypePtr::NOTNULL : TypePtr::BOTTOM); + } + break; case T_VOID: break; default: ShouldNotReachHere(); } return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt, field_array))->hashcons(); } // Make a TypeTuple from the domain of a method signature ! const TypeTuple *TypeTuple::make_domain(ciMethod* method, bool vt_fields_as_args) { ! ciSignature* sig = method->signature(); ! ExtendedSignature sig_cc = ExtendedSignature(vt_fields_as_args ? method->get_sig_cc() : NULL, SigEntryFilter()); ! ! uint arg_cnt = sig->size() + (method->is_static() ? 0 : 1); ! if (vt_fields_as_args) { ! for (arg_cnt = 0; !sig_cc.at_end(); ++sig_cc) { ! arg_cnt += type2size[(*sig_cc)._bt]; ! } ! sig_cc = ExtendedSignature(method->get_sig_cc(), SigEntryFilter()); ! } uint pos = TypeFunc::Parms; ! const Type** field_array = fields(arg_cnt); ! if (!method->is_static()) { ! ciInstanceKlass* recv = method->holder(); ! if (vt_fields_as_args && recv->is_valuetype() && recv->as_value_klass()->is_scalarizable()) { ! collect_value_fields(recv->as_value_klass(), field_array, pos, sig_cc); ! } else { ! field_array[pos++] = get_const_type(recv)->join_speculative(TypePtr::NOTNULL); ! if (vt_fields_as_args) { ! ++sig_cc; ! } ! } } int i = 0; while (pos < TypeFunc::Parms + arg_cnt) { ciType* type = sig->type_at(i); + BasicType bt = type->basic_type(); + bool is_flattened = false; ! switch (bt) { case T_LONG: field_array[pos++] = TypeLong::LONG; field_array[pos++] = Type::HALF; break; case T_DOUBLE:
*** 1941,1955 **** --- 2060,2092 ---- case T_CHAR: case T_BYTE: case T_SHORT: field_array[pos++] = TypeInt::INT; break; + case T_VALUETYPE: { + bool never_null = sig->is_never_null_at(i); + if (vt_fields_as_args && type->as_value_klass()->is_scalarizable() && never_null) { + is_flattened = true; + collect_value_fields(type->as_value_klass(), field_array, pos, sig_cc); + } else { + field_array[pos++] = get_const_type(type)->join_speculative(never_null ? TypePtr::NOTNULL : TypePtr::BOTTOM); + } + break; + } default: ShouldNotReachHere(); } + // Skip reserved arguments + while (!is_flattened && SigEntry::next_is_reserved(sig_cc, bt)) { + field_array[pos++] = Type::get_const_basic_type(bt); + if (type2size[bt] == 2) { + field_array[pos++] = Type::HALF; + } + } i++; } + assert(pos == TypeFunc::Parms + arg_cnt, "wrong number of arguments"); return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt, field_array))->hashcons(); } const TypeTuple *TypeTuple::make( uint cnt, const Type **fields ) {
*** 2080,2095 **** else return size; } //------------------------------make------------------------------------------- ! const TypeAry* TypeAry::make(const Type* elem, const TypeInt* size, bool stable) { if (UseCompressedOops && elem->isa_oopptr()) { elem = elem->make_narrowoop(); } size = normalize_array_size(size); ! return (TypeAry*)(new TypeAry(elem,size,stable))->hashcons(); } //------------------------------meet------------------------------------------- // Compute the MEET of two types. It returns a new Type object. const Type *TypeAry::xmeet( const Type *t ) const { --- 2217,2233 ---- else return size; } //------------------------------make------------------------------------------- ! const TypeAry* TypeAry::make(const Type* elem, const TypeInt* size, bool stable, ! bool not_flat, bool not_null_free) { if (UseCompressedOops && elem->isa_oopptr()) { elem = elem->make_narrowoop(); } size = normalize_array_size(size); ! return (TypeAry*)(new TypeAry(elem, size, stable, not_flat, not_null_free))->hashcons(); } //------------------------------meet------------------------------------------- // Compute the MEET of two types. It returns a new Type object. const Type *TypeAry::xmeet( const Type *t ) const {
*** 2107,2117 **** case Array: { // Meeting 2 arrays? const TypeAry *a = t->is_ary(); return TypeAry::make(_elem->meet_speculative(a->_elem), _size->xmeet(a->_size)->is_int(), ! _stable && a->_stable); } case Top: break; } return this; // Return the double constant --- 2245,2257 ---- case Array: { // Meeting 2 arrays? const TypeAry *a = t->is_ary(); return TypeAry::make(_elem->meet_speculative(a->_elem), _size->xmeet(a->_size)->is_int(), ! _stable && a->_stable, ! _not_flat && a->_not_flat, ! _not_null_free && a->_not_null_free); } case Top: break; } return this; // Return the double constant
*** 2120,2139 **** //------------------------------xdual------------------------------------------ // Dual: compute field-by-field dual const Type *TypeAry::xdual() const { const TypeInt* size_dual = _size->dual()->is_int(); size_dual = normalize_array_size(size_dual); ! return new TypeAry(_elem->dual(), size_dual, !_stable); } //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypeAry::eq( const Type *t ) const { const TypeAry *a = (const TypeAry*)t; return _elem == a->_elem && _stable == a->_stable && ! _size == a->_size; } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeAry::hash(void) const { --- 2260,2282 ---- //------------------------------xdual------------------------------------------ // Dual: compute field-by-field dual const Type *TypeAry::xdual() const { const TypeInt* size_dual = _size->dual()->is_int(); size_dual = normalize_array_size(size_dual); ! return new TypeAry(_elem->dual(), size_dual, !_stable, !_not_flat, !_not_null_free); } //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypeAry::eq( const Type *t ) const { const TypeAry *a = (const TypeAry*)t; return _elem == a->_elem && _stable == a->_stable && ! _size == a->_size && ! _not_flat == a->_not_flat && ! _not_null_free == a->_not_null_free; ! } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeAry::hash(void) const {
*** 2142,2159 **** /** * Return same type without a speculative part in the element */ const Type* TypeAry::remove_speculative() const { ! 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) * --- 2285,2302 ---- /** * Return same type without a speculative part in the element */ const Type* TypeAry::remove_speculative() const { ! return make(_elem->remove_speculative(), _size, _stable, _not_flat, _not_null_free); } /** * Return same type with cleaned up speculative part of element */ const Type* TypeAry::cleanup_speculative() const { ! return make(_elem->cleanup_speculative(), _size, _stable, _not_flat, _not_null_free); } /** * Return same type but with a different inline depth (used for speculation) *
*** 2183,2192 **** --- 2326,2339 ---- //------------------------------dump2------------------------------------------ #ifndef PRODUCT void TypeAry::dump2( Dict &d, uint depth, outputStream *st ) const { if (_stable) st->print("stable:"); + if (Verbose) { + if (_not_flat) st->print("not flat:"); + if (_not_null_free) st->print("not null free:"); + } _elem->dump2(d, depth, st); st->print("["); _size->dump2(d, depth, st); st->print("]"); }
*** 2225,2246 **** const TypeInstPtr* tinst; if (_elem->isa_narrowoop()) tinst = _elem->make_ptr()->isa_instptr(); else tinst = _elem->isa_instptr(); ! if (tinst) ! return tklass->as_instance_klass()->is_final(); const TypeAryPtr* tap; if (_elem->isa_narrowoop()) tap = _elem->make_ptr()->isa_aryptr(); else tap = _elem->isa_aryptr(); if (tap) return tap->ary()->ary_must_be_exact(); return false; } //==============================TypeVect======================================= // Convenience common pre-built types. const TypeVect *TypeVect::VECTS = NULL; // 32-bit vectors const TypeVect *TypeVect::VECTD = NULL; // 64-bit vectors const TypeVect *TypeVect::VECTX = NULL; // 128-bit vectors --- 2372,2525 ---- const TypeInstPtr* tinst; if (_elem->isa_narrowoop()) tinst = _elem->make_ptr()->isa_instptr(); else tinst = _elem->isa_instptr(); ! if (tinst) { ! // [V? has a subtype: [V. So even though V is final, [V? is not exact. ! if (tklass->as_instance_klass()->is_final()) { ! if (tinst->is_valuetypeptr() && (tinst->ptr() == TypePtr::BotPTR || tinst->ptr() == TypePtr::TopPTR)) { ! return false; ! } ! return true; ! } ! return false; ! } const TypeAryPtr* tap; if (_elem->isa_narrowoop()) tap = _elem->make_ptr()->isa_aryptr(); else tap = _elem->isa_aryptr(); if (tap) return tap->ary()->ary_must_be_exact(); return false; } + //==============================TypeValueType======================================= + + const TypeValueType *TypeValueType::BOTTOM; + + //------------------------------make------------------------------------------- + const TypeValueType* TypeValueType::make(ciValueKlass* vk, bool larval) { + return (TypeValueType*)(new TypeValueType(vk, larval))->hashcons(); + } + + //------------------------------meet------------------------------------------- + // Compute the MEET of two types. It returns a new Type object. + const Type* TypeValueType::xmeet(const Type* t) const { + // Perform a fast test for common case; meeting the same types together. + if(this == t) return this; // Meeting same type-rep? + + // Current "this->_base" is ValueType + switch (t->base()) { // switch on original type + + case Int: + case Long: + case FloatTop: + case FloatCon: + case FloatBot: + case DoubleTop: + case DoubleCon: + case DoubleBot: + case NarrowKlass: + case Bottom: + return Type::BOTTOM; + + case OopPtr: + case MetadataPtr: + case KlassPtr: + case RawPtr: + return TypePtr::BOTTOM; + + case Top: + return this; + + case NarrowOop: { + const Type* res = t->make_ptr()->xmeet(this); + if (res->isa_ptr()) { + return res->make_narrowoop(); + } + return res; + } + + case AryPtr: + case InstPtr: { + return t->xmeet(this); + } + + case ValueType: { + // All value types inherit from Object + const TypeValueType* other = t->is_valuetype(); + if (_vk == NULL) { + return this; + } else if (other->_vk == NULL) { + return other; + } else if (_vk == other->_vk) { + if (_larval == other->_larval || + !_larval) { + return this; + } else { + return t; + } + } + return TypeInstPtr::NOTNULL; + } + + default: // All else is a mistake + typerr(t); + + } + return this; + } + + //------------------------------xdual------------------------------------------ + const Type* TypeValueType::xdual() const { + return this; + } + + //------------------------------eq--------------------------------------------- + // Structural equality check for Type representations + bool TypeValueType::eq(const Type* t) const { + const TypeValueType* vt = t->is_valuetype(); + return (_vk == vt->value_klass() && _larval == vt->larval()); + } + + //------------------------------hash------------------------------------------- + // Type-specific hashing function. + int TypeValueType::hash(void) const { + return (intptr_t)_vk; + } + + //------------------------------singleton-------------------------------------- + // TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple constants. + bool TypeValueType::singleton(void) const { + return false; + } + + //------------------------------empty------------------------------------------ + // TRUE if Type is a type with no values, FALSE otherwise. + bool TypeValueType::empty(void) const { + return false; + } + + //------------------------------dump2------------------------------------------ + #ifndef PRODUCT + void TypeValueType::dump2(Dict &d, uint depth, outputStream* st) const { + if (_vk == NULL) { + st->print("BOTTOM valuetype"); + return; + } + int count = _vk->nof_declared_nonstatic_fields(); + st->print("valuetype[%d]:{", count); + st->print("%s", count != 0 ? _vk->declared_nonstatic_field_at(0)->type()->name() : "empty"); + for (int i = 1; i < count; ++i) { + st->print(", %s", _vk->declared_nonstatic_field_at(i)->type()->name()); + } + st->print("}%s", _larval?" : larval":""); + } + #endif + //==============================TypeVect======================================= // Convenience common pre-built types. const TypeVect *TypeVect::VECTS = NULL; // 32-bit vectors const TypeVect *TypeVect::VECTD = NULL; // 64-bit vectors const TypeVect *TypeVect::VECTX = NULL; // 128-bit vectors
*** 2378,2388 **** { /* NotNull */ NotNull, NotNull, NotNull, BotPTR, NotNull, BotPTR,}, { /* BotPTR */ BotPTR, BotPTR, BotPTR, BotPTR, BotPTR, BotPTR,} }; //------------------------------make------------------------------------------- ! const TypePtr *TypePtr::make(TYPES t, enum PTR ptr, int offset, const TypePtr* speculative, int inline_depth) { return (TypePtr*)(new TypePtr(t,ptr,offset, speculative, inline_depth))->hashcons(); } //------------------------------cast_to_ptr_type------------------------------- const Type *TypePtr::cast_to_ptr_type(PTR ptr) const { --- 2657,2667 ---- { /* NotNull */ NotNull, NotNull, NotNull, BotPTR, NotNull, BotPTR,}, { /* BotPTR */ BotPTR, BotPTR, BotPTR, BotPTR, BotPTR, BotPTR,} }; //------------------------------make------------------------------------------- ! const TypePtr* TypePtr::make(TYPES t, enum PTR ptr, Offset offset, const TypePtr* speculative, int inline_depth) { return (TypePtr*)(new TypePtr(t,ptr,offset, speculative, inline_depth))->hashcons(); } //------------------------------cast_to_ptr_type------------------------------- const Type *TypePtr::cast_to_ptr_type(PTR ptr) const {
*** 2392,2402 **** } //------------------------------get_con---------------------------------------- intptr_t TypePtr::get_con() const { assert( _ptr == Null, "" ); ! return _offset; } //------------------------------meet------------------------------------------- // Compute the MEET of two types. It returns a new Type object. const Type *TypePtr::xmeet(const Type *t) const { --- 2671,2681 ---- } //------------------------------get_con---------------------------------------- intptr_t TypePtr::get_con() const { assert( _ptr == Null, "" ); ! return offset(); } //------------------------------meet------------------------------------------- // Compute the MEET of two types. It returns a new Type object. const Type *TypePtr::xmeet(const Type *t) const {
*** 2461,2484 **** } return this; } //------------------------------meet_offset------------------------------------ ! int TypePtr::meet_offset( int offset ) const { ! // Either is 'TOP' offset? Return the other offset! ! if( _offset == OffsetTop ) return offset; ! if( offset == OffsetTop ) return _offset; ! // If either is different, return 'BOTTOM' offset ! if( _offset != offset ) return OffsetBot; ! return _offset; } //------------------------------dual_offset------------------------------------ ! int TypePtr::dual_offset( ) const { ! if( _offset == OffsetTop ) return OffsetBot;// Map 'TOP' into 'BOTTOM' ! if( _offset == OffsetBot ) return OffsetTop;// Map 'BOTTOM' into 'TOP' ! return _offset; // Map everything else into self } //------------------------------xdual------------------------------------------ // Dual: compute field-by-field dual const TypePtr::PTR TypePtr::ptr_dual[TypePtr::lastPTR] = { --- 2740,2756 ---- } return this; } //------------------------------meet_offset------------------------------------ ! Type::Offset TypePtr::meet_offset(int offset) const { ! return _offset.meet(Offset(offset)); } //------------------------------dual_offset------------------------------------ ! Type::Offset TypePtr::dual_offset() const { ! return _offset.dual(); } //------------------------------xdual------------------------------------------ // Dual: compute field-by-field dual const TypePtr::PTR TypePtr::ptr_dual[TypePtr::lastPTR] = {
*** 2487,2509 **** const Type *TypePtr::xdual() const { return new TypePtr(AnyPtr, dual_ptr(), dual_offset(), dual_speculative(), dual_inline_depth()); } //------------------------------xadd_offset------------------------------------ ! int TypePtr::xadd_offset( intptr_t offset ) const { ! // Adding to 'TOP' offset? Return 'TOP'! ! if( _offset == OffsetTop || offset == OffsetTop ) return OffsetTop; ! // Adding to 'BOTTOM' offset? Return 'BOTTOM'! ! if( _offset == OffsetBot || offset == OffsetBot ) return OffsetBot; ! // Addition overflows or "accidentally" equals to OffsetTop? Return 'BOTTOM'! ! offset += (intptr_t)_offset; ! if (offset != (int)offset || offset == OffsetTop) return OffsetBot; ! ! // assert( _offset >= 0 && _offset+offset >= 0, "" ); ! // It is possible to construct a negative offset during PhaseCCP ! ! return (int)offset; // Sum valid offsets } //------------------------------add_offset------------------------------------- const TypePtr *TypePtr::add_offset( intptr_t offset ) const { return make(AnyPtr, _ptr, xadd_offset(offset), _speculative, _inline_depth); --- 2759,2770 ---- const Type *TypePtr::xdual() const { return new TypePtr(AnyPtr, dual_ptr(), dual_offset(), dual_speculative(), dual_inline_depth()); } //------------------------------xadd_offset------------------------------------ ! Type::Offset TypePtr::xadd_offset(intptr_t offset) const { ! return _offset.add(offset); } //------------------------------add_offset------------------------------------- const TypePtr *TypePtr::add_offset( intptr_t offset ) const { return make(AnyPtr, _ptr, xadd_offset(offset), _speculative, _inline_depth);
*** 2511,2527 **** //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypePtr::eq( const Type *t ) const { const TypePtr *a = (const TypePtr*)t; ! return _ptr == a->ptr() && _offset == a->offset() && eq_speculative(a) && _inline_depth == a->_inline_depth; } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypePtr::hash(void) const { ! return java_add(java_add((jint)_ptr, (jint)_offset), java_add((jint)hash_speculative(), (jint)_inline_depth)); ; } /** * Return same type without a speculative part --- 2772,2788 ---- //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypePtr::eq( const Type *t ) const { const TypePtr *a = (const TypePtr*)t; ! return _ptr == a->ptr() && _offset == a->_offset && eq_speculative(a) && _inline_depth == a->_inline_depth; } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypePtr::hash(void) const { ! return java_add(java_add((jint)_ptr, (jint)offset()), java_add((jint)hash_speculative(), (jint)_inline_depth)); ; } /** * Return same type without a speculative part
*** 2777,2789 **** #ifndef PRODUCT void TypePtr::dump2( Dict &d, uint depth, outputStream *st ) const { if( _ptr == Null ) st->print("NULL"); else st->print("%s *", ptr_msg[_ptr]); ! if( _offset == OffsetTop ) st->print("+top"); ! else if( _offset == OffsetBot ) st->print("+bot"); ! else if( _offset ) st->print("+%d", _offset); dump_inline_depth(st); dump_speculative(st); } /** --- 3038,3048 ---- #ifndef PRODUCT void TypePtr::dump2( Dict &d, uint depth, outputStream *st ) const { if( _ptr == Null ) st->print("NULL"); else st->print("%s *", ptr_msg[_ptr]); ! _offset.dump2(st); dump_inline_depth(st); dump_speculative(st); } /**
*** 2814,2828 **** //------------------------------singleton-------------------------------------- // TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple // constants bool TypePtr::singleton(void) const { // TopPTR, Null, AnyNull, Constant are all singletons ! return (_offset != OffsetBot) && !below_centerline(_ptr); } bool TypePtr::empty(void) const { ! return (_offset == OffsetTop) || above_centerline(_ptr); } //============================================================================= // Convenience common pre-built types. const TypeRawPtr *TypeRawPtr::BOTTOM; --- 3073,3087 ---- //------------------------------singleton-------------------------------------- // TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple // constants bool TypePtr::singleton(void) const { // TopPTR, Null, AnyNull, Constant are all singletons ! return (_offset != Offset::bottom) && !below_centerline(_ptr); } bool TypePtr::empty(void) const { ! return (_offset == Offset::top) || above_centerline(_ptr); } //============================================================================= // Convenience common pre-built types. const TypeRawPtr *TypeRawPtr::BOTTOM;
*** 2960,3026 **** //============================================================================= // Convenience common pre-built type. const TypeOopPtr *TypeOopPtr::BOTTOM; //------------------------------TypeOopPtr------------------------------------- ! TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypePtr* speculative, int inline_depth) : TypePtr(t, ptr, offset, speculative, inline_depth), _const_oop(o), _klass(k), _klass_is_exact(xk), _is_ptr_to_narrowoop(false), _is_ptr_to_narrowklass(false), _is_ptr_to_boxed_value(false), _instance_id(instance_id) { 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 || _offset == Type::OffsetTop || _offset == Type::OffsetBot) { ! if (_offset == oopDesc::klass_offset_in_bytes()) { _is_ptr_to_narrowklass = UseCompressedClassPointers; } else if (klass() == NULL) { // Array with unknown body type assert(this->isa_aryptr(), "only arrays without klass"); _is_ptr_to_narrowoop = UseCompressedOops; ! } else if (this->isa_aryptr()) { ! _is_ptr_to_narrowoop = (UseCompressedOops && klass()->is_obj_array_klass() && ! _offset != arrayOopDesc::length_offset_in_bytes()); } else if (klass()->is_instance_klass()) { - ciInstanceKlass* ik = klass()->as_instance_klass(); - ciField* field = NULL; if (this->isa_klassptr()) { // Perm objects don't use compressed references ! } else if (_offset == OffsetBot || _offset == OffsetTop) { // unsafe access _is_ptr_to_narrowoop = UseCompressedOops; } else { // exclude unsafe ops assert(this->isa_instptr(), "must be an instance ptr."); - if (klass() == ciEnv::current()->Class_klass() && ! (_offset == java_lang_Class::klass_offset_in_bytes() || ! _offset == java_lang_Class::array_klass_offset_in_bytes())) { // Special hidden fields from the Class. assert(this->isa_instptr(), "must be an instance ptr."); _is_ptr_to_narrowoop = false; } else if (klass() == ciEnv::current()->Class_klass() && ! _offset >= InstanceMirrorKlass::offset_of_static_fields()) { // Static fields assert(o != NULL, "must be constant"); ! ciInstanceKlass* k = o->as_instance()->java_lang_Class_klass()->as_instance_klass(); ! ciField* field = k->get_field_by_offset(_offset, true); ! assert(field != NULL, "missing field"); ! BasicType basic_elem_type = field->layout_type(); _is_ptr_to_narrowoop = UseCompressedOops && (basic_elem_type == T_OBJECT || basic_elem_type == T_ARRAY); } else { // Instance fields which contains a compressed oop references. ! field = ik->get_field_by_offset(_offset, false); if (field != NULL) { BasicType basic_elem_type = field->layout_type(); _is_ptr_to_narrowoop = UseCompressedOops && (basic_elem_type == T_OBJECT || basic_elem_type == T_ARRAY); } else if (klass()->equals(ciEnv::current()->Object_klass())) { // Compile::find_alias_type() cast exactness on all types to verify // that it does not affect alias type. _is_ptr_to_narrowoop = UseCompressedOops; --- 3219,3300 ---- //============================================================================= // Convenience common pre-built type. const TypeOopPtr *TypeOopPtr::BOTTOM; //------------------------------TypeOopPtr------------------------------------- ! TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, Offset offset, Offset field_offset, int instance_id, const TypePtr* speculative, int inline_depth) : TypePtr(t, ptr, offset, speculative, inline_depth), _const_oop(o), _klass(k), _klass_is_exact(xk), _is_ptr_to_narrowoop(false), _is_ptr_to_narrowklass(false), _is_ptr_to_boxed_value(false), _instance_id(instance_id) { if (Compile::current()->eliminate_boxing() && (t == InstPtr) && ! (offset.get() > 0) && xk && (k != 0) && k->is_instance_klass()) { ! _is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset.get()); } #ifdef _LP64 ! if (this->offset() > 0 || this->offset() == Type::OffsetTop || this->offset() == Type::OffsetBot) { ! if (this->offset() == oopDesc::klass_offset_in_bytes()) { _is_ptr_to_narrowklass = UseCompressedClassPointers; } else if (klass() == NULL) { // Array with unknown body type assert(this->isa_aryptr(), "only arrays without klass"); _is_ptr_to_narrowoop = UseCompressedOops; ! } else if (UseCompressedOops && this->isa_aryptr() && this->offset() != arrayOopDesc::length_offset_in_bytes()) { ! if (klass()->is_obj_array_klass()) { ! _is_ptr_to_narrowoop = true; ! } else if (klass()->is_value_array_klass() && field_offset != Offset::top && field_offset != Offset::bottom) { ! // Check if the field of the value type array element contains oops ! ciValueKlass* vk = klass()->as_value_array_klass()->element_klass()->as_value_klass(); ! int foffset = field_offset.get() + vk->first_field_offset(); ! ciField* field = vk->get_field_by_offset(foffset, false); ! assert(field != NULL, "missing field"); ! BasicType bt = field->layout_type(); ! _is_ptr_to_narrowoop = (bt == T_OBJECT || bt == T_ARRAY || T_VALUETYPE); ! } } else if (klass()->is_instance_klass()) { if (this->isa_klassptr()) { // Perm objects don't use compressed references ! } else if (_offset == Offset::bottom || _offset == Offset::top) { // unsafe access _is_ptr_to_narrowoop = UseCompressedOops; } else { // exclude unsafe ops assert(this->isa_instptr(), "must be an instance ptr."); if (klass() == ciEnv::current()->Class_klass() && ! (this->offset() == java_lang_Class::klass_offset_in_bytes() || ! this->offset() == java_lang_Class::array_klass_offset_in_bytes())) { // Special hidden fields from the Class. assert(this->isa_instptr(), "must be an instance ptr."); _is_ptr_to_narrowoop = false; } else if (klass() == ciEnv::current()->Class_klass() && ! this->offset() >= InstanceMirrorKlass::offset_of_static_fields()) { // Static fields assert(o != NULL, "must be constant"); ! ciInstanceKlass* ik = o->as_instance()->java_lang_Class_klass()->as_instance_klass(); ! BasicType basic_elem_type; ! if (ik->is_valuetype() && this->offset() == ik->as_value_klass()->default_value_offset()) { ! // Special hidden field that contains the oop of the default value type ! basic_elem_type = T_VALUETYPE; ! } else { ! ciField* field = ik->get_field_by_offset(this->offset(), true); ! assert(field != NULL, "missing field"); ! basic_elem_type = field->layout_type(); ! } _is_ptr_to_narrowoop = UseCompressedOops && (basic_elem_type == T_OBJECT || + basic_elem_type == T_VALUETYPE || basic_elem_type == T_ARRAY); } else { // Instance fields which contains a compressed oop references. ! ciInstanceKlass* ik = klass()->as_instance_klass(); ! ciField* field = ik->get_field_by_offset(this->offset(), false); if (field != NULL) { BasicType basic_elem_type = field->layout_type(); _is_ptr_to_narrowoop = UseCompressedOops && (basic_elem_type == T_OBJECT || + basic_elem_type == T_VALUETYPE || basic_elem_type == T_ARRAY); } else if (klass()->equals(ciEnv::current()->Object_klass())) { // Compile::find_alias_type() cast exactness on all types to verify // that it does not affect alias type. _is_ptr_to_narrowoop = UseCompressedOops;
*** 3034,3050 **** } #endif } //------------------------------make------------------------------------------- ! const TypeOopPtr *TypeOopPtr::make(PTR ptr, int offset, int instance_id, ! const TypePtr* speculative, int inline_depth) { assert(ptr != Constant, "no constant generic pointers"); ciKlass* k = Compile::current()->env()->Object_klass(); bool xk = false; ciObject* o = NULL; ! return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id, speculative, inline_depth))->hashcons(); } //------------------------------cast_to_ptr_type------------------------------- const Type *TypeOopPtr::cast_to_ptr_type(PTR ptr) const { --- 3308,3324 ---- } #endif } //------------------------------make------------------------------------------- ! const TypeOopPtr *TypeOopPtr::make(PTR ptr, Offset offset, int instance_id, ! const TypePtr* speculative, int inline_depth) { assert(ptr != Constant, "no constant generic pointers"); ciKlass* k = Compile::current()->env()->Object_klass(); bool xk = false; ciObject* o = NULL; ! return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, Offset::bottom, instance_id, speculative, inline_depth))->hashcons(); } //------------------------------cast_to_ptr_type------------------------------- const Type *TypeOopPtr::cast_to_ptr_type(PTR ptr) const {
*** 3079,3089 **** ciKlass* k = klass(); bool xk = klass_is_exact(); if (k == NULL) return TypeKlassPtr::OBJECT; else ! return TypeKlassPtr::make(xk? Constant: NotNull, k, 0); } //------------------------------meet------------------------------------------- // Compute the MEET of two types. It returns a new Type object. const Type *TypeOopPtr::xmeet_helper(const Type *t) const { --- 3353,3363 ---- ciKlass* k = klass(); bool xk = klass_is_exact(); if (k == NULL) return TypeKlassPtr::OBJECT; else ! return TypeKlassPtr::make(xk? Constant: NotNull, k, Offset(0)); } //------------------------------meet------------------------------------------- // Compute the MEET of two types. It returns a new Type object. const Type *TypeOopPtr::xmeet_helper(const Type *t) const {
*** 3117,3127 **** return TypePtr::BOTTOM; // Oop meet raw is not well defined case AnyPtr: { // Found an AnyPtr type vs self-OopPtr type const TypePtr *tp = t->is_ptr(); ! int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) { case Null: --- 3391,3401 ---- return TypePtr::BOTTOM; // Oop meet raw is not well defined case AnyPtr: { // Found an AnyPtr type vs self-OopPtr type const TypePtr *tp = t->is_ptr(); ! Offset offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) { case Null:
*** 3159,3175 **** //------------------------------xdual------------------------------------------ // Dual of a pure heap pointer. No relevant klass or oop information. const Type *TypeOopPtr::xdual() const { assert(klass() == Compile::current()->env()->Object_klass(), "no klasses here"); assert(const_oop() == NULL, "no constants here"); ! return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative(), dual_inline_depth()); } //--------------------------make_from_klass_common----------------------------- // Computes the element-type given a klass. const TypeOopPtr* TypeOopPtr::make_from_klass_common(ciKlass *klass, bool klass_change, bool try_for_exact) { ! if (klass->is_instance_klass()) { Compile* C = Compile::current(); Dependencies* deps = C->dependencies(); assert((deps != NULL) == (C->method() != NULL && C->method()->code_size() > 0), "sanity"); // Element is an instance bool klass_is_exact = false; --- 3433,3449 ---- //------------------------------xdual------------------------------------------ // Dual of a pure heap pointer. No relevant klass or oop information. const Type *TypeOopPtr::xdual() const { assert(klass() == Compile::current()->env()->Object_klass(), "no klasses here"); assert(const_oop() == NULL, "no constants here"); ! return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), Offset::bottom, dual_instance_id(), dual_speculative(), dual_inline_depth()); } //--------------------------make_from_klass_common----------------------------- // Computes the element-type given a klass. const TypeOopPtr* TypeOopPtr::make_from_klass_common(ciKlass *klass, bool klass_change, bool try_for_exact) { ! if (klass->is_instance_klass() || klass->is_valuetype()) { Compile* C = Compile::current(); Dependencies* deps = C->dependencies(); assert((deps != NULL) == (C->method() != NULL && C->method()->code_size() > 0), "sanity"); // Element is an instance bool klass_is_exact = false;
*** 3193,3220 **** deps->assert_leaf_type(ik); klass_is_exact = true; } } } ! return TypeInstPtr::make(TypePtr::BotPTR, klass, klass_is_exact, NULL, 0); } else if (klass->is_obj_array_klass()) { ! // Element is an object array. Recursively call ourself. ! const TypeOopPtr *etype = TypeOopPtr::make_from_klass_common(klass->as_obj_array_klass()->element_klass(), false, try_for_exact); ! bool xk = etype->klass_is_exact(); ! const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS); // 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. ! const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::BotPTR, arr0, klass, xk, 0); return arr; } else if (klass->is_type_array_klass()) { // Element is an typeArray const Type* etype = get_const_basic_type(klass->as_type_array_klass()->element_type()); ! const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS); // We used to pass NotNull in here, asserting that the array pointer // is not-null. That was not true in general. ! const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::BotPTR, arr0, klass, true, 0); return arr; } else { ShouldNotReachHere(); return NULL; } --- 3467,3508 ---- deps->assert_leaf_type(ik); klass_is_exact = true; } } } ! return TypeInstPtr::make(TypePtr::BotPTR, klass, klass_is_exact, NULL, Offset(0)); } else if (klass->is_obj_array_klass()) { ! // Element is an object or value array. Recursively call ourself. ! const TypeOopPtr* etype = TypeOopPtr::make_from_klass_common(klass->as_array_klass()->element_klass(), false, try_for_exact); ! bool null_free = klass->is_loaded() && klass->as_array_klass()->storage_properties().is_null_free(); ! if (null_free) { ! assert(etype->is_valuetypeptr(), "must be a valuetypeptr"); ! etype = etype->join_speculative(TypePtr::NOTNULL)->is_oopptr(); ! } ! // [V? has a subtype: [V. So even though V is final, [V? is not exact. ! bool xk = etype->klass_is_exact() && (!etype->is_valuetypeptr() || null_free); ! bool not_null_free = !etype->can_be_value_type() || xk; ! bool not_flat = !ValueArrayFlatten || not_null_free || (etype->is_valuetypeptr() && !etype->value_klass()->flatten_array()); ! const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS, false, not_flat, not_null_free); // 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. ! const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::BotPTR, arr0, klass, xk, Offset(0)); return arr; } else if (klass->is_type_array_klass()) { // Element is an typeArray const Type* etype = get_const_basic_type(klass->as_type_array_klass()->element_type()); ! const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS, ! /* stable= */ false, /* not_flat= */ true, /* not_null_free= */ true); // We used to pass NotNull in here, asserting that the array pointer // is not-null. That was not true in general. ! const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::BotPTR, arr0, klass, true, Offset(0)); ! return arr; ! } else if (klass->is_value_array_klass()) { ! ciValueKlass* vk = klass->as_array_klass()->element_klass()->as_value_klass(); ! const TypeAry* arr0 = TypeAry::make(TypeValueType::make(vk), TypeInt::POS); ! const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::BotPTR, arr0, klass, true, Offset(0)); return arr; } else { ShouldNotReachHere(); return NULL; }
*** 3226,3279 **** assert(!o->is_null_object(), "null object not yet handled here."); const bool make_constant = require_constant || o->should_be_constant(); ciKlass* klass = o->klass(); ! if (klass->is_instance_klass()) { ! // Element is an instance if (make_constant) { return TypeInstPtr::make(o); } else { ! return TypeInstPtr::make(TypePtr::NotNull, klass, true, NULL, 0); } } 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 (make_constant) { ! return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); } else { ! return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); } } 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 (make_constant) { ! return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0); } else { ! return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); } } fatal("unhandled object type"); return NULL; } //------------------------------get_con---------------------------------------- intptr_t TypeOopPtr::get_con() const { assert( _ptr == Null || _ptr == Constant, "" ); ! assert( _offset >= 0, "" ); ! if (_offset != 0) { // After being ported to the compiler interface, the compiler no longer // directly manipulates the addresses of oops. Rather, it only has a pointer // to a handle at compile time. This handle is embedded in the generated // code and dereferenced at the time the nmethod is made. Until that time, // it is not reasonable to do arithmetic with the addresses of oops (we don't --- 3514,3583 ---- assert(!o->is_null_object(), "null object not yet handled here."); const bool make_constant = require_constant || o->should_be_constant(); ciKlass* klass = o->klass(); ! if (klass->is_instance_klass() || klass->is_valuetype()) { ! // Element is an instance or value type if (make_constant) { return TypeInstPtr::make(o); } else { ! return TypeInstPtr::make(TypePtr::NotNull, klass, true, NULL, Offset(0)); } } 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_array_klass()->element_klass()); ! bool null_free = klass->is_loaded() && klass->as_array_klass()->storage_properties().is_null_free(); ! if (null_free) { ! assert(etype->is_valuetypeptr(), "must be a valuetypeptr"); ! etype = etype->join_speculative(TypePtr::NOTNULL)->is_oopptr(); ! } ! const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length()), ! /* stable= */ false, /* not_flat= */ true, /* not_null_free= */ !null_free); // 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 (make_constant) { ! return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, Offset(0)); } else { ! return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, Offset(0)); } } 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()), ! /* stable= */ false, /* not_flat= */ true, /* not_null_free= */ true); // We used to pass NotNull in here, asserting that the array pointer // is not-null. That was not true in general. if (make_constant) { ! return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, Offset(0)); } else { ! return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, Offset(0)); ! } ! } else if (klass->is_value_array_klass()) { ! ciValueKlass* vk = klass->as_array_klass()->element_klass()->as_value_klass(); ! const TypeAry* arr0 = TypeAry::make(TypeValueType::make(vk), 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 (make_constant) { ! return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, Offset(0)); ! } else { ! return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, Offset(0)); } } fatal("unhandled object type"); return NULL; } //------------------------------get_con---------------------------------------- intptr_t TypeOopPtr::get_con() const { assert( _ptr == Null || _ptr == Constant, "" ); ! assert(offset() >= 0, ""); ! if (offset() != 0) { // After being ported to the compiler interface, the compiler no longer // directly manipulates the addresses of oops. Rather, it only has a pointer // to a handle at compile time. This handle is embedded in the generated // code and dereferenced at the time the nmethod is made. Until that time, // it is not reasonable to do arithmetic with the addresses of oops (we don't
*** 3362,3377 **** #ifndef PRODUCT void TypeOopPtr::dump2( Dict &d, uint depth, outputStream *st ) const { st->print("oopptr:%s", ptr_msg[_ptr]); if( _klass_is_exact ) st->print(":exact"); if( const_oop() ) st->print(INTPTR_FORMAT, p2i(const_oop())); ! switch( _offset ) { ! case OffsetTop: st->print("+top"); break; ! case OffsetBot: st->print("+any"); break; ! case 0: break; ! default: st->print("+%d",_offset); break; ! } if (_instance_id == InstanceTop) st->print(",iid=top"); else if (_instance_id != InstanceBot) st->print(",iid=%d",_instance_id); --- 3666,3676 ---- #ifndef PRODUCT void TypeOopPtr::dump2( Dict &d, uint depth, outputStream *st ) const { st->print("oopptr:%s", ptr_msg[_ptr]); if( _klass_is_exact ) st->print(":exact"); if( const_oop() ) st->print(INTPTR_FORMAT, p2i(const_oop())); ! _offset.dump2(st); if (_instance_id == InstanceTop) st->print(",iid=top"); else if (_instance_id != InstanceBot) st->print(",iid=%d",_instance_id);
*** 3384,3394 **** // TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple // constants bool TypeOopPtr::singleton(void) const { // detune optimizer to not generate constant oop + constant offset as a constant! // TopPTR, Null, AnyNull, Constant are all singletons ! return (_offset == 0) && !below_centerline(_ptr); } //------------------------------add_offset------------------------------------- const TypePtr *TypeOopPtr::add_offset(intptr_t offset) const { return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth); --- 3683,3693 ---- // TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple // constants bool TypeOopPtr::singleton(void) const { // detune optimizer to not generate constant oop + constant offset as a constant! // TopPTR, Null, AnyNull, Constant are all singletons ! return (offset() == 0) && !below_centerline(_ptr); } //------------------------------add_offset------------------------------------- const TypePtr *TypeOopPtr::add_offset(intptr_t offset) const { return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth);
*** 3476,3488 **** const TypeInstPtr *TypeInstPtr::MIRROR; const TypeInstPtr *TypeInstPtr::MARK; const TypeInstPtr *TypeInstPtr::KLASS; //------------------------------TypeInstPtr------------------------------------- ! TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypePtr* speculative, int inline_depth) ! : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth), _name(k->name()) { assert(k != NULL && (k->is_loaded() || o == NULL), "cannot have constants with non-loaded klass"); }; --- 3775,3787 ---- const TypeInstPtr *TypeInstPtr::MIRROR; const TypeInstPtr *TypeInstPtr::MARK; const TypeInstPtr *TypeInstPtr::KLASS; //------------------------------TypeInstPtr------------------------------------- ! TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, Offset off, int instance_id, const TypePtr* speculative, int inline_depth) ! : TypeOopPtr(InstPtr, ptr, k, xk, o, off, Offset::bottom, instance_id, speculative, inline_depth), _name(k->name()) { assert(k != NULL && (k->is_loaded() || o == NULL), "cannot have constants with non-loaded klass"); };
*** 3490,3500 **** //------------------------------make------------------------------------------- const TypeInstPtr *TypeInstPtr::make(PTR ptr, ciKlass* k, bool xk, ciObject* o, ! int offset, int instance_id, const TypePtr* speculative, int inline_depth) { assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance"); // Either const_oop() is NULL or else ptr is Constant --- 3789,3799 ---- //------------------------------make------------------------------------------- const TypeInstPtr *TypeInstPtr::make(PTR ptr, ciKlass* k, bool xk, ciObject* o, ! Offset offset, int instance_id, const TypePtr* speculative, int inline_depth) { assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance"); // Either const_oop() is NULL or else ptr is Constant
*** 3577,3587 **** //------------------------------xmeet_unloaded--------------------------------- // Compute the MEET of two InstPtrs when at least one is unloaded. // Assume classes are different since called after check for same name/class-loader const TypeInstPtr *TypeInstPtr::xmeet_unloaded(const TypeInstPtr *tinst) const { ! int off = meet_offset(tinst->offset()); PTR ptr = meet_ptr(tinst->ptr()); int instance_id = meet_instance_id(tinst->instance_id()); const TypePtr* speculative = xmeet_speculative(tinst); int depth = meet_inline_depth(tinst->inline_depth()); --- 3876,3886 ---- //------------------------------xmeet_unloaded--------------------------------- // Compute the MEET of two InstPtrs when at least one is unloaded. // Assume classes are different since called after check for same name/class-loader const TypeInstPtr *TypeInstPtr::xmeet_unloaded(const TypeInstPtr *tinst) const { ! Offset off = meet_offset(tinst->offset()); PTR ptr = meet_ptr(tinst->ptr()); int instance_id = meet_instance_id(tinst->instance_id()); const TypePtr* speculative = xmeet_speculative(tinst); int depth = meet_inline_depth(tinst->inline_depth());
*** 3655,3665 **** case KlassPtr: case RawPtr: return TypePtr::BOTTOM; case AryPtr: { // All arrays inherit from Object class const TypeAryPtr *tp = t->is_aryptr(); ! int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (ptr) { --- 3954,3964 ---- case KlassPtr: case RawPtr: return TypePtr::BOTTOM; case AryPtr: { // All arrays inherit from Object class const TypeAryPtr *tp = t->is_aryptr(); ! Offset offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (ptr) {
*** 3667,3677 **** case AnyNull: // Fall 'down' to dual of object klass // For instances when a subclass meets a superclass we fall // below the centerline when the superclass is exact. We need to // do the same here. if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) { ! return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative, depth); } else { // cannot subclass, so the meet has to fall badly below the centerline ptr = NotNull; instance_id = InstanceBot; return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth); --- 3966,3976 ---- case AnyNull: // Fall 'down' to dual of object klass // For instances when a subclass meets a superclass we fall // below the centerline when the superclass is exact. We need to // do the same here. if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) { ! return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, tp->field_offset(), instance_id, speculative, depth); } else { // cannot subclass, so the meet has to fall badly below the centerline ptr = NotNull; instance_id = InstanceBot; return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth);
*** 3687,3697 **** // below the centerline when the superclass is exact. We need // to do the same here. if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) { // that is, tp's array type is a subtype of my klass return TypeAryPtr::make(ptr, (ptr == Constant ? tp->const_oop() : NULL), ! tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative, depth); } } // The other case cannot happen, since I cannot be a subtype of an array. // The meet falls down to Object class below centerline. if( ptr == Constant ) --- 3986,3996 ---- // below the centerline when the superclass is exact. We need // to do the same here. if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) { // that is, tp's array type is a subtype of my klass return TypeAryPtr::make(ptr, (ptr == Constant ? tp->const_oop() : NULL), ! tp->ary(), tp->klass(), tp->klass_is_exact(), offset, tp->field_offset(), instance_id, speculative, depth); } } // The other case cannot happen, since I cannot be a subtype of an array. // The meet falls down to Object class below centerline. if( ptr == Constant )
*** 3703,3713 **** } case OopPtr: { // Meeting to OopPtrs // Found a OopPtr type vs self-InstPtr type const TypeOopPtr *tp = t->is_oopptr(); ! int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); switch (tp->ptr()) { case TopPTR: case AnyNull: { int instance_id = meet_instance_id(InstanceTop); --- 4002,4012 ---- } case OopPtr: { // Meeting to OopPtrs // Found a OopPtr type vs self-InstPtr type const TypeOopPtr *tp = t->is_oopptr(); ! Offset offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); switch (tp->ptr()) { case TopPTR: case AnyNull: { int instance_id = meet_instance_id(InstanceTop);
*** 3728,3738 **** } case AnyPtr: { // Meeting to AnyPtrs // Found an AnyPtr type vs self-InstPtr type const TypePtr *tp = t->is_ptr(); ! int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(InstanceTop); const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) { --- 4027,4037 ---- } case AnyPtr: { // Meeting to AnyPtrs // Found an AnyPtr type vs self-InstPtr type const TypePtr *tp = t->is_ptr(); ! Offset offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(InstanceTop); const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) {
*** 3768,3778 **** */ case InstPtr: { // Meeting 2 Oops? // Found an InstPtr sub-type vs self-InstPtr type const TypeInstPtr *tinst = t->is_instptr(); ! int off = meet_offset( tinst->offset() ); PTR ptr = meet_ptr( tinst->ptr() ); int instance_id = meet_instance_id(tinst->instance_id()); const TypePtr* speculative = xmeet_speculative(tinst); int depth = meet_inline_depth(tinst->inline_depth()); --- 4067,4077 ---- */ case InstPtr: { // Meeting 2 Oops? // Found an InstPtr sub-type vs self-InstPtr type const TypeInstPtr *tinst = t->is_instptr(); ! Offset off = meet_offset( tinst->offset() ); PTR ptr = meet_ptr( tinst->ptr() ); int instance_id = meet_instance_id(tinst->instance_id()); const TypePtr* speculative = xmeet_speculative(tinst); int depth = meet_inline_depth(tinst->inline_depth());
*** 3935,3958 **** // Now we find the LCA of Java classes ciKlass* k = this_klass->least_common_ancestor(tinst_klass); return make(ptr, k, false, NULL, off, instance_id, speculative, depth); } // End of case InstPtr } // End of switch return this; // Return the double constant } //------------------------java_mirror_type-------------------------------------- ! ciType* TypeInstPtr::java_mirror_type() const { // must be a singleton type if( const_oop() == NULL ) return NULL; // must be of type java.lang.Class if( klass() != ciEnv::current()->Class_klass() ) return NULL; ! return const_oop()->as_instance()->java_mirror_type(); } //------------------------------xdual------------------------------------------ // Dual: do NOT dual on klasses. This means I do NOT understand the Java --- 4234,4278 ---- // Now we find the LCA of Java classes ciKlass* k = this_klass->least_common_ancestor(tinst_klass); return make(ptr, k, false, NULL, off, instance_id, speculative, depth); } // End of case InstPtr + case ValueType: { + const TypeValueType* tv = t->is_valuetype(); + if (above_centerline(ptr())) { + if (tv->value_klass()->is_subtype_of(_klass)) { + return t; + } else { + return TypeInstPtr::make(NotNull, _klass); + } + } else { + PTR ptr = this->_ptr; + if (ptr == Constant) { + ptr = NotNull; + } + if (tv->value_klass()->is_subtype_of(_klass)) { + return TypeInstPtr::make(ptr, _klass); + } else { + return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass()); + } + } + } + } // End of switch return this; // Return the double constant } //------------------------java_mirror_type-------------------------------------- ! ciType* TypeInstPtr::java_mirror_type(bool* is_indirect_type) const { // must be a singleton type if( const_oop() == NULL ) return NULL; // must be of type java.lang.Class if( klass() != ciEnv::current()->Class_klass() ) return NULL; ! return const_oop()->as_instance()->java_mirror_type(is_indirect_type); } //------------------------------xdual------------------------------------------ // Dual: do NOT dual on klasses. This means I do NOT understand the Java
*** 4003,4017 **** break; default: break; } ! if( _offset ) { // Dump offset, if any ! if( _offset == OffsetBot ) st->print("+any"); ! else if( _offset == OffsetTop ) st->print("+unknown"); ! else st->print("+%d", _offset); ! } st->print(" *"); if (_instance_id == InstanceTop) st->print(",iid=top"); else if (_instance_id != InstanceBot) --- 4323,4333 ---- break; default: break; } ! _offset.dump2(st); st->print(" *"); if (_instance_id == InstanceTop) st->print(",iid=top"); else if (_instance_id != InstanceBot)
*** 4059,4117 **** const TypeAryPtr *TypeAryPtr::CHARS; const TypeAryPtr *TypeAryPtr::INTS; const TypeAryPtr *TypeAryPtr::LONGS; const TypeAryPtr *TypeAryPtr::FLOATS; const TypeAryPtr *TypeAryPtr::DOUBLES; //------------------------------make------------------------------------------- ! const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypePtr* speculative, int inline_depth) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); ! if (!xk) xk = ary->ary_must_be_exact(); 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, false, speculative, inline_depth))->hashcons(); } //------------------------------make------------------------------------------- ! const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypePtr* speculative, int inline_depth, bool is_autobox_cache) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" ); 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, is_autobox_cache, speculative, inline_depth))->hashcons(); } //------------------------------cast_to_ptr_type------------------------------- const Type *TypeAryPtr::cast_to_ptr_type(PTR ptr) const { if( ptr == _ptr ) return this; ! return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth); } //-----------------------------cast_to_exactness------------------------------- const Type *TypeAryPtr::cast_to_exactness(bool klass_is_exact) const { if( klass_is_exact == _klass_is_exact ) return this; if (!UseExactTypes) return this; if (_ary->ary_must_be_exact()) return this; // cannot clear xk ! return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative, _inline_depth); } //-----------------------------cast_to_instance_id---------------------------- const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const { if( instance_id == _instance_id ) return this; ! return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative, _inline_depth); } const TypeOopPtr *TypeAryPtr::cast_to_nonconst() const { if (const_oop() == NULL) return this; ! return make(NotNull, NULL, _ary, klass(), _klass_is_exact, _offset, _instance_id, _speculative, _inline_depth); } //-----------------------------narrow_size_type------------------------------- // Local cache for arrayOopDesc::max_array_length(etype), --- 4375,4440 ---- const TypeAryPtr *TypeAryPtr::CHARS; const TypeAryPtr *TypeAryPtr::INTS; const TypeAryPtr *TypeAryPtr::LONGS; const TypeAryPtr *TypeAryPtr::FLOATS; const TypeAryPtr *TypeAryPtr::DOUBLES; + const TypeAryPtr *TypeAryPtr::VALUES; //------------------------------make------------------------------------------- ! const TypeAryPtr* TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, Offset offset, Offset field_offset, int instance_id, const TypePtr* speculative, int inline_depth) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); ! if (!xk) xk = ary->ary_must_be_exact(); 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, field_offset, instance_id, false, speculative, inline_depth))->hashcons(); } //------------------------------make------------------------------------------- ! const TypeAryPtr* TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, Offset offset, Offset field_offset, int instance_id, const TypePtr* speculative, int inline_depth, bool is_autobox_cache) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" ); 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, field_offset, instance_id, is_autobox_cache, speculative, inline_depth))->hashcons(); } //------------------------------cast_to_ptr_type------------------------------- const Type *TypeAryPtr::cast_to_ptr_type(PTR ptr) const { if( ptr == _ptr ) return this; ! return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _field_offset, _instance_id, _speculative, _inline_depth, _is_autobox_cache); } //-----------------------------cast_to_exactness------------------------------- const Type *TypeAryPtr::cast_to_exactness(bool klass_is_exact) const { if( klass_is_exact == _klass_is_exact ) return this; if (!UseExactTypes) return this; if (_ary->ary_must_be_exact()) return this; // cannot clear xk ! ! const TypeAry* new_ary = _ary; ! if (klass() != NULL && klass()->is_obj_array_klass() && klass_is_exact) { ! // An object array can't be flat or null-free if the klass is exact ! new_ary = TypeAry::make(elem(), size(), is_stable(), /* not_flat= */ true, /* not_null_free= */ true); ! } ! return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact, _offset, _field_offset, _instance_id, _speculative, _inline_depth, _is_autobox_cache); } //-----------------------------cast_to_instance_id---------------------------- const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const { if( instance_id == _instance_id ) return this; ! return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, _field_offset, instance_id, _speculative, _inline_depth, _is_autobox_cache); } const TypeOopPtr *TypeAryPtr::cast_to_nonconst() const { if (const_oop() == NULL) return this; ! return make(NotNull, NULL, _ary, klass(), _klass_is_exact, _offset, _field_offset, _instance_id, _speculative, _inline_depth); } //-----------------------------narrow_size_type------------------------------- // Local cache for arrayOopDesc::max_array_length(etype),
*** 4173,4184 **** //-------------------------------cast_to_size---------------------------------- const TypeAryPtr* TypeAryPtr::cast_to_size(const TypeInt* new_size) const { assert(new_size != NULL, ""); new_size = narrow_size_type(new_size); if (new_size == size()) return this; ! const TypeAry* new_ary = TypeAry::make(elem(), new_size, is_stable()); ! return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth); } //------------------------------cast_to_stable--------------------------------- const TypeAryPtr* TypeAryPtr::cast_to_stable(bool stable, int stable_dimension) const { if (stable_dimension <= 0 || (stable_dimension == 1 && stable == this->is_stable())) --- 4496,4526 ---- //-------------------------------cast_to_size---------------------------------- const TypeAryPtr* TypeAryPtr::cast_to_size(const TypeInt* new_size) const { assert(new_size != NULL, ""); new_size = narrow_size_type(new_size); if (new_size == size()) return this; ! const TypeAry* new_ary = TypeAry::make(elem(), new_size, is_stable(), is_not_flat(), is_not_null_free()); ! return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _field_offset, _instance_id, _speculative, _inline_depth, _is_autobox_cache); ! } ! ! //-------------------------------cast_to_not_flat------------------------------ ! const TypeAryPtr* TypeAryPtr::cast_to_not_flat(bool not_flat) const { ! if (not_flat == is_not_flat()) { ! return this; ! } ! const TypeAry* new_ary = TypeAry::make(elem(), size(), is_stable(), not_flat, is_not_null_free()); ! return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _field_offset, _instance_id, _speculative, _inline_depth, _is_autobox_cache); ! } ! ! //-------------------------------cast_to_not_null_free------------------------- ! const TypeAryPtr* TypeAryPtr::cast_to_not_null_free(bool not_null_free) const { ! if (not_null_free == is_not_null_free()) { ! return this; ! } ! // Not null free implies not flat ! const TypeAry* new_ary = TypeAry::make(elem(), size(), is_stable(), not_null_free ? true : is_not_flat(), not_null_free); ! return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _field_offset, _instance_id, _speculative, _inline_depth, _is_autobox_cache); } //------------------------------cast_to_stable--------------------------------- const TypeAryPtr* TypeAryPtr::cast_to_stable(bool stable, int stable_dimension) const { if (stable_dimension <= 0 || (stable_dimension == 1 && stable == this->is_stable()))
*** 4190,4202 **** if (stable_dimension > 1 && elem_ptr != NULL && elem_ptr->isa_aryptr()) { // If this is widened from a narrow oop, TypeAry::make will re-narrow it. elem = elem_ptr = elem_ptr->is_aryptr()->cast_to_stable(stable, stable_dimension - 1); } ! const TypeAry* new_ary = TypeAry::make(elem, size(), stable); ! return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth); } //-----------------------------stable_dimension-------------------------------- int TypeAryPtr::stable_dimension() const { if (!is_stable()) return 0; --- 4532,4544 ---- if (stable_dimension > 1 && elem_ptr != NULL && elem_ptr->isa_aryptr()) { // If this is widened from a narrow oop, TypeAry::make will re-narrow it. elem = elem_ptr = elem_ptr->is_aryptr()->cast_to_stable(stable, stable_dimension - 1); } ! const TypeAry* new_ary = TypeAry::make(elem, size(), stable, is_not_flat(), is_not_null_free()); ! return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _field_offset, _instance_id, _speculative, _inline_depth, _is_autobox_cache); } //-----------------------------stable_dimension-------------------------------- int TypeAryPtr::stable_dimension() const { if (!is_stable()) return 0;
*** 4213,4239 **** const TypeOopPtr* etype = elem()->make_oopptr(); if (etype == NULL) return this; // The pointers in the autobox arrays are always non-null. TypePtr::PTR ptr_type = cache ? TypePtr::NotNull : TypePtr::AnyNull; etype = etype->cast_to_ptr_type(TypePtr::NotNull)->is_oopptr(); ! const TypeAry* new_ary = TypeAry::make(etype, size(), is_stable()); ! return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth, cache); } //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypeAryPtr::eq( const Type *t ) const { const TypeAryPtr *p = t->is_aryptr(); return _ary == p->_ary && // Check array ! TypeOopPtr::eq(p); // Check sub-parts } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeAryPtr::hash(void) const { ! return (intptr_t)_ary + TypeOopPtr::hash(); } //------------------------------meet------------------------------------------- // Compute the MEET of two types. It returns a new Type object. const Type *TypeAryPtr::xmeet_helper(const Type *t) const { --- 4555,4582 ---- const TypeOopPtr* etype = elem()->make_oopptr(); if (etype == NULL) return this; // The pointers in the autobox arrays are always non-null. TypePtr::PTR ptr_type = cache ? TypePtr::NotNull : TypePtr::AnyNull; etype = etype->cast_to_ptr_type(TypePtr::NotNull)->is_oopptr(); ! const TypeAry* new_ary = TypeAry::make(etype, size(), is_stable(), is_not_flat(), is_not_null_free()); ! return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _field_offset, _instance_id, _speculative, _inline_depth, cache); } //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypeAryPtr::eq( const Type *t ) const { const TypeAryPtr *p = t->is_aryptr(); return _ary == p->_ary && // Check array ! TypeOopPtr::eq(p) &&// Check sub-parts ! _field_offset == p->_field_offset; } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeAryPtr::hash(void) const { ! return (intptr_t)_ary + TypeOopPtr::hash() + _field_offset.get(); } //------------------------------meet------------------------------------------- // Compute the MEET of two types. It returns a new Type object. const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
*** 4262,4281 **** typerr(t); case OopPtr: { // Meeting to OopPtrs // Found a OopPtr type vs self-AryPtr type const TypeOopPtr *tp = t->is_oopptr(); ! int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int depth = meet_inline_depth(tp->inline_depth()); const TypePtr* speculative = xmeet_speculative(tp); switch (tp->ptr()) { case TopPTR: case AnyNull: { int instance_id = meet_instance_id(InstanceTop); return make(ptr, (ptr == Constant ? const_oop() : NULL), ! _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } case BotPTR: case NotNull: { int instance_id = meet_instance_id(tp->instance_id()); return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth); --- 4605,4624 ---- typerr(t); case OopPtr: { // Meeting to OopPtrs // Found a OopPtr type vs self-AryPtr type const TypeOopPtr *tp = t->is_oopptr(); ! Offset offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int depth = meet_inline_depth(tp->inline_depth()); const TypePtr* speculative = xmeet_speculative(tp); switch (tp->ptr()) { case TopPTR: case AnyNull: { int instance_id = meet_instance_id(InstanceTop); return make(ptr, (ptr == Constant ? const_oop() : NULL), ! _ary, _klass, _klass_is_exact, offset, _field_offset, instance_id, speculative, depth); } case BotPTR: case NotNull: { int instance_id = meet_instance_id(tp->instance_id()); return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth);
*** 4285,4295 **** } case AnyPtr: { // Meeting two AnyPtrs // Found an AnyPtr type vs self-AryPtr type const TypePtr *tp = t->is_ptr(); ! int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) { case TopPTR: --- 4628,4638 ---- } case AnyPtr: { // Meeting two AnyPtrs // Found an AnyPtr type vs self-AryPtr type const TypePtr *tp = t->is_ptr(); ! Offset offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) { case TopPTR:
*** 4301,4311 **** if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, speculative, depth); // else fall through to AnyNull case AnyNull: { int instance_id = meet_instance_id(InstanceTop); return make(ptr, (ptr == Constant ? const_oop() : NULL), ! _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } default: ShouldNotReachHere(); } } --- 4644,4654 ---- if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, speculative, depth); // else fall through to AnyNull case AnyNull: { int instance_id = meet_instance_id(InstanceTop); return make(ptr, (ptr == Constant ? const_oop() : NULL), ! _ary, _klass, _klass_is_exact, offset, _field_offset, instance_id, speculative, depth); } default: ShouldNotReachHere(); } }
*** 4313,4323 **** case KlassPtr: case RawPtr: return TypePtr::BOTTOM; case AryPtr: { // Meeting 2 references? const TypeAryPtr *tap = t->is_aryptr(); ! int off = meet_offset(tap->offset()); const TypeAry *tary = _ary->meet_speculative(tap->_ary)->is_ary(); PTR ptr = meet_ptr(tap->ptr()); int instance_id = meet_instance_id(tap->instance_id()); const TypePtr* speculative = xmeet_speculative(tap); int depth = meet_inline_depth(tap->inline_depth()); --- 4656,4667 ---- case KlassPtr: case RawPtr: return TypePtr::BOTTOM; case AryPtr: { // Meeting 2 references? const TypeAryPtr *tap = t->is_aryptr(); ! Offset off = meet_offset(tap->offset()); ! Offset field_off = meet_field_offset(tap->field_offset()); const TypeAry *tary = _ary->meet_speculative(tap->_ary)->is_ary(); PTR ptr = meet_ptr(tap->ptr()); int instance_id = meet_instance_id(tap->instance_id()); const TypePtr* speculative = xmeet_speculative(tap); int depth = meet_inline_depth(tap->inline_depth());
*** 4331,4358 **** lazy_klass = _klass; } else { // Something like byte[int+] meets char[int+]. // This must fall to bottom, not (int[-128..65535])[int+]. instance_id = InstanceBot; ! tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable); } } else // Non integral arrays. // Must fall to bottom if exact klasses in upper lattice // are not equal or super klass is exact. if ((above_centerline(ptr) || ptr == Constant) && klass() != tap->klass() && // meet with top[] and bottom[] are processed further down: ! tap->_klass != NULL && this->_klass != NULL && // both are exact and not equal: ((tap->_klass_is_exact && this->_klass_is_exact) || ! // 'tap' is exact and super or unrelated: (tap->_klass_is_exact && !tap->klass()->is_subtype_of(klass())) || // 'this' is exact and super or unrelated: (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) { if (above_centerline(ptr)) { ! tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable); } ! return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot, speculative, depth); } bool xk = false; switch (tap->ptr()) { case AnyNull: --- 4675,4714 ---- lazy_klass = _klass; } else { // Something like byte[int+] meets char[int+]. // This must fall to bottom, not (int[-128..65535])[int+]. instance_id = InstanceBot; ! tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable, tary->_not_flat, tary->_not_null_free); ! } ! } else if (klass() != NULL && tap->klass() != NULL && ! klass()->as_array_klass()->storage_properties().value() != tap->klass()->as_array_klass()->storage_properties().value()) { ! // Meeting value type arrays with conflicting storage properties ! if (tary->_elem->isa_valuetype()) { ! // Result is flattened ! off = Offset(elem()->isa_valuetype() ? offset() : tap->offset()); ! field_off = elem()->isa_valuetype() ? field_offset() : tap->field_offset(); ! } else if (tary->_elem->make_oopptr() != NULL && tary->_elem->make_oopptr()->isa_instptr() && below_centerline(ptr)) { ! // Result is non-flattened ! off = Offset(flattened_offset()).meet(Offset(tap->flattened_offset())); ! field_off = Offset::bottom; } } else // Non integral arrays. // Must fall to bottom if exact klasses in upper lattice // are not equal or super klass is exact. if ((above_centerline(ptr) || ptr == Constant) && klass() != tap->klass() && // meet with top[] and bottom[] are processed further down: ! tap->_klass != NULL && this->_klass != NULL && // both are exact and not equal: ((tap->_klass_is_exact && this->_klass_is_exact) || ! // 'tap' is exact and super or unrelated: (tap->_klass_is_exact && !tap->klass()->is_subtype_of(klass())) || // 'this' is exact and super or unrelated: (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) { if (above_centerline(ptr)) { ! tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable, tary->_not_flat, tary->_not_null_free); } ! return make(NotNull, NULL, tary, lazy_klass, false, off, field_off, InstanceBot, speculative, depth); } bool xk = false; switch (tap->ptr()) { case AnyNull:
*** 4361,4371 **** if (below_centerline(this->_ptr)) { xk = this->_klass_is_exact; } else { xk = (tap->_klass_is_exact || this->_klass_is_exact); } ! return make(ptr, const_oop(), tary, lazy_klass, xk, off, instance_id, speculative, depth); case Constant: { ciObject* o = const_oop(); if( _ptr == Constant ) { if( tap->const_oop() != NULL && !o->equals(tap->const_oop()) ) { xk = (klass() == tap->klass()); --- 4717,4727 ---- if (below_centerline(this->_ptr)) { xk = this->_klass_is_exact; } else { xk = (tap->_klass_is_exact || this->_klass_is_exact); } ! return make(ptr, const_oop(), tary, lazy_klass, xk, off, field_off, instance_id, speculative, depth); case Constant: { ciObject* o = const_oop(); if( _ptr == Constant ) { if( tap->const_oop() != NULL && !o->equals(tap->const_oop()) ) { xk = (klass() == tap->klass());
*** 4380,4407 **** xk = true; } else { // Only precise for identical arrays xk = this->_klass_is_exact && (klass() == tap->klass()); } ! return TypeAryPtr::make(ptr, o, tary, lazy_klass, xk, off, instance_id, speculative, depth); } case NotNull: case BotPTR: // Compute new klass on demand, do not use tap->_klass if (above_centerline(this->_ptr)) xk = tap->_klass_is_exact; else xk = (tap->_klass_is_exact & this->_klass_is_exact) && (klass() == tap->klass()); // Only precise for identical arrays ! return TypeAryPtr::make(ptr, NULL, tary, lazy_klass, xk, off, instance_id, speculative, depth); default: ShouldNotReachHere(); } } // All arrays inherit from Object class case InstPtr: { const TypeInstPtr *tp = t->is_instptr(); ! int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (ptr) { --- 4736,4763 ---- xk = true; } else { // Only precise for identical arrays xk = this->_klass_is_exact && (klass() == tap->klass()); } ! return TypeAryPtr::make(ptr, o, tary, lazy_klass, xk, off, field_off, instance_id, speculative, depth); } case NotNull: case BotPTR: // Compute new klass on demand, do not use tap->_klass if (above_centerline(this->_ptr)) xk = tap->_klass_is_exact; else xk = (tap->_klass_is_exact & this->_klass_is_exact) && (klass() == tap->klass()); // Only precise for identical arrays ! return TypeAryPtr::make(ptr, NULL, tary, lazy_klass, xk, off, field_off, instance_id, speculative, depth); default: ShouldNotReachHere(); } } // All arrays inherit from Object class case InstPtr: { const TypeInstPtr *tp = t->is_instptr(); ! Offset offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); const TypePtr* speculative = xmeet_speculative(tp); int depth = meet_inline_depth(tp->inline_depth()); switch (ptr) {
*** 4409,4424 **** case AnyNull: // Fall 'down' to dual of object klass // For instances when a subclass meets a superclass we fall // below the centerline when the superclass is exact. We need to // do the same here. if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) { ! return TypeAryPtr::make(ptr, _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } else { // cannot subclass, so the meet has to fall badly below the centerline ptr = NotNull; instance_id = InstanceBot; ! return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative, depth); } case Constant: case NotNull: case BotPTR: // Fall down to object klass // LCA is object_klass, but if we subclass from the top we can do better --- 4765,4780 ---- case AnyNull: // Fall 'down' to dual of object klass // For instances when a subclass meets a superclass we fall // below the centerline when the superclass is exact. We need to // do the same here. if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) { ! return TypeAryPtr::make(ptr, _ary, _klass, _klass_is_exact, offset, _field_offset, instance_id, speculative, depth); } else { // cannot subclass, so the meet has to fall badly below the centerline ptr = NotNull; instance_id = InstanceBot; ! return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth); } case Constant: case NotNull: case BotPTR: // Fall down to object klass // LCA is object_klass, but if we subclass from the top we can do better
*** 4429,4458 **** // below the centerline when the superclass is exact. We need // to do the same here. if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) { // that is, my array type is a subtype of 'tp' klass return make(ptr, (ptr == Constant ? const_oop() : NULL), ! _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } } // The other case cannot happen, since t cannot be a subtype of an array. // The meet falls down to Object class below centerline. if( ptr == Constant ) ptr = NotNull; instance_id = InstanceBot; ! return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative, depth); default: typerr(t); } } } return this; // Lint noise } //------------------------------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(), is_autobox_cache(), dual_speculative(), dual_inline_depth()); } //----------------------interface_vs_oop--------------------------------------- #ifdef ASSERT bool TypeAryPtr::interface_vs_oop(const Type *t) const { --- 4785,4833 ---- // below the centerline when the superclass is exact. We need // to do the same here. if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) { // that is, my array type is a subtype of 'tp' klass return make(ptr, (ptr == Constant ? const_oop() : NULL), ! _ary, _klass, _klass_is_exact, offset, _field_offset, instance_id, speculative, depth); } } // The other case cannot happen, since t cannot be a subtype of an array. // The meet falls down to Object class below centerline. if( ptr == Constant ) ptr = NotNull; instance_id = InstanceBot; ! return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth); default: typerr(t); } } + + case ValueType: { + // All value types inherit from Object + PTR ptr = this->_ptr; + if (ptr == Constant) { + ptr = NotNull; + } + return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass()); + } + } return this; // Lint noise } //------------------------------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_field_offset(), dual_instance_id(), is_autobox_cache(), dual_speculative(), dual_inline_depth()); ! } ! ! Type::Offset TypeAryPtr::meet_field_offset(const Type::Offset offset) const { ! return _field_offset.meet(offset); ! } ! ! //------------------------------dual_offset------------------------------------ ! Type::Offset TypeAryPtr::dual_field_offset() const { ! return _field_offset.dual(); } //----------------------interface_vs_oop--------------------------------------- #ifdef ASSERT bool TypeAryPtr::interface_vs_oop(const Type *t) const {
*** 4485,4504 **** break; default: break; } ! if( _offset != 0 ) { int header_size = objArrayOopDesc::header_size() * wordSize; ! if( _offset == OffsetTop ) st->print("+undefined"); ! else if( _offset == OffsetBot ) st->print("+any"); ! else if( _offset < header_size ) st->print("+%d", _offset); else { BasicType basic_elem_type = elem()->basic_type(); int array_base = arrayOopDesc::base_offset_in_bytes(basic_elem_type); int elem_size = type2aelembytes(basic_elem_type); ! st->print("[%d]", (_offset - array_base)/elem_size); } } st->print(" *"); if (_instance_id == InstanceTop) st->print(",iid=top"); --- 4860,4884 ---- break; default: break; } ! if (elem()->isa_valuetype()) { ! st->print("("); ! _field_offset.dump2(st); ! st->print(")"); ! } ! if (offset() != 0) { int header_size = objArrayOopDesc::header_size() * wordSize; ! if( _offset == Offset::top ) st->print("+undefined"); ! else if( _offset == Offset::bottom ) st->print("+any"); ! else if( offset() < header_size ) st->print("+%d", offset()); else { BasicType basic_elem_type = elem()->basic_type(); int array_base = arrayOopDesc::base_offset_in_bytes(basic_elem_type); int elem_size = type2aelembytes(basic_elem_type); ! st->print("[%d]", (offset() - array_base)/elem_size); } } st->print(" *"); if (_instance_id == InstanceTop) st->print(",iid=top");
*** 4515,4549 **** return TypeOopPtr::empty(); } //------------------------------add_offset------------------------------------- const TypePtr *TypeAryPtr::add_offset(intptr_t offset) const { ! return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth); } const Type *TypeAryPtr::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(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL, _inline_depth); } const TypePtr *TypeAryPtr::with_inline_depth(int depth) const { if (!UseInlineDepthForSpeculativeTypes) { return this; } ! return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, _speculative, depth); } const TypePtr *TypeAryPtr::with_instance_id(int instance_id) const { assert(is_known_instance(), "should be known"); ! return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, instance_id, _speculative, _inline_depth); } //============================================================================= //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeNarrowPtr::hash(void) const { return _ptrtype->hash() + 7; } --- 4895,4993 ---- return TypeOopPtr::empty(); } //------------------------------add_offset------------------------------------- const TypePtr *TypeAryPtr::add_offset(intptr_t offset) const { ! return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _field_offset, _instance_id, add_offset_speculative(offset), _inline_depth, _is_autobox_cache); } const Type *TypeAryPtr::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(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _field_offset, _instance_id, NULL, _inline_depth, _is_autobox_cache); ! } ! ! const Type* TypeAryPtr::cleanup_speculative() const { ! if (speculative() == NULL) { ! return this; ! } ! // Keep speculative part if it contains information about flat-/nullability ! const TypeAryPtr* spec_aryptr = speculative()->isa_aryptr(); ! if (spec_aryptr != NULL && (spec_aryptr->is_not_flat() || spec_aryptr->is_not_null_free())) { ! return this; ! } ! return TypeOopPtr::cleanup_speculative(); } const TypePtr *TypeAryPtr::with_inline_depth(int depth) const { if (!UseInlineDepthForSpeculativeTypes) { return this; } ! return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _field_offset, _instance_id, _speculative, depth, _is_autobox_cache); ! } ! ! const TypeAryPtr* TypeAryPtr::with_field_offset(int offset) const { ! return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, Offset(offset), _instance_id, _speculative, _inline_depth, _is_autobox_cache); ! } ! ! const TypePtr* TypeAryPtr::add_field_offset_and_offset(intptr_t offset) const { ! int adj = 0; ! if (offset != Type::OffsetBot && offset != Type::OffsetTop) { ! const Type* elemtype = elem(); ! if (elemtype->isa_valuetype()) { ! if (_offset.get() != OffsetBot && _offset.get() != OffsetTop) { ! adj = _offset.get(); ! offset += _offset.get(); ! } ! uint header = arrayOopDesc::base_offset_in_bytes(T_OBJECT); ! if (_field_offset.get() != OffsetBot && _field_offset.get() != OffsetTop) { ! offset += _field_offset.get(); ! if (_offset.get() == OffsetBot || _offset.get() == OffsetTop) { ! offset += header; ! } ! } ! if (offset >= (intptr_t)header || offset < 0) { ! // Try to get the field of the value type array element we are pointing to ! ciKlass* arytype_klass = klass(); ! ciValueArrayKlass* vak = arytype_klass->as_value_array_klass(); ! ciValueKlass* vk = vak->element_klass()->as_value_klass(); ! int shift = vak->log2_element_size(); ! int mask = (1 << shift) - 1; ! intptr_t field_offset = ((offset - header) & mask); ! ciField* field = vk->get_field_by_offset(field_offset + vk->first_field_offset(), false); ! if (field == NULL) { ! // This may happen with nested AddP(base, AddP(base, base, offset), longcon(16)) ! return add_offset(offset); ! } else { ! return with_field_offset(field_offset)->add_offset(offset - field_offset - adj); ! } ! } ! } ! } ! return add_offset(offset - adj); ! } ! ! // Return offset incremented by field_offset for flattened value type arrays ! const int TypeAryPtr::flattened_offset() const { ! int offset = _offset.get(); ! if (offset != Type::OffsetBot && offset != Type::OffsetTop && ! _field_offset != Offset::bottom && _field_offset != Offset::top) { ! offset += _field_offset.get(); ! } ! return offset; } const TypePtr *TypeAryPtr::with_instance_id(int instance_id) const { assert(is_known_instance(), "should be known"); ! return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _field_offset, instance_id, _speculative, _inline_depth); } //============================================================================= + //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeNarrowPtr::hash(void) const { return _ptrtype->hash() + 7; }
*** 4628,4643 **** case AryPtr: case MetadataPtr: case KlassPtr: case NarrowOop: case NarrowKlass: - case Bottom: // Ye Olde Default return Type::BOTTOM; case Top: return this; default: // All else is a mistake typerr(t); } // End of switch --- 5072,5089 ---- case AryPtr: case MetadataPtr: case KlassPtr: case NarrowOop: case NarrowKlass: case Bottom: // Ye Olde Default return Type::BOTTOM; case Top: return this; + case ValueType: + return t->xmeet(this); + default: // All else is a mistake typerr(t); } // End of switch
*** 4712,4722 **** // TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple // constants bool TypeMetadataPtr::singleton(void) const { // detune optimizer to not generate constant metadata + constant offset as a constant! // TopPTR, Null, AnyNull, Constant are all singletons ! return (_offset == 0) && !below_centerline(_ptr); } //------------------------------add_offset------------------------------------- const TypePtr *TypeMetadataPtr::add_offset( intptr_t offset ) const { return make( _ptr, _metadata, xadd_offset(offset)); --- 5158,5168 ---- // TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple // constants bool TypeMetadataPtr::singleton(void) const { // detune optimizer to not generate constant metadata + constant offset as a constant! // TopPTR, Null, AnyNull, Constant are all singletons ! return (offset() == 0) && !below_centerline(_ptr); } //------------------------------add_offset------------------------------------- const TypePtr *TypeMetadataPtr::add_offset( intptr_t offset ) const { return make( _ptr, _metadata, xadd_offset(offset));
*** 4732,4744 **** } //------------------------------get_con---------------------------------------- intptr_t TypeMetadataPtr::get_con() const { assert( _ptr == Null || _ptr == Constant, "" ); ! assert( _offset >= 0, "" ); ! if (_offset != 0) { // After being ported to the compiler interface, the compiler no longer // directly manipulates the addresses of oops. Rather, it only has a pointer // to a handle at compile time. This handle is embedded in the generated // code and dereferenced at the time the nmethod is made. Until that time, // it is not reasonable to do arithmetic with the addresses of oops (we don't --- 5178,5190 ---- } //------------------------------get_con---------------------------------------- intptr_t TypeMetadataPtr::get_con() const { assert( _ptr == Null || _ptr == Constant, "" ); ! assert(offset() >= 0, ""); ! if (offset() != 0) { // After being ported to the compiler interface, the compiler no longer // directly manipulates the addresses of oops. Rather, it only has a pointer // to a handle at compile time. This handle is embedded in the generated // code and dereferenced at the time the nmethod is made. Until that time, // it is not reasonable to do arithmetic with the addresses of oops (we don't
*** 4785,4795 **** typerr(t); case AnyPtr: { // Found an AnyPtr type vs self-OopPtr type const TypePtr *tp = t->is_ptr(); ! int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); switch (tp->ptr()) { case Null: if (ptr == Null) return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); // else fall through: --- 5231,5241 ---- typerr(t); case AnyPtr: { // Found an AnyPtr type vs self-OopPtr type const TypePtr *tp = t->is_ptr(); ! Offset offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); switch (tp->ptr()) { case Null: if (ptr == Null) return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); // else fall through:
*** 4811,4821 **** case AryPtr: return TypePtr::BOTTOM; // Oop meet raw is not well defined case MetadataPtr: { const TypeMetadataPtr *tp = t->is_metadataptr(); ! int offset = meet_offset(tp->offset()); PTR tptr = tp->ptr(); PTR ptr = meet_ptr(tptr); ciMetadata* md = (tptr == TopPTR) ? metadata() : tp->metadata(); if (tptr == TopPTR || _ptr == TopPTR || metadata()->equals(tp->metadata())) { --- 5257,5267 ---- case AryPtr: return TypePtr::BOTTOM; // Oop meet raw is not well defined case MetadataPtr: { const TypeMetadataPtr *tp = t->is_metadataptr(); ! Offset offset = meet_offset(tp->offset()); PTR tptr = tp->ptr(); PTR ptr = meet_ptr(tptr); ciMetadata* md = (tptr == TopPTR) ? metadata() : tp->metadata(); if (tptr == TopPTR || _ptr == TopPTR || metadata()->equals(tp->metadata())) {
*** 4844,4881 **** //------------------------------dump2------------------------------------------ #ifndef PRODUCT void TypeMetadataPtr::dump2( Dict &d, uint depth, outputStream *st ) const { st->print("metadataptr:%s", ptr_msg[_ptr]); if( metadata() ) st->print(INTPTR_FORMAT, p2i(metadata())); ! switch( _offset ) { case OffsetTop: st->print("+top"); break; case OffsetBot: st->print("+any"); break; case 0: break; ! default: st->print("+%d",_offset); break; } } #endif //============================================================================= // Convenience common pre-built type. const TypeMetadataPtr *TypeMetadataPtr::BOTTOM; ! TypeMetadataPtr::TypeMetadataPtr(PTR ptr, ciMetadata* metadata, int offset): TypePtr(MetadataPtr, ptr, offset), _metadata(metadata) { } const TypeMetadataPtr* TypeMetadataPtr::make(ciMethod* m) { ! return make(Constant, m, 0); } const TypeMetadataPtr* TypeMetadataPtr::make(ciMethodData* m) { ! return make(Constant, m, 0); } //------------------------------make------------------------------------------- // Create a meta data constant ! const TypeMetadataPtr *TypeMetadataPtr::make(PTR ptr, ciMetadata* m, int offset) { assert(m == NULL || !m->is_klass(), "wrong type"); return (TypeMetadataPtr*)(new TypeMetadataPtr(ptr, m, offset))->hashcons(); } --- 5290,5327 ---- //------------------------------dump2------------------------------------------ #ifndef PRODUCT void TypeMetadataPtr::dump2( Dict &d, uint depth, outputStream *st ) const { st->print("metadataptr:%s", ptr_msg[_ptr]); if( metadata() ) st->print(INTPTR_FORMAT, p2i(metadata())); ! switch (offset()) { case OffsetTop: st->print("+top"); break; case OffsetBot: st->print("+any"); break; case 0: break; ! default: st->print("+%d",offset()); break; } } #endif //============================================================================= // Convenience common pre-built type. const TypeMetadataPtr *TypeMetadataPtr::BOTTOM; ! TypeMetadataPtr::TypeMetadataPtr(PTR ptr, ciMetadata* metadata, Offset offset): TypePtr(MetadataPtr, ptr, offset), _metadata(metadata) { } const TypeMetadataPtr* TypeMetadataPtr::make(ciMethod* m) { ! return make(Constant, m, Offset(0)); } const TypeMetadataPtr* TypeMetadataPtr::make(ciMethodData* m) { ! return make(Constant, m, Offset(0)); } //------------------------------make------------------------------------------- // Create a meta data constant ! const TypeMetadataPtr* TypeMetadataPtr::make(PTR ptr, ciMetadata* m, Offset offset) { assert(m == NULL || !m->is_klass(), "wrong type"); return (TypeMetadataPtr*)(new TypeMetadataPtr(ptr, m, offset))->hashcons(); }
*** 4885,4931 **** // Not-null object klass or below const TypeKlassPtr *TypeKlassPtr::OBJECT; const TypeKlassPtr *TypeKlassPtr::OBJECT_OR_NULL; //------------------------------TypeKlassPtr----------------------------------- ! TypeKlassPtr::TypeKlassPtr( PTR ptr, ciKlass* klass, int offset ) : TypePtr(KlassPtr, ptr, offset), _klass(klass), _klass_is_exact(ptr == Constant) { } //------------------------------make------------------------------------------- // ptr to klass 'k', if Constant, or possibly to a sub-klass if not a Constant ! const TypeKlassPtr *TypeKlassPtr::make( PTR ptr, ciKlass* k, int offset ) { ! assert( k != NULL, "Expect a non-NULL klass"); ! assert(k->is_instance_klass() || k->is_array_klass(), "Incorrect type of klass oop"); ! TypeKlassPtr *r = ! (TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset))->hashcons(); ! ! return r; } //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypeKlassPtr::eq( const Type *t ) const { const TypeKlassPtr *p = t->is_klassptr(); ! return ! klass()->equals(p->klass()) && ! TypePtr::eq(p); } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeKlassPtr::hash(void) const { ! return java_add((jint)klass()->hash(), (jint)TypePtr::hash()); } //------------------------------singleton-------------------------------------- // TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple // constants bool TypeKlassPtr::singleton(void) const { // detune optimizer to not generate constant klass + constant offset as a constant! // TopPTR, Null, AnyNull, Constant are all singletons ! return (_offset == 0) && !below_centerline(_ptr); } // Do not allow interface-vs.-noninterface joins to collapse to top. const Type *TypeKlassPtr::filter_helper(const Type *kills, bool include_speculative) const { // logic here mirrors the one from TypeOopPtr::filter. See comments --- 5331,5371 ---- // Not-null object klass or below const TypeKlassPtr *TypeKlassPtr::OBJECT; const TypeKlassPtr *TypeKlassPtr::OBJECT_OR_NULL; //------------------------------TypeKlassPtr----------------------------------- ! TypeKlassPtr::TypeKlassPtr( PTR ptr, ciKlass* klass, Offset offset ) : TypePtr(KlassPtr, ptr, offset), _klass(klass), _klass_is_exact(ptr == Constant) { } //------------------------------make------------------------------------------- // ptr to klass 'k', if Constant, or possibly to a sub-klass if not a Constant ! const TypeKlassPtr* TypeKlassPtr::make(PTR ptr, ciKlass* k, Offset offset) { ! assert(k == NULL || k->is_instance_klass() || k->is_array_klass(), "Incorrect type of klass oop"); ! return (TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset))->hashcons(); } //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypeKlassPtr::eq( const Type *t ) const { const TypeKlassPtr *p = t->is_klassptr(); ! return klass() == p->klass() && TypePtr::eq(p); } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeKlassPtr::hash(void) const { ! return java_add(klass() != NULL ? klass()->hash() : (jint)0, (jint)TypePtr::hash()); } //------------------------------singleton-------------------------------------- // TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple // constants bool TypeKlassPtr::singleton(void) const { // detune optimizer to not generate constant klass + constant offset as a constant! // TopPTR, Null, AnyNull, Constant are all singletons ! return (offset() == 0) && !below_centerline(_ptr); } // Do not allow interface-vs.-noninterface joins to collapse to top. const Type *TypeKlassPtr::filter_helper(const Type *kills, bool include_speculative) const { // logic here mirrors the one from TypeOopPtr::filter. See comments
*** 4933,4943 **** const Type* ft = join_helper(kills, include_speculative); const TypeKlassPtr* ftkp = ft->isa_klassptr(); const TypeKlassPtr* ktkp = kills->isa_klassptr(); if (ft->empty()) { ! if (!empty() && ktkp != NULL && ktkp->klass()->is_loaded() && ktkp->klass()->is_interface()) return kills; // Uplift to interface return Type::TOP; // Canonical empty value } --- 5373,5383 ---- const Type* ft = join_helper(kills, include_speculative); const TypeKlassPtr* ftkp = ft->isa_klassptr(); const TypeKlassPtr* ktkp = kills->isa_klassptr(); if (ft->empty()) { ! if (!empty() && ktkp != NULL && ktkp->is_loaded() && ktkp->klass()->is_interface()) return kills; // Uplift to interface return Type::TOP; // Canonical empty value }
*** 4956,4976 **** //----------------------compute_klass------------------------------------------ // Compute the defining klass for this class ciKlass* TypeAryPtr::compute_klass(DEBUG_ONLY(bool verify)) const { // Compute _klass based on element type. ciKlass* k_ary = NULL; - const TypeInstPtr *tinst; const TypeAryPtr *tary; const Type* el = elem(); if (el->isa_narrowoop()) { el = el->make_ptr(); } // Get element klass ! if ((tinst = el->isa_instptr()) != NULL) { ! // Compute array klass from element klass ! k_ary = ciObjArrayKlass::make(tinst->klass()); } else if ((tary = el->isa_aryptr()) != NULL) { // Compute array klass from element klass ciKlass* k_elem = tary->klass(); // If element type is something like bottom[], k_elem will be null. if (k_elem != NULL) --- 5396,5420 ---- //----------------------compute_klass------------------------------------------ // Compute the defining klass for this class ciKlass* TypeAryPtr::compute_klass(DEBUG_ONLY(bool verify)) const { // Compute _klass based on element type. ciKlass* k_ary = NULL; const TypeAryPtr *tary; const Type* el = elem(); if (el->isa_narrowoop()) { el = el->make_ptr(); } // Get element klass ! if (el->isa_instptr()) { ! // Compute object array klass from element klass ! bool null_free = el->is_valuetypeptr() && el->isa_instptr()->ptr() != TypePtr::TopPTR && !el->isa_instptr()->maybe_null(); ! k_ary = ciArrayKlass::make(el->is_oopptr()->klass(), null_free); ! } else if (el->isa_valuetype()) { ! if (el->value_klass() != NULL) { ! k_ary = ciArrayKlass::make(el->value_klass(), /* null_free */ true); ! } } else if ((tary = el->isa_aryptr()) != NULL) { // Compute array klass from element klass ciKlass* k_elem = tary->klass(); // If element type is something like bottom[], k_elem will be null. if (k_elem != NULL)
*** 5031,5041 **** // Recomputing the underlying ciKlass for each request is // a bit less efficient than caching, but calls to // TypeAryPtr::OOPS->klass() are not common enough to matter. ((TypeAryPtr*)this)->_klass = k_ary; if (UseCompressedOops && k_ary != NULL && k_ary->is_obj_array_klass() && ! _offset != 0 && _offset != arrayOopDesc::length_offset_in_bytes()) { ((TypeAryPtr*)this)->_is_ptr_to_narrowoop = true; } } return k_ary; } --- 5475,5485 ---- // Recomputing the underlying ciKlass for each request is // a bit less efficient than caching, but calls to // TypeAryPtr::OOPS->klass() are not common enough to matter. ((TypeAryPtr*)this)->_klass = k_ary; if (UseCompressedOops && k_ary != NULL && k_ary->is_obj_array_klass() && ! offset() != 0 && offset() != arrayOopDesc::length_offset_in_bytes()) { ((TypeAryPtr*)this)->_is_ptr_to_narrowoop = true; } } return k_ary; }
*** 5066,5075 **** --- 5510,5520 ---- //-----------------------------as_instance_type-------------------------------- // Corresponding type for an instance of the given class. // It will be NotNull, and exact if and only if the klass type is exact. const TypeOopPtr* TypeKlassPtr::as_instance_type() const { ciKlass* k = klass(); + assert(k != NULL, "klass should not be NULL"); bool xk = klass_is_exact(); //return TypeInstPtr::make(TypePtr::NotNull, k, xk, NULL, 0); const TypeOopPtr* toop = TypeOopPtr::make_from_klass_raw(k); guarantee(toop != NULL, "need type for given klass"); toop = toop->cast_to_ptr_type(TypePtr::NotNull)->is_oopptr();
*** 5105,5115 **** typerr(t); case AnyPtr: { // Meeting to AnyPtrs // Found an AnyPtr type vs self-KlassPtr type const TypePtr *tp = t->is_ptr(); ! int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); switch (tp->ptr()) { case TopPTR: return this; case Null: --- 5550,5560 ---- typerr(t); case AnyPtr: { // Meeting to AnyPtrs // Found an AnyPtr type vs self-KlassPtr type const TypePtr *tp = t->is_ptr(); ! Offset offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); switch (tp->ptr()) { case TopPTR: return this; case Null:
*** 5146,5158 **** // A-bot } // case KlassPtr: { // Meet two KlassPtr types const TypeKlassPtr *tkls = t->is_klassptr(); ! int off = meet_offset(tkls->offset()); PTR ptr = meet_ptr(tkls->ptr()); // Check for easy case; klasses are equal (and perhaps not loaded!) // If we have constants, then we created oops so classes are loaded // and we can handle the constants further down. This case handles // not-loaded classes if( ptr != Constant && tkls->klass()->equals(klass()) ) { --- 5591,5611 ---- // A-bot } // case KlassPtr: { // Meet two KlassPtr types const TypeKlassPtr *tkls = t->is_klassptr(); ! Offset off = meet_offset(tkls->offset()); PTR ptr = meet_ptr(tkls->ptr()); + if (klass() == NULL || tkls->klass() == NULL) { + ciKlass* k = NULL; + if (ptr == Constant) { + k = (klass() == NULL) ? tkls->klass() : klass(); + } + return make(ptr, k, off); + } + // Check for easy case; klasses are equal (and perhaps not loaded!) // If we have constants, then we created oops so classes are loaded // and we can handle the constants further down. This case handles // not-loaded classes if( ptr != Constant && tkls->klass()->equals(klass()) ) {
*** 5214,5226 **** } //------------------------------get_con---------------------------------------- intptr_t TypeKlassPtr::get_con() const { assert( _ptr == Null || _ptr == Constant, "" ); ! assert( _offset >= 0, "" ); ! if (_offset != 0) { // After being ported to the compiler interface, the compiler no longer // directly manipulates the addresses of oops. Rather, it only has a pointer // to a handle at compile time. This handle is embedded in the generated // code and dereferenced at the time the nmethod is made. Until that time, // it is not reasonable to do arithmetic with the addresses of oops (we don't --- 5667,5679 ---- } //------------------------------get_con---------------------------------------- intptr_t TypeKlassPtr::get_con() const { assert( _ptr == Null || _ptr == Constant, "" ); ! assert(offset() >= 0, ""); ! if (offset() != 0) { // After being ported to the compiler interface, the compiler no longer // directly manipulates the addresses of oops. Rather, it only has a pointer // to a handle at compile time. This handle is embedded in the generated // code and dereferenced at the time the nmethod is made. Until that time, // it is not reasonable to do arithmetic with the addresses of oops (we don't
*** 5239,5253 **** switch( _ptr ) { case Constant: st->print("precise "); case NotNull: { ! const char *name = klass()->name()->as_utf8(); ! if( name ) { st->print("klass %s: " INTPTR_FORMAT, name, p2i(klass())); } else { ! ShouldNotReachHere(); } } case BotPTR: if( !WizardMode && !Verbose && !_klass_is_exact ) break; case TopPTR: --- 5692,5706 ---- switch( _ptr ) { case Constant: st->print("precise "); case NotNull: { ! if (klass() != NULL) { ! const char* name = klass()->name()->as_utf8(); st->print("klass %s: " INTPTR_FORMAT, name, p2i(klass())); } else { ! st->print("klass BOTTOM"); } } case BotPTR: if( !WizardMode && !Verbose && !_klass_is_exact ) break; case TopPTR:
*** 5257,5271 **** break; default: break; } ! if( _offset ) { // Dump offset, if any ! if( _offset == OffsetBot ) { st->print("+any"); } ! else if( _offset == OffsetTop ) { st->print("+unknown"); } ! else { st->print("+%d", _offset); } ! } st->print(" *"); } #endif --- 5710,5720 ---- break; default: break; } ! _offset.dump2(st); st->print(" *"); } #endif
*** 5273,5299 **** //============================================================================= // Convenience common pre-built types. //------------------------------make------------------------------------------- ! const TypeFunc *TypeFunc::make( const TypeTuple *domain, const TypeTuple *range ) { ! return (TypeFunc*)(new TypeFunc(domain,range))->hashcons(); } //------------------------------make------------------------------------------- const TypeFunc *TypeFunc::make(ciMethod* method) { Compile* C = Compile::current(); const TypeFunc* tf = C->last_tf(method); // check cache if (tf != NULL) return tf; // The hit rate here is almost 50%. ! const TypeTuple *domain; ! if (method->is_static()) { ! domain = TypeTuple::make_domain(NULL, method->signature()); ! } else { ! domain = TypeTuple::make_domain(method->holder(), method->signature()); ! } ! const TypeTuple *range = TypeTuple::make_range(method->signature()); ! tf = TypeFunc::make(domain, range); C->set_last_tf(method, tf); // fill cache return tf; } //------------------------------meet------------------------------------------- --- 5722,5757 ---- //============================================================================= // Convenience common pre-built types. //------------------------------make------------------------------------------- ! const TypeFunc *TypeFunc::make(const TypeTuple *domain_sig, const TypeTuple* domain_cc, ! const TypeTuple *range_sig, const TypeTuple *range_cc) { ! return (TypeFunc*)(new TypeFunc(domain_sig, domain_cc, range_sig, range_cc))->hashcons(); ! } ! ! const TypeFunc *TypeFunc::make(const TypeTuple *domain, const TypeTuple *range) { ! return make(domain, domain, range, range); } //------------------------------make------------------------------------------- const TypeFunc *TypeFunc::make(ciMethod* method) { Compile* C = Compile::current(); const TypeFunc* tf = C->last_tf(method); // check cache if (tf != NULL) return tf; // The hit rate here is almost 50%. ! // Value types are not passed/returned by reference, instead each field of ! // the value type is passed/returned as an argument. We maintain two views of ! // the argument/return list here: one based on the signature (with a value ! // type argument/return as a single slot), one based on the actual calling ! // convention (with a value type argument/return as a list of its fields). ! const TypeTuple* domain_sig = TypeTuple::make_domain(method, false); ! const TypeTuple* domain_cc = method->has_scalarized_args() ? TypeTuple::make_domain(method, true) : domain_sig; ! ciSignature* sig = method->signature(); ! bool has_scalarized_ret = sig->returns_never_null() && sig->return_type()->as_value_klass()->can_be_returned_as_fields(); ! const TypeTuple* range_sig = TypeTuple::make_range(sig, false); ! const TypeTuple* range_cc = has_scalarized_ret ? TypeTuple::make_range(sig, true) : range_sig; ! tf = TypeFunc::make(domain_sig, domain_cc, range_sig, range_cc); C->set_last_tf(method, tf); // fill cache return tf; } //------------------------------meet-------------------------------------------
*** 5325,5370 **** //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypeFunc::eq( const Type *t ) const { const TypeFunc *a = (const TypeFunc*)t; ! return _domain == a->_domain && ! _range == a->_range; } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeFunc::hash(void) const { ! return (intptr_t)_domain + (intptr_t)_range; } //------------------------------dump2------------------------------------------ // Dump Function Type #ifndef PRODUCT void TypeFunc::dump2( Dict &d, uint depth, outputStream *st ) const { ! if( _range->cnt() <= Parms ) st->print("void"); else { uint i; ! for (i = Parms; i < _range->cnt()-1; i++) { ! _range->field_at(i)->dump2(d,depth,st); st->print("/"); } ! _range->field_at(i)->dump2(d,depth,st); } st->print(" "); st->print("( "); if( !depth || d[this] ) { // Check for recursive dump st->print("...)"); return; } d.Insert((void*)this,(void*)this); // Stop recursion ! if (Parms < _domain->cnt()) ! _domain->field_at(Parms)->dump2(d,depth-1,st); ! for (uint i = Parms+1; i < _domain->cnt(); i++) { st->print(", "); ! _domain->field_at(i)->dump2(d,depth-1,st); } st->print(" )"); } #endif --- 5783,5830 ---- //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypeFunc::eq( const Type *t ) const { const TypeFunc *a = (const TypeFunc*)t; ! return _domain_sig == a->_domain_sig && ! _domain_cc == a->_domain_cc && ! _range_sig == a->_range_sig && ! _range_cc == a->_range_cc; } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeFunc::hash(void) const { ! return (intptr_t)_domain_sig + (intptr_t)_domain_cc + (intptr_t)_range_sig + (intptr_t)_range_cc; } //------------------------------dump2------------------------------------------ // Dump Function Type #ifndef PRODUCT void TypeFunc::dump2( Dict &d, uint depth, outputStream *st ) const { ! if( _range_sig->cnt() <= Parms ) st->print("void"); else { uint i; ! for (i = Parms; i < _range_sig->cnt()-1; i++) { ! _range_sig->field_at(i)->dump2(d,depth,st); st->print("/"); } ! _range_sig->field_at(i)->dump2(d,depth,st); } st->print(" "); st->print("( "); if( !depth || d[this] ) { // Check for recursive dump st->print("...)"); return; } d.Insert((void*)this,(void*)this); // Stop recursion ! if (Parms < _domain_sig->cnt()) ! _domain_sig->field_at(Parms)->dump2(d,depth-1,st); ! for (uint i = Parms+1; i < _domain_sig->cnt(); i++) { st->print(", "); ! _domain_sig->field_at(i)->dump2(d,depth-1,st); } st->print(" )"); } #endif
*** 5380,5389 **** return false; // Never empty } BasicType TypeFunc::return_type() const{ ! if (range()->cnt() == TypeFunc::Parms) { return T_VOID; } ! return range()->field_at(TypeFunc::Parms)->basic_type(); } --- 5840,5849 ---- return false; // Never empty } BasicType TypeFunc::return_type() const{ ! if (range_sig()->cnt() == TypeFunc::Parms) { return T_VOID; } ! return range_sig()->field_at(TypeFunc::Parms)->basic_type(); }
< prev index next >