--- old/src/share/vm/opto/type.cpp 2017-06-01 17:27:46.737201433 +0200 +++ new/src/share/vm/opto/type.cpp 2017-06-01 17:27:46.660201533 +0200 @@ -591,6 +591,8 @@ TypeNarrowKlass::NULL_PTR = TypeNarrowKlass::make( TypePtr::NULL_PTR ); + TypeValueTypePtr::NOTNULL = EnableValhalla ? TypeValueTypePtr::make(TypePtr::NotNull, current->env()->___Value_klass()->as_value_klass()) : NULL; + mreg2type[Op_Node] = Type::BOTTOM; mreg2type[Op_Set ] = 0; mreg2type[Op_RegN] = TypeNarrowOop::BOTTOM; @@ -1914,12 +1916,66 @@ 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) { + for (int j = 0; j < vk->nof_nonstatic_fields(); j++) { + ciField* f = vk->nonstatic_field_at(j); + BasicType bt = f->type()->basic_type(); + assert(bt < T_VALUETYPE && bt >= T_BOOLEAN, "not yet supported"); + field_array[pos++] = Type::get_const_type(f->type()); + if (bt == T_LONG || bt == T_DOUBLE) { + field_array[pos++] = Type::HALF; + } + } +} + +// Can a value type instance of this type be returned as multiple +// returned values? +static bool vt_can_be_returned_as_fields(ciValueKlass* vk) { + if (vk == ciEnv::current()->___Value_klass()) { + return false; + } + + ResourceMark rm; + uint args = vk->value_arg_slots() + 1 /* return vk as well */; + + BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, args); + VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, args); + + sig_bt[0] = T_METADATA; + for (uint i = 0, j = 1; i < (uint)vk->nof_nonstatic_fields(); i++) { + BasicType bt = vk->nonstatic_field_at(i)->layout_type(); + assert(i+j < args, "out of bounds access"); + sig_bt[i+j] = bt; + if (bt == T_LONG || bt == T_DOUBLE) { + j++; + assert(i+j < args, "out of bounds access"); + sig_bt[i+j] = T_VOID; + } + } + + if (SharedRuntime::java_return_convention(sig_bt, regs, args) <= 0) { + return false; + } + + return true; +} + //------------------------------make------------------------------------------- // Make a TypeTuple from the range of a method signature -const TypeTuple *TypeTuple::make_range(ciSignature* sig) { +const TypeTuple *TypeTuple::make_range(ciSignature* sig, bool ret_vt_fields) { ciType* return_type = sig->return_type(); - uint arg_cnt = return_type->size(); + uint arg_cnt = 0; + if (ret_vt_fields) { + ret_vt_fields = return_type->is_valuetype() && vt_can_be_returned_as_fields((ciValueKlass*)return_type); + } + if (ret_vt_fields) { + ciValueKlass* vk = (ciValueKlass*)return_type; + arg_cnt = vk->value_arg_slots()+1; + } else { + arg_cnt = return_type->size(); + } + const Type **field_array = fields(arg_cnt); switch (return_type->basic_type()) { case T_LONG: @@ -1931,7 +1987,6 @@ field_array[TypeFunc::Parms+1] = Type::HALF; break; case T_OBJECT: - case T_VALUETYPE: case T_ARRAY: case T_BOOLEAN: case T_CHAR: @@ -1941,6 +1996,17 @@ case T_INT: field_array[TypeFunc::Parms] = get_const_type(return_type); break; + case T_VALUETYPE: + if (ret_vt_fields) { + ciValueKlass* vk = (ciValueKlass*)return_type; + uint pos = TypeFunc::Parms; + field_array[pos] = TypeKlassPtr::make(vk); + pos++; + collect_value_fields(vk, field_array, pos); + } else { + field_array[TypeFunc::Parms] = get_const_type(return_type); + } + break; case T_VOID: break; default: @@ -1949,18 +2015,6 @@ return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt, field_array))->hashcons(); } -static void collect_value_fields(ciValueKlass* vk, const Type**& field_array, uint& pos) { - for (int j = 0; j < vk->nof_nonstatic_fields(); j++) { - ciField* f = vk->nonstatic_field_at(j); - BasicType bt = f->type()->basic_type(); - assert(bt < T_VALUETYPE && bt >= T_BOOLEAN, "not yet supported"); - field_array[pos++] = Type::get_const_type(f->type()); - if (bt == T_LONG || bt == T_DOUBLE) { - field_array[pos++] = Type::HALF; - } - } -} - // Make a TypeTuple from the domain of a method signature const TypeTuple *TypeTuple::make_domain(ciInstanceKlass* recv, ciSignature* sig, bool vt_fields_as_args) { uint arg_cnt = sig->size(); @@ -4701,6 +4755,7 @@ //============================================================================= +const TypeValueTypePtr* TypeValueTypePtr::NOTNULL; //------------------------------make------------------------------------------- const TypeValueTypePtr* TypeValueTypePtr::make(const TypeValueType* vt, PTR ptr, ciObject* o, Offset offset, int instance_id, const TypePtr* speculative, int inline_depth) { return (TypeValueTypePtr*)(new TypeValueTypePtr(vt, ptr, o, offset, instance_id, speculative, inline_depth))->hashcons(); @@ -4808,6 +4863,22 @@ ciObject* o = NULL; ciObject* this_oop = const_oop(); ciObject* tp_oop = tp->const_oop(); + const TypeValueType* vt = NULL; + if (_vt != tp->_vt) { + ciKlass* __value_klass = ciEnv::current()->___Value_klass(); + assert(klass() == __value_klass || tp->klass() == __value_klass, "impossible meet"); + if (above_centerline(ptr)) { + vt = klass() == __value_klass ? tp->_vt : _vt; + } else if (above_centerline(this->_ptr) && !above_centerline(tp->_ptr)) { + vt = tp->_vt; + } else if (above_centerline(tp->_ptr) && !above_centerline(this->_ptr)) { + vt = _vt; + } else { + vt = klass() == __value_klass ? _vt : tp->_vt; + } + } else { + vt = _vt; + } if (ptr == Constant) { if (this_oop != NULL && tp_oop != NULL && this_oop->equals(tp_oop) ) { @@ -4820,7 +4891,7 @@ ptr = NotNull; } } - return make(_vt, ptr, o, offset, instance_id, speculative, depth); + return make(vt, ptr, o, offset, instance_id, speculative, depth); } } } @@ -5593,12 +5664,13 @@ // Convenience common pre-built types. //------------------------------make------------------------------------------- -const TypeFunc *TypeFunc::make( const TypeTuple *domain_sig, const TypeTuple* domain_cc, const TypeTuple *range ) { - return (TypeFunc*)(new TypeFunc(domain_sig, domain_cc, range))->hashcons(); +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); +const TypeFunc *TypeFunc::make(const TypeTuple *domain, const TypeTuple *range) { + return make(domain, domain, range, range); } //------------------------------make------------------------------------------- @@ -5620,8 +5692,9 @@ domain_sig = TypeTuple::make_domain(method->holder(), method->signature(), false); domain_cc = TypeTuple::make_domain(method->holder(), method->signature(), ValueTypePassFieldsAsArgs); } - const TypeTuple *range = TypeTuple::make_range(method->signature()); - tf = TypeFunc::make(domain_sig, domain_cc, range); + const TypeTuple *range_sig = TypeTuple::make_range(method->signature(), false); + const TypeTuple *range_cc = TypeTuple::make_range(method->signature(), ValueTypeReturnedAsFields); + tf = TypeFunc::make(domain_sig, domain_cc, range_sig, range_cc); C->set_last_tf(method, tf); // fill cache return tf; } @@ -5659,28 +5732,29 @@ const TypeFunc *a = (const TypeFunc*)t; return _domain_sig == a->_domain_sig && _domain_cc == a->_domain_cc && - _range == a->_range; + _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; + 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->cnt() <= Parms ) + if( _range_sig->cnt() <= Parms ) st->print("void"); else { uint i; - for (i = Parms; i < _range->cnt()-1; i++) { - _range->field_at(i)->dump2(d,depth,st); + for (i = Parms; i < _range_sig->cnt()-1; i++) { + _range_sig->field_at(i)->dump2(d,depth,st); st->print("/"); } - _range->field_at(i)->dump2(d,depth,st); + _range_sig->field_at(i)->dump2(d,depth,st); } st->print(" "); st->print("( "); @@ -5713,8 +5787,8 @@ BasicType TypeFunc::return_type() const{ - if (range()->cnt() == TypeFunc::Parms) { + if (range_sig()->cnt() == TypeFunc::Parms) { return T_VOID; } - return range()->field_at(TypeFunc::Parms)->basic_type(); + return range_sig()->field_at(TypeFunc::Parms)->basic_type(); }