< prev index next >
src/share/vm/opto/graphKit.cpp
Print this page
@@ -47,18 +47,24 @@
#include "runtime/deoptimization.hpp"
#include "runtime/sharedRuntime.hpp"
//----------------------------GraphKit-----------------------------------------
// Main utility constructor.
-GraphKit::GraphKit(JVMState* jvms)
+GraphKit::GraphKit(JVMState* jvms, PhaseGVN* gvn)
: Phase(Phase::Parser),
_env(C->env()),
- _gvn(*C->initial_gvn())
+ _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,22 +1387,12 @@
} 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);
+ // 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,13 +1529,13 @@
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);
+ 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,31 +1624,31 @@
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()) {
+ 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);
+ 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);
+ arg = arg->as_ValueType()->allocate(this)->get_oop();
}
call->init_req(i, arg);
}
}
}
@@ -1689,41 +1685,44 @@
}
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)
+ call->method()->return_type()->basic_type() == T_VOID) {
ret = top();
- else {
+ } 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 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);
+ Node* ctl = control();
+ ret = ValueTypeNode::make(_gvn, ctl, merged_memory(), call, vk, TypeFunc::Parms+1, false);
+ set_control(ctl);
}
}
- // 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.
@@ -3395,11 +3394,11 @@
// - 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) {
+ 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,11 +3690,11 @@
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);
+ 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,11 +4561,11 @@
/*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);
+ con = ValueTypeNode::make(this, con);
}
return con;
}
return NULL;
}
< prev index next >