< prev index next >

src/share/vm/opto/compile.cpp

Print this page

        

*** 71,88 **** --- 71,94 ---- # include AD_MD_HPP #elif defined TARGET_ARCH_MODEL_x86_32 # include "adfiles/ad_x86_32.hpp" #elif defined TARGET_ARCH_MODEL_x86_64 # include "adfiles/ad_x86_64.hpp" + #elif defined TARGET_ARCH_MODEL_aarch64 + # include "adfiles/ad_aarch64.hpp" #elif defined TARGET_ARCH_MODEL_sparc # include "adfiles/ad_sparc.hpp" #elif defined TARGET_ARCH_MODEL_zero # include "adfiles/ad_zero.hpp" #elif defined TARGET_ARCH_MODEL_ppc_64 # include "adfiles/ad_ppc_64.hpp" #endif + #if INCLUDE_ALL_GCS + #include "gc_implementation/shenandoah/shenandoahForwarding.hpp" + #include "gc_implementation/shenandoah/shenandoahSupport.hpp" + #endif // -------------------- Compile::mach_constant_base_node ----------------------- // Constant table base node singleton. MachConstantBaseNode* Compile::mach_constant_base_node() { if (_mach_constant_base_node == NULL) {
*** 402,411 **** --- 408,422 ---- } } if (n->outcnt() == 1 && n->has_special_unique_user()) { record_for_igvn(n->unique_out()); } + if (n->Opcode() == Op_AddP && CallLeafNode::has_only_g1_wb_pre_uses(n)) { + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + record_for_igvn(n->fast_out(i)); + } + } } // Remove useless macro and predicate opaq nodes for (int i = C->macro_count()-1; i >= 0; i--) { Node* n = C->macro_node(i); if (!useful.member(n)) {
*** 424,433 **** --- 435,450 ---- Node* n = C->expensive_node(i); if (!useful.member(n)) { remove_expensive_node(n); } } + for (int i = C->shenandoah_barriers_count()-1; i >= 0; i--) { + ShenandoahLoadReferenceBarrierNode* n = C->shenandoah_barrier(i); + if (!useful.member(n)) { + remove_shenandoah_barrier(n); + } + } // clean up the late inline lists remove_useless_late_inlines(&_string_late_inlines, useful); remove_useless_late_inlines(&_boxing_late_inlines, useful); remove_useless_late_inlines(&_late_inlines, useful); debug_only(verify_graph_edges(true/*check for no_dead_code*/);)
*** 767,777 **** // Normal case. init_tf(TypeFunc::make(method())); StartNode* s = new (this) StartNode(root(), tf()->domain()); initial_gvn()->set_type_bottom(s); init_start(s); ! if (method()->intrinsic_id() == vmIntrinsics::_Reference_get && UseG1GC) { // With java.lang.ref.reference.get() we must go through the // intrinsic when G1 is enabled - even when get() is the root // method of the compile - so that, if necessary, the value in // the referent field of the reference object gets recorded by // the pre-barrier code. --- 784,794 ---- // Normal case. init_tf(TypeFunc::make(method())); StartNode* s = new (this) StartNode(root(), tf()->domain()); initial_gvn()->set_type_bottom(s); init_start(s); ! if (method()->intrinsic_id() == vmIntrinsics::_Reference_get && (UseG1GC || UseShenandoahGC)) { // With java.lang.ref.reference.get() we must go through the // intrinsic when G1 is enabled - even when get() is the root // method of the compile - so that, if necessary, the value in // the referent field of the reference object gets recorded by // the pre-barrier code.
*** 1160,1169 **** --- 1177,1187 ---- _intrinsics = NULL; _macro_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); _predicate_opaqs = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); _expensive_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); _range_check_casts = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); + _shenandoah_barriers = new(comp_arena()) GrowableArray<ShenandoahLoadReferenceBarrierNode*>(comp_arena(), 8, 0, NULL); register_library_intrinsics(); } //---------------------------init_start---------------------------------------- // Install the StartNode on this compile object.
*** 2270,2288 **** --- 2288,2318 ---- // No more loop optimizations. Remove all range check dependent CastIINodes. C->remove_range_check_casts(igvn); igvn.optimize(); } + #ifdef ASSERT + if (UseShenandoahGC && ShenandoahVerifyOptoBarriers) { + ShenandoahBarrierC2Support::verify(C->root()); + } + #endif + { NOT_PRODUCT( TracePhase t2("macroExpand", &_t_macroExpand, TimeCompiler); ) PhaseMacroExpand mex(igvn); if (mex.expand_macro_nodes()) { assert(failing(), "must bail out w/ explicit message"); return; } } + #if INCLUDE_ALL_GCS + if (UseShenandoahGC) { + ShenandoahBarrierC2Support::expand(this, igvn); + } + #endif + } // (End scope of igvn; run destructor if necessary for asserts.) dump_inlining(); // A method with only infinite loops has no edges entering loops from root {
*** 2648,2657 **** --- 2678,2698 ---- // oop will be recorded in oop map if load crosses safepoint n->is_Load() && (n->as_Load()->bottom_type()->isa_oopptr() || LoadNode::is_immutable_value(n->in(MemNode::Address))), "raw memory operations should have control edge"); } + if (n->is_MemBar()) { + MemBarNode* mb = n->as_MemBar(); + if (mb->trailing_store() || mb->trailing_load_store()) { + assert(mb->leading_membar()->trailing_membar() == mb, "bad membar pair"); + Node* mem = mb->in(MemBarNode::Precedent); + assert((mb->trailing_store() && mem->is_Store() && mem->as_Store()->is_release()) || + (mb->trailing_load_store() && mem->is_LoadStore()), "missing mem op"); + } else if (mb->leading()) { + assert(mb->trailing_membar()->leading_membar() == mb, "bad membar pair"); + } + } #endif // Count FPU ops and common calls, implements item (3) switch( nop ) { // Count all float operations that may use FPU case Op_AddF:
*** 2702,2711 **** --- 2743,2761 ---- case Op_CallRuntime: case Op_CallLeaf: case Op_CallLeafNoFP: { assert( n->is_Call(), "" ); CallNode *call = n->as_Call(); + if (UseShenandoahGC && call->is_g1_wb_pre_call()) { + uint cnt = OptoRuntime::g1_wb_pre_Type()->domain()->cnt(); + if (call->req() > cnt) { + assert(call->req() == cnt+1, "only one extra input"); + Node* addp = call->in(cnt); + assert(!CallLeafNode::has_only_g1_wb_pre_uses(addp), "useless address computation?"); + call->del_req(cnt); + } + } // Count call sites where the FP mode bit would have to be flipped. // Do not count uncommon runtime calls: // uncommon_trap, _complete_monitor_locking, _complete_monitor_unlocking, // _new_Java, _new_typeArray, _new_objArray, _rethrow_Java, ... if( !call->is_CallStaticJava() || !call->as_CallStaticJava()->_name ) {
*** 2845,2857 **** } #endif break; } ! #ifdef _LP64 ! case Op_CastPP: ! if (n->in(1)->is_DecodeN() && Matcher::gen_narrow_oop_implicit_null_checks()) { Node* in1 = n->in(1); const Type* t = n->bottom_type(); Node* new_in1 = in1->clone(); new_in1->as_DecodeN()->set_type(t); --- 2895,2936 ---- } #endif break; } ! case Op_CastPP: { ! // Remove CastPP nodes to gain more freedom during scheduling but ! // keep the dependency they encode as control or precedence edges ! // (if control is set already) on memory operations. Some CastPP ! // nodes don't have a control (don't carry a dependency): skip ! // those. ! if (n->in(0) != NULL) { ! ResourceMark rm; ! Unique_Node_List wq; ! wq.push(n); ! for (uint next = 0; next < wq.size(); ++next) { ! Node *m = wq.at(next); ! for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) { ! Node* use = m->fast_out(i); ! if (use->is_Mem() || use->is_EncodeNarrowPtr() || use->Opcode() == Op_ShenandoahLoadReferenceBarrier) { ! use->ensure_control_or_add_prec(n->in(0)); ! } else if (use->in(0) == NULL) { ! switch(use->Opcode()) { ! case Op_AddP: ! case Op_DecodeN: ! case Op_DecodeNKlass: ! case Op_CheckCastPP: ! case Op_CastPP: ! wq.push(use); ! break; ! } ! } ! } ! } ! } ! const bool is_LP64 = LP64_ONLY(true) NOT_LP64(false); ! if (is_LP64 && n->in(1)->is_DecodeN() && Matcher::gen_narrow_oop_implicit_null_checks()) { Node* in1 = n->in(1); const Type* t = n->bottom_type(); Node* new_in1 = in1->clone(); new_in1->as_DecodeN()->set_type(t);
*** 2880,2892 **** n->subsume_by(new_in1, this); if (in1->outcnt() == 0) { in1->disconnect_inputs(NULL, this); } } break; ! case Op_CmpP: // Do this transformation here to preserve CmpPNode::sub() and // other TypePtr related Ideal optimizations (for example, ptr nullness). if (n->in(1)->is_DecodeNarrowPtr() || n->in(2)->is_DecodeNarrowPtr()) { Node* in1 = n->in(1); --- 2959,2977 ---- n->subsume_by(new_in1, this); if (in1->outcnt() == 0) { in1->disconnect_inputs(NULL, this); } + } else { + n->subsume_by(n->in(1), this); + if (n->outcnt() == 0) { + n->disconnect_inputs(NULL, this); + } } break; ! } ! #ifdef _LP64 case Op_CmpP: // Do this transformation here to preserve CmpPNode::sub() and // other TypePtr related Ideal optimizations (for example, ptr nullness). if (n->in(1)->is_DecodeNarrowPtr() || n->in(2)->is_DecodeNarrowPtr()) { Node* in1 = n->in(1);
*** 3148,3157 **** --- 3233,3245 ---- // confuses register allocation. if (n->req() > MemBarNode::Precedent) { n->set_req(MemBarNode::Precedent, top()); } break; + case Op_ShenandoahLoadReferenceBarrier: + assert(false, "should have been expanded already"); + break; default: assert( !n->is_Call(), "" ); assert( !n->is_Mem(), "" ); assert( nop != Op_ProfileBoolean, "should be eliminated during IGVN"); break;
*** 3514,3524 **** // Verify GC barriers consistency // Currently supported: // - G1 pre-barriers (see GraphKit::g1_write_barrier_pre()) void Compile::verify_barriers() { ! if (UseG1GC) { // Verify G1 pre-barriers const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()); ResourceArea *area = Thread::current()->resource_area(); Unique_Node_List visited(area); --- 3602,3612 ---- // Verify GC barriers consistency // Currently supported: // - G1 pre-barriers (see GraphKit::g1_write_barrier_pre()) void Compile::verify_barriers() { ! if (UseG1GC || UseShenandoahGC) { // Verify G1 pre-barriers const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_active()); ResourceArea *area = Thread::current()->resource_area(); Unique_Node_List visited(area);
*** 4045,4055 **** TypeNode* tn = n->as_Type(); const Type* t = tn->type(); const Type* t_no_spec = t->remove_speculative(); if (t_no_spec != t) { bool in_hash = igvn.hash_delete(n); ! assert(in_hash, "node should be in igvn hash table"); tn->set_type(t_no_spec); igvn.hash_insert(n); igvn._worklist.push(n); // give it a chance to go away modified++; } --- 4133,4143 ---- TypeNode* tn = n->as_Type(); const Type* t = tn->type(); const Type* t_no_spec = t->remove_speculative(); if (t_no_spec != t) { bool in_hash = igvn.hash_delete(n); ! assert(in_hash || n->hash() == Node::NO_HASH, "node should be in igvn hash table"); tn->set_type(t_no_spec); igvn.hash_insert(n); igvn._worklist.push(n); // give it a chance to go away modified++; }
*** 4140,4144 **** --- 4228,4253 ---- #define RANDOMIZED_DOMAIN_MASK ((1 << (RANDOMIZED_DOMAIN_POW + 1)) - 1) bool Compile::randomized_select(int count) { assert(count > 0, "only positive"); return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count); } + + void Compile::shenandoah_eliminate_g1_wb_pre(Node* call, PhaseIterGVN* igvn) { + assert(UseShenandoahGC && call->is_g1_wb_pre_call(), ""); + Node* c = call->as_Call()->proj_out(TypeFunc::Control); + c = c->unique_ctrl_out(); + assert(c->is_Region() && c->req() == 3, "where's the pre barrier control flow?"); + c = c->unique_ctrl_out(); + assert(c->is_Region() && c->req() == 3, "where's the pre barrier control flow?"); + Node* iff = c->in(1)->is_IfProj() ? c->in(1)->in(0) : c->in(2)->in(0); + assert(iff->is_If(), "expect test"); + if (!iff->is_shenandoah_marking_if(igvn)) { + c = c->unique_ctrl_out(); + assert(c->is_Region() && c->req() == 3, "where's the pre barrier control flow?"); + iff = c->in(1)->is_IfProj() ? c->in(1)->in(0) : c->in(2)->in(0); + assert(iff->is_shenandoah_marking_if(igvn), "expect marking test"); + } + Node* cmpx = iff->in(1)->in(1); + igvn->replace_node(cmpx, igvn->makecon(TypeInt::CC_EQ)); + igvn->rehash_node_delayed(call); + call->del_req(call->req()-1); + }
< prev index next >