< prev index next >
src/share/vm/opto/type.cpp
Print this page
@@ -21,10 +21,11 @@
* 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"
@@ -1808,27 +1809,74 @@
ShouldNotReachHere();
}
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:
+ 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()) {
case T_LONG:
field_array[pos++] = TypeLong::LONG;
@@ -1837,27 +1885,37 @@
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;
+ 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 ) {
return (TypeTuple*)(new TypeTuple(cnt,fields))->hashcons();
}
@@ -5364,27 +5422,35 @@
//=============================================================================
// 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-------------------------------------------
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;
+ 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;
}
//------------------------------meet-------------------------------------------
@@ -5416,18 +5482,19 @@
//------------------------------eq---------------------------------------------
// 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------------------------------------------
// Dump Function Type
#ifndef PRODUCT
@@ -5447,15 +5514,15 @@
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++) {
+ 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(" )");
}
#endif
< prev index next >