< 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 >