< prev index next >
src/share/vm/opto/graphKit.cpp
Print this page
*** 47,64 ****
#include "runtime/deoptimization.hpp"
#include "runtime/sharedRuntime.hpp"
//----------------------------GraphKit-----------------------------------------
// Main utility constructor.
! GraphKit::GraphKit(JVMState* jvms)
: Phase(Phase::Parser),
_env(C->env()),
! _gvn(*C->initial_gvn())
{
_exceptions = jvms->map()->next_exception();
if (_exceptions != NULL) jvms->map()->set_next_exception(NULL);
set_jvms(jvms);
}
// Private constructor for parser.
GraphKit::GraphKit()
: Phase(Phase::Parser),
--- 47,70 ----
#include "runtime/deoptimization.hpp"
#include "runtime/sharedRuntime.hpp"
//----------------------------GraphKit-----------------------------------------
// Main utility constructor.
! GraphKit::GraphKit(JVMState* jvms, PhaseGVN* gvn)
: Phase(Phase::Parser),
_env(C->env()),
! _gvn((gvn != NULL) ? *gvn : *C->initial_gvn())
{
_exceptions = jvms->map()->next_exception();
if (_exceptions != NULL) jvms->map()->set_next_exception(NULL);
set_jvms(jvms);
+ #ifdef ASSERT
+ if (_gvn.is_IterGVN() != NULL) {
+ // Save the initial size of _for_igvn worklist for verification (see ~GraphKit)
+ _worklist_size = _gvn.C->for_igvn()->size();
+ }
+ #endif
}
// Private constructor for parser.
GraphKit::GraphKit()
: Phase(Phase::Parser),
*** 1381,1402 ****
} else {
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency, unaligned, mismatched);
}
ld = _gvn.transform(ld);
if (bt == T_VALUETYPE) {
! // Load non-flattened value type from memory. Add a null check and let the
! // interpreter take care of initializing the field to the default value type.
! Node* null_ctl = top();
! ld = null_check_common(ld, bt, false, &null_ctl, false);
! if (null_ctl != top()) {
! assert(!adr_type->isa_aryptr(), "value type array must be initialized");
! PreserveJVMState pjvms(this);
! set_control(null_ctl);
! uncommon_trap(Deoptimization::reason_null_check(false), Deoptimization::Action_maybe_recompile,
! t->is_valuetypeptr()->value_type()->value_klass(), "uninitialized non-flattened value type");
! }
! ld = ValueTypeNode::make(gvn(), map()->memory(), ld);
} else if (((bt == T_OBJECT) && C->do_escape_analysis()) || C->eliminate_boxing()) {
// Improve graph before escape analysis and boxing elimination.
record_for_igvn(ld);
}
return ld;
--- 1387,1398 ----
} else {
ld = LoadNode::make(_gvn, ctl, mem, adr, adr_type, t, bt, mo, control_dependency, unaligned, mismatched);
}
ld = _gvn.transform(ld);
if (bt == T_VALUETYPE) {
! // Loading a non-flattened value type from memory requires a null check.
! ld = ValueTypeNode::make(this, ld, true /* null check */);
} else if (((bt == T_OBJECT) && C->do_escape_analysis()) || C->eliminate_boxing()) {
// Improve graph before escape analysis and boxing elimination.
record_for_igvn(ld);
}
return ld;
*** 1533,1545 ****
assert(bt == T_OBJECT || bt == T_VALUETYPE, "sanity");
assert(val != NULL, "not dead path");
uint adr_idx = C->get_alias_index(adr_type);
assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" );
! if (bt == T_VALUETYPE) {
! // Allocate value type and store oop
! val = val->as_ValueType()->allocate(this);
}
pre_barrier(true /* do_load */,
control(), obj, adr, adr_idx, val, val_type,
NULL /* pre_val */,
--- 1529,1541 ----
assert(bt == T_OBJECT || bt == T_VALUETYPE, "sanity");
assert(val != NULL, "not dead path");
uint adr_idx = C->get_alias_index(adr_type);
assert(adr_idx != Compile::AliasIdxTop, "use other store_to_memory factory" );
! if (val->is_ValueType()) {
! // Allocate value type and get oop
! val = val->as_ValueType()->allocate(this)->get_oop();
}
pre_barrier(true /* do_load */,
control(), obj, adr, adr_idx, val, val_type,
NULL /* pre_val */,
*** 1628,1658 ****
for (uint i = TypeFunc::Parms, idx = TypeFunc::Parms; i < nargs; i++) {
Node* arg = argument(i-TypeFunc::Parms);
if (ValueTypePassFieldsAsArgs) {
if (arg->is_ValueType()) {
ValueTypeNode* vt = arg->as_ValueType();
! if (domain->field_at(i)->is_valuetypeptr()->klass() != C->env()->___Value_klass()) {
// We don't pass value type arguments by reference but instead
// pass each field of the value type
idx += vt->pass_fields(call, idx, *this);
// If a value type argument is passed as fields, attach the Method* to the call site
// to be able to access the extended signature later via attached_method_before_pc().
// For example, see CompiledMethod::preserve_callee_argument_oops().
call->set_override_symbolic_info(true);
} else {
! arg = arg->as_ValueType()->allocate(this);
call->init_req(idx, arg);
idx++;
}
} else {
call->init_req(idx, arg);
idx++;
}
} else {
if (arg->is_ValueType()) {
// Pass value type argument via oop to callee
! arg = arg->as_ValueType()->allocate(this);
}
call->init_req(i, arg);
}
}
}
--- 1624,1654 ----
for (uint i = TypeFunc::Parms, idx = TypeFunc::Parms; i < nargs; i++) {
Node* arg = argument(i-TypeFunc::Parms);
if (ValueTypePassFieldsAsArgs) {
if (arg->is_ValueType()) {
ValueTypeNode* vt = arg->as_ValueType();
! if (!domain->field_at(i)->is_valuetypeptr()->is__Value()) {
// We don't pass value type arguments by reference but instead
// pass each field of the value type
idx += vt->pass_fields(call, idx, *this);
// If a value type argument is passed as fields, attach the Method* to the call site
// to be able to access the extended signature later via attached_method_before_pc().
// For example, see CompiledMethod::preserve_callee_argument_oops().
call->set_override_symbolic_info(true);
} else {
! arg = arg->as_ValueType()->allocate(this)->get_oop();
call->init_req(idx, arg);
idx++;
}
} else {
call->init_req(idx, arg);
idx++;
}
} else {
if (arg->is_ValueType()) {
// Pass value type argument via oop to callee
! arg = arg->as_ValueType()->allocate(this)->get_oop();
}
call->init_req(i, arg);
}
}
}
*** 1689,1729 ****
}
Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_proj) {
if (stopped()) return top(); // maybe the call folded up?
// Capture the return value, if any.
Node* ret;
if (call->method() == NULL ||
! call->method()->return_type()->basic_type() == T_VOID)
ret = top();
! else {
if (!call->tf()->returns_value_type_as_fields()) {
ret = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
} else {
// Return of multiple values (value type fields): we create a
// ValueType node, each field is a projection from the call.
! const TypeTuple *range_sig = call->tf()->range_sig();
const Type* t = range_sig->field_at(TypeFunc::Parms);
assert(t->isa_valuetypeptr(), "only value types for multiple return values");
ciValueKlass* vk = t->is_valuetypeptr()->value_type()->value_klass();
! ret = ValueTypeNode::make(_gvn, call, vk, TypeFunc::Parms+1, false);
}
}
- // Note: Since any out-of-line call can produce an exception,
- // we always insert an I_O projection from the call into the result.
-
- make_slow_call_ex(call, env()->Throwable_klass(), separate_io_proj);
-
- if (separate_io_proj) {
- // The caller requested separate projections be used by the fall
- // through and exceptional paths, so replace the projections for
- // the fall through path.
- set_i_o(_gvn.transform( new ProjNode(call, TypeFunc::I_O) ));
- set_all_memory(_gvn.transform( new ProjNode(call, TypeFunc::Memory) ));
- }
return ret;
}
//--------------------set_predefined_input_for_runtime_call--------------------
// Reading and setting the memory state is way conservative here.
--- 1685,1728 ----
}
Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_proj) {
if (stopped()) return top(); // maybe the call folded up?
+ // Note: Since any out-of-line call can produce an exception,
+ // we always insert an I_O projection from the call into the result.
+
+ make_slow_call_ex(call, env()->Throwable_klass(), separate_io_proj);
+
+ if (separate_io_proj) {
+ // The caller requested separate projections be used by the fall
+ // through and exceptional paths, so replace the projections for
+ // the fall through path.
+ set_i_o(_gvn.transform( new ProjNode(call, TypeFunc::I_O) ));
+ set_all_memory(_gvn.transform( new ProjNode(call, TypeFunc::Memory) ));
+ }
+
// Capture the return value, if any.
Node* ret;
if (call->method() == NULL ||
! call->method()->return_type()->basic_type() == T_VOID) {
ret = top();
! } else {
if (!call->tf()->returns_value_type_as_fields()) {
ret = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
} else {
// Return of multiple values (value type fields): we create a
// ValueType node, each field is a projection from the call.
! const TypeTuple* range_sig = call->tf()->range_sig();
const Type* t = range_sig->field_at(TypeFunc::Parms);
assert(t->isa_valuetypeptr(), "only value types for multiple return values");
ciValueKlass* vk = t->is_valuetypeptr()->value_type()->value_klass();
! Node* ctl = control();
! ret = ValueTypeNode::make(_gvn, ctl, merged_memory(), call, vk, TypeFunc::Parms+1, false);
! set_control(ctl);
}
}
return ret;
}
//--------------------set_predefined_input_for_runtime_call--------------------
// Reading and setting the memory state is way conservative here.
*** 3395,3405 ****
// - deoptimize_on_exception controls how Java exceptions are handled (rethrow vs deoptimize)
Node* GraphKit::new_instance(Node* klass_node,
Node* extra_slow_test,
Node* *return_size_val,
bool deoptimize_on_exception,
! ValueTypeNode* value_node) {
// Compute size in doublewords
// The size is always an integral number of doublewords, represented
// as a positive bytewise size stored in the klass's layout_helper.
// The layout_helper also encodes (in a low bit) the need for a slow path.
jint layout_con = Klass::_lh_neutral_value;
--- 3394,3404 ----
// - deoptimize_on_exception controls how Java exceptions are handled (rethrow vs deoptimize)
Node* GraphKit::new_instance(Node* klass_node,
Node* extra_slow_test,
Node* *return_size_val,
bool deoptimize_on_exception,
! ValueTypeBaseNode* value_node) {
// Compute size in doublewords
// The size is always an integral number of doublewords, represented
// as a positive bytewise size stored in the klass's layout_helper.
// The layout_helper also encodes (in a low bit) the need for a slow path.
jint layout_con = Klass::_lh_neutral_value;
*** 3691,3701 ****
SafePointNode* loop_map = NULL;
{
PreserveJVMState pjvms(this);
// Create default value type and store it to memory
Node* oop = ValueTypeNode::make_default(gvn(), vk);
! oop = oop->as_ValueType()->allocate(this);
length = SubI(length, intcon(1));
add_predicate(nargs);
RegionNode* loop = new RegionNode(3);
loop->init_req(1, control());
--- 3690,3700 ----
SafePointNode* loop_map = NULL;
{
PreserveJVMState pjvms(this);
// Create default value type and store it to memory
Node* oop = ValueTypeNode::make_default(gvn(), vk);
! oop = oop->as_ValueType()->allocate(this)->get_oop();
length = SubI(length, intcon(1));
add_predicate(nargs);
RegionNode* loop = new RegionNode(3);
loop->init_req(1, control());
*** 4562,4572 ****
/*is_unsigned_load=*/false);
if (con_type != NULL) {
Node* con = makecon(con_type);
if (field->layout_type() == T_VALUETYPE) {
// Load value type from constant oop
! con = ValueTypeNode::make(gvn(), map()->memory(), con);
}
return con;
}
return NULL;
}
--- 4561,4571 ----
/*is_unsigned_load=*/false);
if (con_type != NULL) {
Node* con = makecon(con_type);
if (field->layout_type() == T_VALUETYPE) {
// Load value type from constant oop
! con = ValueTypeNode::make(this, con);
}
return con;
}
return NULL;
}
< prev index next >