< prev index next >
src/hotspot/share/opto/graphKit.cpp
Print this page
*** 1395,1404 ****
--- 1395,1405 ----
//------------------------------cast_not_null----------------------------------
// Cast obj to not-null on this path
Node* GraphKit::cast_not_null(Node* obj, bool do_replace_in_map) {
+ assert(!obj->is_ValueType(), "should not cast value type");
const Type *t = _gvn.type(obj);
const Type *t_not_null = t->join_speculative(TypePtr::NOTNULL);
// Object is already not-null?
if( t == t_not_null ) return obj;
*** 1770,1787 ****
} else {
// Pass value type argument via oop to callee
arg = vt->allocate(this)->get_oop();
}
} else if (t->is_valuetypeptr()) {
// Constant null passed for a value type argument
assert(arg->bottom_type()->remove_speculative() == TypePtr::NULL_PTR, "Anything other than null?");
- ciMethod* declared_method = method()->get_method_at_bci(bci());
int arg_size = declared_method->signature()->arg_size_for_bc(java_bc());
inc_sp(arg_size); // restore arguments
uncommon_trap(Deoptimization::Reason_null_check, Deoptimization::Action_none);
return;
}
call->init_req(idx, arg);
idx++;
}
}
--- 1771,1796 ----
} else {
// Pass value type argument via oop to callee
arg = vt->allocate(this)->get_oop();
}
} else if (t->is_valuetypeptr()) {
+ ciMethod* declared_method = method()->get_method_at_bci(bci());
+ if (arg->is_ValueTypePtr()) {
+ // We are calling an Object method with a value type receiver
+ ValueTypePtrNode* vt = arg->isa_ValueTypePtr();
+ assert(i == TypeFunc::Parms && !declared_method->is_static(), "argument must be receiver");
+ assert(vt->is_allocated(&gvn()), "argument must be allocated");
+ arg = vt->get_oop();
+ } else {
// Constant null passed for a value type argument
assert(arg->bottom_type()->remove_speculative() == TypePtr::NULL_PTR, "Anything other than null?");
int arg_size = declared_method->signature()->arg_size_for_bc(java_bc());
inc_sp(arg_size); // restore arguments
uncommon_trap(Deoptimization::Reason_null_check, Deoptimization::Action_none);
return;
}
+ }
call->init_req(idx, arg);
idx++;
}
}
*** 3272,3288 ****
res = ValueTypeNode::make_from_oop(this, res, toop->value_klass(), /* buffer_check */ false, /* null2default */ false);
}
return res;
}
// Deoptimize if 'ary' is flattened or if 'obj' is null and 'ary' is a value type array
void GraphKit::gen_value_type_array_guard(Node* ary, Node* obj, Node* elem_klass) {
assert(EnableValhalla, "should only be used if value types are enabled");
if (elem_klass == NULL) {
// Load array element klass
Node* kls = load_object_klass(ary);
! Node* k_adr = basic_plus_adr(kls, kls, in_bytes(ArrayKlass::element_klass_offset()));
elem_klass = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), k_adr, TypeInstPtr::KLASS));
}
// Check if element is a value type
Node* flags_addr = basic_plus_adr(elem_klass, in_bytes(Klass::access_flags_offset()));
Node* flags = make_load(NULL, flags_addr, TypeInt::INT, T_INT, MemNode::unordered);
--- 3281,3318 ----
res = ValueTypeNode::make_from_oop(this, res, toop->value_klass(), /* buffer_check */ false, /* null2default */ false);
}
return res;
}
+ // Deoptimize if 'obj' is a value type
+ void GraphKit::gen_value_type_guard(Node* obj, int nargs) {
+ assert(EnableValhalla, "should only be used if value types are enabled");
+ Node* bol = NULL;
+ if (obj->is_ValueTypeBase()) {
+ bol = intcon(0);
+ } else {
+ Node* kls = load_object_klass(obj);
+ Node* flags_addr = basic_plus_adr(kls, in_bytes(Klass::access_flags_offset()));
+ Node* flags = make_load(NULL, flags_addr, TypeInt::INT, T_INT, MemNode::unordered);
+ Node* is_value = _gvn.transform(new AndINode(flags, intcon(JVM_ACC_VALUE)));
+ Node* cmp = _gvn.transform(new CmpINode(is_value, intcon(0)));
+ bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
+ }
+ { BuildCutout unless(this, bol, PROB_MAX);
+ inc_sp(nargs);
+ uncommon_trap(Deoptimization::Reason_class_check,
+ Deoptimization::Action_none);
+ }
+ }
+
// Deoptimize if 'ary' is flattened or if 'obj' is null and 'ary' is a value type array
void GraphKit::gen_value_type_array_guard(Node* ary, Node* obj, Node* elem_klass) {
assert(EnableValhalla, "should only be used if value types are enabled");
if (elem_klass == NULL) {
// Load array element klass
Node* kls = load_object_klass(ary);
! Node* k_adr = basic_plus_adr(kls, in_bytes(ArrayKlass::element_klass_offset()));
elem_klass = _gvn.transform(LoadKlassNode::make(_gvn, NULL, immutable_memory(), k_adr, TypeInstPtr::KLASS));
}
// Check if element is a value type
Node* flags_addr = basic_plus_adr(elem_klass, in_bytes(Klass::access_flags_offset()));
Node* flags = make_load(NULL, flags_addr, TypeInt::INT, T_INT, MemNode::unordered);
*** 3324,3334 ****
void GraphKit::gen_flattened_array_guard(Node* ary, int nargs) {
assert(EnableValhalla, "should only be used if value types are enabled");
if (ValueArrayFlatten) {
// Cannot statically determine if array is flattened, emit runtime check
Node* kls = load_object_klass(ary);
! Node* lhp = basic_plus_adr(kls, kls, in_bytes(Klass::layout_helper_offset()));
Node* layout_val = make_load(NULL, lhp, TypeInt::INT, T_INT, MemNode::unordered);
layout_val = _gvn.transform(new RShiftINode(layout_val, intcon(Klass::_lh_array_tag_shift)));
Node* cmp = _gvn.transform(new CmpINode(layout_val, intcon(Klass::_lh_array_tag_vt_value)));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::ne));
--- 3354,3364 ----
void GraphKit::gen_flattened_array_guard(Node* ary, int nargs) {
assert(EnableValhalla, "should only be used if value types are enabled");
if (ValueArrayFlatten) {
// Cannot statically determine if array is flattened, emit runtime check
Node* kls = load_object_klass(ary);
! Node* lhp = basic_plus_adr(kls, in_bytes(Klass::layout_helper_offset()));
Node* layout_val = make_load(NULL, lhp, TypeInt::INT, T_INT, MemNode::unordered);
layout_val = _gvn.transform(new RShiftINode(layout_val, intcon(Klass::_lh_array_tag_shift)));
Node* cmp = _gvn.transform(new CmpINode(layout_val, intcon(Klass::_lh_array_tag_vt_value)));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::ne));
*** 3404,3413 ****
--- 3434,3450 ----
// %%% SynchronizationEntryBCI is redundant; use InvocationEntryBci in interfaces
assert(SynchronizationEntryBCI == InvocationEntryBci, "");
if( !GenerateSynchronizationCode )
return NULL; // Not locking things?
+
+ // We cannot lock on a value type
+ const TypeOopPtr* objptr = _gvn.type(obj)->make_oopptr();
+ if (objptr->can_be_value_type()) {
+ gen_value_type_guard(obj, 1);
+ }
+
if (stopped()) // Dead monitor?
return NULL;
assert(dead_locals_are_killed(), "should kill locals before sync. point");
*** 3476,3485 ****
--- 3513,3523 ----
return;
if (stopped()) { // Dead monitor?
map()->pop_monitor(); // Kill monitor from debug info
return;
}
+ assert(!obj->is_ValueTypeBase(), "should not unlock on value type");
// Memory barrier to avoid floating things down past the locked region
insert_mem_bar(Op_MemBarReleaseLock);
const TypeFunc *tf = OptoRuntime::complete_monitor_exit_Type();
< prev index next >