@@ -29,10 +29,11 @@ #include "compiler/compileLog.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/c2/barrierSetC2.hpp" #include "interpreter/interpreter.hpp" #include "memory/resourceArea.hpp" + #include "oops/trainingData.hpp" #include "opto/addnode.hpp" #include "opto/castnode.hpp" #include "opto/convertnode.hpp" #include "opto/graphKit.hpp" #include "opto/idealKit.hpp"
@@ -2147,10 +2148,20 @@ tty->print_cr("Uncommon trap %s at bci:%d", Deoptimization::format_trap_request(buf, sizeof(buf), trap_request), bci()); } + if (PreloadReduceTraps && Compile::current()->for_preload() && + (action != Deoptimization::Action_none)) { + ResourceMark rm; + ciMethod* cim = Compile::current()->method(); + log_debug(aot, codecache, deoptimization)("Uncommon trap in preload code: reason=%s action=%s method=%s::%s bci=%d, %s", + Deoptimization::trap_reason_name(reason), Deoptimization::trap_action_name(action), + cim->holder()->name()->as_klass_external_name(), cim->name()->as_klass_external_name(), + bci(), comment); + } + CompileLog* log = C->log(); if (log != nullptr) { int kid = (klass == nullptr)? -1: log->identify(klass); log->begin_elem("uncommon_trap bci='%d'", bci()); char buf[100];
@@ -2988,10 +2999,83 @@ } speculating = false; return false; } + void GraphKit::guard_klass_is_initialized(Node* klass) { + assert(C->do_clinit_barriers(), "should be called only for clinit barriers"); + int init_state_off = in_bytes(InstanceKlass::init_state_offset()); + Node* adr = basic_plus_adr(top(), klass, init_state_off); + Node* init_state = LoadNode::make(_gvn, nullptr, immutable_memory(), adr, + adr->bottom_type()->is_ptr(), TypeInt::BYTE, + T_BYTE, MemNode::unordered); + init_state = _gvn.transform(init_state); + + Node* initialized_state = makecon(TypeInt::make(InstanceKlass::fully_initialized)); + + Node* chk = _gvn.transform(new CmpINode(initialized_state, init_state)); + Node* tst = _gvn.transform(new BoolNode(chk, BoolTest::eq)); + + switch (ClassInitBarrierMode) { + case 1: { // uncommon trap on slow path + BuildCutout unless(this, tst, PROB_MAX); + // Do not deoptimize this nmethod. Go to Interpreter to initialize class. + uncommon_trap(Deoptimization::Reason_uninitialized, Deoptimization::Action_none); + break; + } + case 2: { // runtime call on slow path + if (StressClassInitBarriers) { + tst = makecon(TypeInt::ZERO); // always go through slow path + } + IfNode* iff = create_and_xform_if(control(), tst, PROB_MAX, COUNT_UNKNOWN); + // IfNode* iff = create_and_map_if(control(), tst, PROB_MAX, COUNT_UNKNOWN); + + RegionNode* r = new RegionNode(3); + r->init_req(1, _gvn.transform(new IfTrueNode(iff))); + + set_control(_gvn.transform(new IfFalseNode(iff))); + + if (!stopped()) { + kill_dead_locals(); + + Node* call = make_runtime_call(RC_NO_LEAF, + OptoRuntime::class_init_barrier_Type(), + OptoRuntime::class_init_barrier_Java(), + nullptr, TypePtr::BOTTOM, + klass); + // Deoptimization during class init barrier execution should trigger current bytecode reexecution. + call->jvms()->set_should_reexecute(true); + + // FIXME: deoptimize for now. deoptimize=false doesn't work with late inlining yet. + // Parse::create_entry_map() introduces a barrier which uses distinct JVM state (*before* call). + // Compilation fails when distinct exception states are combined. + make_slow_call_ex(call, env()->Throwable_klass(), /*separate_io_proj=*/true, /*deoptimize=*/true); + + Node* fast_io = call->in(TypeFunc::I_O); + Node* fast_mem = call->in(TypeFunc::Memory); + // These two phis are pre-filled with copies of of the fast IO and Memory + Node* io_phi = PhiNode::make(r, fast_io, Type::ABIO); + Node* mem_phi = PhiNode::make(r, fast_mem, Type::MEMORY, TypePtr::BOTTOM); + + r->init_req(2, control()); + io_phi->init_req(2, i_o()); + mem_phi->init_req(2, reset_memory()); + + set_all_memory(_gvn.transform(mem_phi)); + set_i_o(_gvn.transform(io_phi)); + } else { + r->init_req(2, top()); + } + set_control(_gvn.transform(r)); + break; + } + + default: fatal("unknown barrier mode: %d", ClassInitBarrierMode); + } + C->set_has_clinit_barriers(true); + } + void GraphKit::guard_klass_being_initialized(Node* klass) { int init_state_off = in_bytes(InstanceKlass::init_state_offset()); Node* adr = basic_plus_adr(top(), klass, init_state_off); Node* init_state = LoadNode::make(_gvn, nullptr, immutable_memory(), adr, adr->bottom_type()->is_ptr(), TypeInt::BYTE,
@@ -3026,20 +3110,29 @@ uncommon_trap(Deoptimization::Reason_uninitialized, Deoptimization::Action_none); } } void GraphKit::clinit_barrier(ciInstanceKlass* ik, ciMethod* context) { + if (C->do_clinit_barriers()) { + Node* klass = makecon(TypeKlassPtr::make(ik, Type::trust_interfaces)); + guard_klass_is_initialized(klass); + return; + } if (ik->is_being_initialized()) { if (C->needs_clinit_barrier(ik, context)) { - Node* klass = makecon(TypeKlassPtr::make(ik)); + Node* klass = makecon(TypeKlassPtr::make(ik, Type::trust_interfaces)); guard_klass_being_initialized(klass); guard_init_thread(klass); insert_mem_bar(Op_MemBarCPUOrder); } } else if (ik->is_initialized()) { return; // no barrier needed } else { + if (C->env()->task()->is_precompile()) { + ResourceMark rm; + log_debug(precompile)("Emitting uncommon trap (clinit barrier) in AOT code for %s", ik->name()->as_klass_external_name()); + } uncommon_trap(Deoptimization::Reason_uninitialized, Deoptimization::Action_reinterpret, nullptr); } }