< prev index next >
src/share/vm/opto/type.cpp
Print this page
@@ -589,10 +589,12 @@
TypeNarrowOop::NULL_PTR = TypeNarrowOop::make( TypePtr::NULL_PTR );
TypeNarrowOop::BOTTOM = TypeNarrowOop::make( TypeInstPtr::BOTTOM );
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;
mreg2type[Op_RegI] = TypeInt::INT;
mreg2type[Op_RegP] = TypePtr::BOTTOM;
@@ -1912,16 +1914,70 @@
const TypeTuple *TypeTuple::INT_PAIR;
const TypeTuple *TypeTuple::LONG_PAIR;
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:
field_array[TypeFunc::Parms] = TypeLong::LONG;
field_array[TypeFunc::Parms+1] = Type::HALF;
@@ -1929,40 +1985,38 @@
case T_DOUBLE:
field_array[TypeFunc::Parms] = Type::DOUBLE;
field_array[TypeFunc::Parms+1] = 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[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:
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;
@@ -4699,10 +4753,11 @@
//=============================================================================
//=============================================================================
+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();
}
@@ -4806,10 +4861,26 @@
int depth = meet_inline_depth(tp->inline_depth());
// Compute constant oop
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) ) {
o = this_oop;
} else if (above_centerline(this ->_ptr)) {
@@ -4818,11 +4889,11 @@
o = this_oop;
} else {
ptr = NotNull;
}
}
- return make(_vt, ptr, o, offset, instance_id, speculative, depth);
+ return make(vt, ptr, o, offset, instance_id, speculative, depth);
}
}
}
// Dual: compute field-by-field dual
@@ -5591,16 +5662,17 @@
//=============================================================================
// 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-------------------------------------------
const TypeFunc *TypeFunc::make(ciMethod* method) {
Compile* C = Compile::current();
@@ -5618,12 +5690,13 @@
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);
+ 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;
}
//------------------------------meet-------------------------------------------
@@ -5657,32 +5730,33 @@
// 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;
+ _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("( ");
if( !depth || d[this] ) { // Check for recursive dump
st->print("...)");
@@ -5711,10 +5785,10 @@
return false; // Never empty
}
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();
}
< prev index next >