< prev index next >

src/hotspot/share/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,71 ---- #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) { + assert(_gvn.is_IterGVN()->delay_transform(), "Transformation must be delayed if IterGVN is used"); + // 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; --- 1388,1399 ---- } 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 */, --- 1530,1542 ---- 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); } } } --- 1625,1655 ---- 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. --- 1686,1729 ---- } 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; --- 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, ! 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()); --- 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)->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; } --- 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(this, con); } return con; } return NULL; }
< prev index next >