IfNode* create_and_xform_if(Node* ctrl, Node* tst, float prob, float cnt) { IfNode* iff = new (C, 2) IfNode(ctrl, tst, prob, cnt);// New IfNode's _gvn.transform(iff); // Value may be known at parse-time // Place 'if' on worklist if it will be in graph if (!tst->is_Con()) record_for_igvn(iff); // Range-check and Null-check removal is later return iff; }
void Parse::emit_guard_for_new(ciInstanceKlass* klass) { // Emit guarded new // if (klass->_init_thread != current_thread || // klass->_init_state != being_initialized) // uncommon_trap Node* cur_thread = _gvn.transform( new (C, 1) ThreadLocalNode() ); Node* merge = new (C, 3) RegionNode(3); _gvn.set_type(merge, Type::CONTROL); Node* kls = makecon(TypeKlassPtr::make(klass)); Node* init_thread_offset = _gvn.MakeConX(instanceKlass::init_thread_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()); Node* adr_node = basic_plus_adr(kls, kls, init_thread_offset); Node* init_thread = make_load(NULL, adr_node, TypeRawPtr::BOTTOM, T_ADDRESS); Node *tst = Bool( CmpP( init_thread, cur_thread), BoolTest::eq); IfNode* iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN); set_control(IfTrue(iff)); merge->set_req(1, IfFalse(iff)); Node* init_state_offset = _gvn.MakeConX(instanceKlass::init_state_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()); adr_node = basic_plus_adr(kls, kls, init_state_offset); Node* init_state = make_load(NULL, adr_node, TypeInt::INT, T_INT); Node* being_init = _gvn.intcon(instanceKlass::being_initialized); tst = Bool( CmpI( init_state, being_init), BoolTest::eq); iff = create_and_map_if(control(), tst, PROB_ALWAYS, COUNT_UNKNOWN); set_control(IfTrue(iff)); merge->set_req(2, IfFalse(iff)); PreserveJVMState pjvms(this); record_for_igvn(merge); set_control(merge); uncommon_trap(Deoptimization::Reason_uninitialized, Deoptimization::Action_reinterpret, klass); }
//---------------------------catch_call_exceptions----------------------------- // Put a Catch and CatchProj nodes behind a just-created call. // Send their caught exceptions to the proper handler. // This may be used after a call to the rethrow VM stub, // when it is needed to process unloaded exception classes. void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) { // Exceptions are delivered through this channel: Node* i_o = this->i_o(); // Add a CatchNode. GrowableArray<int>* bcis = new (C->node_arena()) GrowableArray<int>(C->node_arena(), 8, 0, -1); GrowableArray<const Type*>* extypes = new (C->node_arena()) GrowableArray<const Type*>(C->node_arena(), 8, 0, NULL); GrowableArray<int>* saw_unloaded = new (C->node_arena()) GrowableArray<int>(C->node_arena(), 8, 0, 0); for (; !handlers.is_done(); handlers.next()) { ciExceptionHandler* h = handlers.handler(); int h_bci = h->handler_bci(); ciInstanceKlass* h_klass = h->is_catch_all() ? env()->Throwable_klass() : h->catch_klass(); const TypePtr* h_extype = TypeOopPtr::make_from_klass_unique(h_klass)->cast_away_null(); // Ignore exceptions with no implementors. These cannot be thrown // (without class loading anyways, which will deopt this code). if( h_extype->empty() ) continue; // Do not introduce unloaded exception types into the graph: if (!h_klass->is_loaded()) { if (saw_unloaded->contains(h_bci)) { /* We've already seen an unloaded exception with h_bci, so don't duplicate. Duplication will cause the CatchNode to be unnecessarily large. See 4713716. */ continue; } else { saw_unloaded->append(h_bci); } } // Note: It's OK if the BCIs repeat themselves. bcis->append(h_bci); extypes->append(h_extype); } int len = bcis->length(); CatchNode *cn = new (C, 2) CatchNode(control(), i_o, len+1); Node *catch_ = _gvn.transform(cn); // now branch with the exception state to each of the (potential) // handlers for(int i=0; i < len; i++) { // Setup JVM state to enter the handler. PreserveJVMState pjvms(this); // Locals are just copied from before the call. // Get control from the CatchNode. int handler_bci = bcis->at(i); Node* ctrl = _gvn.transform( new (C, 1) CatchProjNode(catch_, i+1,handler_bci)); // This handler cannot happen? if (ctrl == top()) continue; set_control(ctrl); // Create exception oop const TypeInstPtr* extype = extypes->at(i)->is_instptr(); Node *thread = _gvn.transform( new (C, 1) ThreadLocalNode() ); Node*ex_adr=basic_plus_adr(top(),thread,in_bytes(JavaThread::pending_exception_offset())); int pending_ex_alias_idx = C->get_alias_index(ex_adr->bottom_type()->is_ptr()); Node *ex_oop = make_load( NULL, ex_adr, extype, T_OBJECT, pending_ex_alias_idx ); Node *ex_st = store_to_memory( ctrl, ex_adr, null(), T_OBJECT, pending_ex_alias_idx ); record_for_igvn(ex_st); // Handle unloaded exception classes. if (saw_unloaded->contains(handler_bci)) { // An unloaded exception type is coming here. Do an uncommon trap. // We do not expect the same handler bci to take both cold unloaded // and hot loaded exceptions. But, watch for it. if(PrintOpto&&extype->is_loaded()){ C2OUT->print_cr("Warning: Handler @%d takes mixed loaded/unloaded exceptions in ",handler_bci); method()->print_name(C2OUT);C2OUT->cr(); } // Emit an uncommon trap instead of processing the block. set_bci(handler_bci); push_ex_oop(ex_oop); uncommon_trap(Deoptimization::Reason_unloaded,extype->klass(),"not loaded exception",false); set_bci(iter().cur_bci()); // put it back continue; } // go to the exception handler if (handler_bci < 0) { // merge with corresponding rethrow node throw_to_exit(make_exception_state(ex_oop)); } else { // Else jump to corresponding handle push_ex_oop(ex_oop); // Clear stack and push just the oop. merge_exception(handler_bci); } } // The first CatchProj is for the normal return. // (Note: If this is a call to rethrow_Java, this node goes dead.) set_control(_gvn.transform( new (C, 1) CatchProjNode(catch_, CatchProjNode::fall_through_index, CatchProjNode::no_handler_bci))); }