< prev index next >
src/hotspot/share/opto/parse1.cpp
Print this page
*** 607,626 ****
// Handle value type arguments
int arg_size_sig = tf()->domain_sig()->cnt();
for (uint i = 0; i < (uint)arg_size_sig; i++) {
Node* parm = map()->in(i);
const Type* t = _gvn.type(parm);
- if (!ValueTypePassFieldsAsArgs) {
if (t->is_valuetypeptr() && t->value_klass()->is_scalarizable() && !t->maybe_null()) {
// Create ValueTypeNode from the oop and replace the parameter
Node* vt = ValueTypeNode::make_from_oop(this, parm, t->value_klass());
map()->replace_edge(parm, vt);
}
- } else {
- assert(false, "FIXME");
- // TODO move the code from build_start_state and do_late_inline here
- }
}
entry_map = map(); // capture any changes performed by method setup code
assert(jvms()->endoff() == map()->req(), "map matches JVMS layout");
--- 607,621 ----
*** 840,855 ****
//----------------------------build_start_state-------------------------------
// Construct a state which contains only the incoming arguments from an
// unknown caller. The method & bci will be NULL & InvocationEntryBci.
JVMState* Compile::build_start_state(StartNode* start, const TypeFunc* tf) {
! int arg_size_sig = tf->domain_sig()->cnt();
! int max_size = MAX2(arg_size_sig, (int)tf->range_cc()->cnt());
JVMState* jvms = new (this) JVMState(max_size - TypeFunc::Parms);
SafePointNode* map = new SafePointNode(max_size, NULL);
record_for_igvn(map);
! assert(arg_size_sig == TypeFunc::Parms + (is_osr_compilation() ? 1 : method()->arg_size()), "correct arg_size");
Node_Notes* old_nn = default_node_notes();
if (old_nn != NULL && has_method()) {
Node_Notes* entry_nn = old_nn->clone(this);
JVMState* entry_jvms = new(this) JVMState(method(), old_nn->jvms());
entry_jvms->set_offsets(0);
--- 835,852 ----
//----------------------------build_start_state-------------------------------
// Construct a state which contains only the incoming arguments from an
// unknown caller. The method & bci will be NULL & InvocationEntryBci.
JVMState* Compile::build_start_state(StartNode* start, const TypeFunc* tf) {
! int arg_size = tf->domain_sig()->cnt();
! int max_size = MAX2(arg_size, (int)tf->range_cc()->cnt());
JVMState* jvms = new (this) JVMState(max_size - TypeFunc::Parms);
SafePointNode* map = new SafePointNode(max_size, NULL);
+ map->set_jvms(jvms);
+ jvms->set_map(map);
record_for_igvn(map);
! assert(arg_size == TypeFunc::Parms + (is_osr_compilation() ? 1 : method()->arg_size()), "correct arg_size");
Node_Notes* old_nn = default_node_notes();
if (old_nn != NULL && has_method()) {
Node_Notes* entry_nn = old_nn->clone(this);
JVMState* entry_jvms = new(this) JVMState(method(), old_nn->jvms());
entry_jvms->set_offsets(0);
*** 857,916 ****
entry_nn->set_jvms(entry_jvms);
set_default_node_notes(entry_nn);
}
PhaseGVN& gvn = *initial_gvn();
uint j = 0;
! for (uint i = 0; i < (uint)arg_size_sig; i++) {
! assert(j >= i, "less actual arguments than in the signature?");
! if (ValueTypePassFieldsAsArgs) {
! assert(false, "FIXME");
! // TODO move this into Parse::Parse because we might need to deopt
! /*
! if (i < TypeFunc::Parms) {
! assert(i == j, "no change before the actual arguments");
! Node* parm = gvn.transform(new ParmNode(start, i));
! map->init_req(i, parm);
! // Record all these guys for later GVN.
! record_for_igvn(parm);
! j++;
! } else {
! // Value type arguments are not passed by reference: we get an
! // argument per field of the value type. Build ValueTypeNodes
! // from the value type arguments.
const Type* t = tf->domain_sig()->field_at(i);
! if (t->is_valuetypeptr()) {
! ciValueKlass* vk = t->value_klass();
GraphKit kit(jvms, &gvn);
kit.set_control(map->control());
! ValueTypeNode* vt = ValueTypeNode::make_from_multi(&kit, start, vk, j, true);
map->set_control(kit.control());
! map->init_req(i, vt);
! j += vk->value_arg_slots();
} else {
! Node* parm = gvn.transform(new ParmNode(start, j));
! map->init_req(i, parm);
! // Record all these guys for later GVN.
! record_for_igvn(parm);
! j++;
}
}
- */
- } else {
- Node* parm = gvn.transform(new ParmNode(start, i));
map->init_req(i, parm);
// Record all these guys for later GVN.
record_for_igvn(parm);
- j++;
- }
}
for (; j < map->req(); j++) {
map->init_req(j, top());
}
assert(jvms->argoff() == TypeFunc::Parms, "parser gets arguments here");
set_default_node_notes(old_nn);
- map->set_jvms(jvms);
- jvms->set_map(map);
return jvms;
}
//-----------------------------make_node_notes---------------------------------
Node_Notes* Parse::make_node_notes(Node_Notes* caller_nn) {
--- 854,898 ----
entry_nn->set_jvms(entry_jvms);
set_default_node_notes(entry_nn);
}
PhaseGVN& gvn = *initial_gvn();
uint j = 0;
! for (uint i = 0; i < (uint)arg_size; i++) {
const Type* t = tf->domain_sig()->field_at(i);
! Node* parm = NULL;
! // TODO for now, don't scalarize value type receivers because of interface calls
! if (has_scalarized_args() && t->is_valuetypeptr() && (method()->is_static() || i != TypeFunc::Parms)) {
! // Value type arguments are not passed by reference: we get an argument per
! // field of the value type. Build ValueTypeNodes from the value type arguments.
GraphKit kit(jvms, &gvn);
kit.set_control(map->control());
! Node* old_mem = map->memory();
! // Use immutable memory for value type loads and restore it below
! // TODO make sure value types are always loaded from immutable memory
! kit.set_all_memory(C->immutable_memory());
! parm = ValueTypeNode::make_from_multi(&kit, start, t->value_klass(), j, true);
map->set_control(kit.control());
! map->set_memory(old_mem);
} else {
! int index = j;
! SigEntry res_slot = get_res_entry();
! if (res_slot._offset != -1 && (index - TypeFunc::Parms) >= res_slot._offset) {
! // Skip reserved entry
! index += type2size[res_slot._bt];
}
+ parm = gvn.transform(new ParmNode(start, index));
+ j++;
}
map->init_req(i, parm);
// Record all these guys for later GVN.
record_for_igvn(parm);
}
for (; j < map->req(); j++) {
map->init_req(j, top());
}
assert(jvms->argoff() == TypeFunc::Parms, "parser gets arguments here");
set_default_node_notes(old_nn);
return jvms;
}
//-----------------------------make_node_notes---------------------------------
Node_Notes* Parse::make_node_notes(Node_Notes* caller_nn) {
*** 941,954 ****
kit.sync_jvms();
Node* res = kit.argument(0);
if (tf()->returns_value_type_as_fields()) {
// Multiple return values (value type fields): add as many edges
// to the Return node as returned values.
! assert(res->is_ValueType(), "what else supports multi value return");
ValueTypeNode* vt = res->as_ValueType();
ret->add_req_batch(NULL, tf()->range_cc()->cnt() - TypeFunc::Parms);
! vt->pass_klass(ret, TypeFunc::Parms, kit);
vt->pass_fields(ret, TypeFunc::Parms+1, kit, /* assert_allocated */ true);
} else {
ret->add_req(res);
// Note: The second dummy edge is not needed by a ReturnNode.
}
--- 923,940 ----
kit.sync_jvms();
Node* res = kit.argument(0);
if (tf()->returns_value_type_as_fields()) {
// Multiple return values (value type fields): add as many edges
// to the Return node as returned values.
! assert(res->is_ValueType(), "what else supports multi value return?");
ValueTypeNode* vt = res->as_ValueType();
ret->add_req_batch(NULL, tf()->range_cc()->cnt() - TypeFunc::Parms);
! if (vt->is_allocated(&kit.gvn()) && !StressValueTypeReturnedAsFields) {
! ret->init_req(TypeFunc::Parms, vt->get_oop());
! } else {
! ret->init_req(TypeFunc::Parms, vt->tagged_klass(kit.gvn()));
! }
vt->pass_fields(ret, TypeFunc::Parms+1, kit, /* assert_allocated */ true);
} else {
ret->add_req(res);
// Note: The second dummy edge is not needed by a ReturnNode.
}
*** 2322,2337 ****
}
//------------------------------return_current---------------------------------
// Append current _map to _exit_return
void Parse::return_current(Node* value) {
- if (tf()->returns_value_type_as_fields()) {
- assert(false, "Fix this with the calling convention changes");
- // Value type is returned as fields, make sure non-flattened value type fields are allocated
- // value = value->as_ValueType()->allocate_fields(this);
- }
-
if (RegisterFinalizersAtInit &&
method()->intrinsic_id() == vmIntrinsics::_Object_init) {
call_register_finalizer();
}
--- 2308,2317 ----
*** 2348,2360 ****
}
// frame pointer is always same, already captured
if (value != NULL) {
Node* phi = _exits.argument(0);
const TypeOopPtr* tr = phi->bottom_type()->isa_oopptr();
if (value->is_ValueType() && !_caller->has_method()) {
! // Value type is returned as oop from root method, make sure it's allocated
value = value->as_ValueType()->allocate(this)->get_oop();
} else if (tr && tr->isa_instptr() && tr->klass()->is_loaded() && tr->klass()->is_interface()) {
// If returning oops to an interface-return, there is a silent free
// cast from oop to interface allowed by the Verifier. Make it explicit here.
const TypeInstPtr* tp = value->bottom_type()->isa_instptr();
if (tp && tp->klass()->is_loaded() && !tp->klass()->is_interface()) {
--- 2328,2350 ----
}
// frame pointer is always same, already captured
if (value != NULL) {
Node* phi = _exits.argument(0);
const TypeOopPtr* tr = phi->bottom_type()->isa_oopptr();
+ if (tf()->returns_value_type_as_fields() && !_caller->has_method() && !value->is_ValueType()) {
+ // TODO there should be a checkcast in between, right?
+ value = ValueTypeNode::make_from_oop(this, value, phi->bottom_type()->is_valuetype()->value_klass());
+ }
if (value->is_ValueType() && !_caller->has_method()) {
! // Value type is returned as oop from root method
! if (tf()->returns_value_type_as_fields()) {
! // Make sure non-flattened value type fields are allocated
! value = value->as_ValueType()->allocate_fields(this);
! } else {
! // Make sure value type is allocated
value = value->as_ValueType()->allocate(this)->get_oop();
+ }
} else if (tr && tr->isa_instptr() && tr->klass()->is_loaded() && tr->klass()->is_interface()) {
// If returning oops to an interface-return, there is a silent free
// cast from oop to interface allowed by the Verifier. Make it explicit here.
const TypeInstPtr* tp = value->bottom_type()->isa_instptr();
if (tp && tp->klass()->is_loaded() && !tp->klass()->is_interface()) {
< prev index next >