< prev index next >

src/share/vm/opto/type.cpp

Print this page
rev 10512 : value type calling convention

*** 21,30 **** --- 21,31 ---- * 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"
*** 1809,1835 **** 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; --- 1810,1870 ---- ShouldNotReachHere(); } 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(); + int vt_extra = 0; + if (vt_fields_as_args) { + for (int i = 0; i < sig->count(); i++) { + ciType* type = sig->type_at(i); + if (type->basic_type() == T_VALUETYPE) { + assert(type->is_valuetype(), "inconsistent type"); + ciValueKlass* vk = (ciValueKlass*)type; + vt_extra += vk->extra_value_args(); + } + } + assert(((int)arg_cnt) + vt_extra >= 0, "negative number of actual arguments?"); + } + uint pos = TypeFunc::Parms; const Type **field_array; if (recv != NULL) { arg_cnt++; ! if (vt_fields_as_args && recv->is_valuetype()) { ! ciValueKlass* vk = (ciValueKlass*)recv; ! vt_extra += vk->extra_value_args(); ! } ! field_array = fields(arg_cnt + vt_extra); // Use get_const_type here because it respects UseUniqueSubclasses: + if (vt_fields_as_args && 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 + vt_extra); } int i = 0; ! while (pos < TypeFunc::Parms + arg_cnt + vt_extra) { ciType* type = sig->type_at(i); switch (type->basic_type()) { case T_LONG: field_array[pos++] = TypeLong::LONG;
*** 1838,1864 **** case T_DOUBLE: field_array[pos++] = Type::DOUBLE; field_array[pos++] = Type::HALF; break; case T_OBJECT: - case T_VALUETYPE: case T_ARRAY: case T_BOOLEAN: case T_CHAR: case T_FLOAT: case T_BYTE: case T_SHORT: case T_INT: field_array[pos++] = get_const_type(type); break; default: ShouldNotReachHere(); } i++; } ! return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt, field_array))->hashcons(); } const TypeTuple *TypeTuple::make( uint cnt, const Type **fields ) { return (TypeTuple*)(new TypeTuple(cnt,fields))->hashcons(); } --- 1873,1909 ---- case T_DOUBLE: field_array[pos++] = Type::DOUBLE; field_array[pos++] = Type::HALF; break; case T_OBJECT: case T_ARRAY: case T_BOOLEAN: case T_CHAR: case T_FLOAT: case T_BYTE: case T_SHORT: case T_INT: field_array[pos++] = get_const_type(type); break; + case T_VALUETYPE: { + assert(type->is_valuetype(), "inconsistent type"); + if (vt_fields_as_args) { + 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, "wrong number of arguments"); ! return (TypeTuple*)(new TypeTuple(TypeFunc::Parms + arg_cnt + vt_extra, field_array))->hashcons(); } const TypeTuple *TypeTuple::make( uint cnt, const Type **fields ) { return (TypeTuple*)(new TypeTuple(cnt,fields))->hashcons(); }
*** 5383,5409 **** //============================================================================= // 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------------------------------------------- --- 5428,5466 ---- //============================================================================= // 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, const TypeTuple *range ) { ! return make(domain, domain, 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%. ! 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_sig = TypeTuple::make_domain(NULL, method->signature(), false); ! domain_cc = TypeTuple::make_domain(NULL, method->signature(), ValueTypePassFieldsAsArgs); } else { ! 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); C->set_last_tf(method, tf); // fill cache return tf; } //------------------------------meet-------------------------------------------
*** 5435,5452 **** //------------------------------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 --- 5492,5510 ---- //------------------------------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 == a->_range; } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeFunc::hash(void) const { ! return (intptr_t)_domain_sig + (intptr_t)_domain_cc + (intptr_t)_range; } //------------------------------dump2------------------------------------------ // Dump Function Type #ifndef PRODUCT
*** 5466,5480 **** 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 --- 5524,5538 ---- 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
< prev index next >