--- old/src/share/vm/opto/type.cpp 2016-11-24 11:13:30.194563584 +0100 +++ new/src/share/vm/opto/type.cpp 2016-11-24 11:13:30.126563975 +0100 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "ci/ciField.hpp" #include "ci/ciMethodData.hpp" #include "ci/ciTypeFlow.hpp" #include "ci/ciValueKlass.hpp" @@ -1810,23 +1811,70 @@ return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt, field_array))->hashcons(); } +static int extra_value_fields(ciValueKlass* vk) { + int vt_extra = vk->nof_nonstatic_fields() - 1; + 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, "embedded"); + if (bt == T_LONG || bt == T_DOUBLE) { + vt_extra++; + } + } + return vt_extra; +} + +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) { +const TypeTuple *TypeTuple::make_domain(ciInstanceKlass* recv, ciSignature* sig, bool is_cc) { uint arg_cnt = sig->size(); + int vt_extra = 0; + if (is_cc) { + for (int i = 0; i < sig->count(); i++) { + ciType* type = sig->type_at(i); + if (type->basic_type() == T_VALUETYPE) { + assert(type->is_valuetype(), ""); + ciValueKlass* vk = (ciValueKlass*)type; + vt_extra += extra_value_fields(vk); + } + } + assert(((int)arg_cnt) + vt_extra >= 0, ""); + } + uint pos = TypeFunc::Parms; const Type **field_array; if (recv != NULL) { arg_cnt++; - field_array = fields(arg_cnt); + if (is_cc && recv->is_valuetype()) { + ciValueKlass* vk = (ciValueKlass*)recv; + vt_extra += extra_value_fields(vk); + } + field_array = fields(arg_cnt + vt_extra); // Use get_const_type here because it respects UseUniqueSubclasses: - field_array[pos++] = get_const_type(recv)->join_speculative(TypePtr::NOTNULL); + if (is_cc && recv->is_valuetype()) { + ciValueKlass* vk = (ciValueKlass*)recv; + collect_value_fields(vk, field_array, pos); + } else { + field_array[pos++] = get_const_type(recv)->join_speculative(TypePtr::NOTNULL); + } } else { - field_array = fields(arg_cnt); + field_array = fields(arg_cnt + vt_extra); } int i = 0; - while (pos < TypeFunc::Parms + arg_cnt) { + while (pos < TypeFunc::Parms + arg_cnt + vt_extra) { ciType* type = sig->type_at(i); switch (type->basic_type()) { @@ -1839,7 +1887,6 @@ field_array[pos++] = Type::HALF; break; case T_OBJECT: - case T_VALUETYPE: case T_ARRAY: case T_BOOLEAN: case T_CHAR: @@ -1849,13 +1896,24 @@ case T_INT: field_array[pos++] = get_const_type(type); break; + case T_VALUETYPE: { + assert(type->is_valuetype(), ""); + if (is_cc) { + ciValueKlass* vk = (ciValueKlass*)type; + collect_value_fields(vk, field_array, pos); + } else { + field_array[pos++] = get_const_type(type); + } + break; + } default: ShouldNotReachHere(); } i++; } + assert(pos == TypeFunc::Parms + arg_cnt + vt_extra, ""); - return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt, field_array))->hashcons(); + return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt + vt_extra, field_array))->hashcons(); } const TypeTuple *TypeTuple::make( uint cnt, const Type **fields ) { @@ -5366,8 +5424,8 @@ // Convenience common pre-built types. //------------------------------make------------------------------------------- -const TypeFunc *TypeFunc::make( const TypeTuple *domain, const TypeTuple *range ) { - return (TypeFunc*)(new TypeFunc(domain,range))->hashcons(); +const TypeFunc *TypeFunc::make( const TypeTuple *domain, const TypeTuple* domain_cc, const TypeTuple *range ) { + return (TypeFunc*)(new TypeFunc(domain, domain_cc, range))->hashcons(); } //------------------------------make------------------------------------------- @@ -5375,14 +5433,22 @@ 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; + const TypeTuple *domain_sig, *domain_cc; + // Value type arguments are not passed by reference, instead each + // field of the value type is passed as an argument. We maintain 2 + // views of the argument list here: one based on the signature (with + // a value type argument as a single slot), one based on the actual + // calling convention (with a value type argument as a list of its + // fields). if (method->is_static()) { - domain = TypeTuple::make_domain(NULL, method->signature()); + domain_sig = TypeTuple::make_domain(NULL, method->signature(), false); + domain_cc = TypeTuple::make_domain(NULL, method->signature(), ValueTypePassFieldsAsArgs); } else { - domain = TypeTuple::make_domain(method->holder(), method->signature()); + 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, range); + tf = TypeFunc::make(domain_sig, domain_cc, range); C->set_last_tf(method, tf); // fill cache return tf; } @@ -5418,14 +5484,15 @@ // Structural equality check for Type representations bool TypeFunc::eq( const Type *t ) const { const TypeFunc *a = (const TypeFunc*)t; - return _domain == a->_domain && + return _domain_sig == a->_domain_sig && + _domain_cc == a->_domain_cc && _range == a->_range; } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeFunc::hash(void) const { - return (intptr_t)_domain + (intptr_t)_range; + return (intptr_t)_domain_sig + (intptr_t)_domain_cc + (intptr_t)_range; } //------------------------------dump2------------------------------------------ @@ -5449,11 +5516,11 @@ 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++) { + 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->field_at(i)->dump2(d,depth-1,st); + _domain_sig->field_at(i)->dump2(d,depth-1,st); } st->print(" )"); }