Path: blob/master/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp
40976 views
/*1* Copyright (c) 2015, 2021, Red Hat, Inc. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"2526#include "classfile/javaClasses.hpp"27#include "gc/shenandoah/c2/shenandoahSupport.hpp"28#include "gc/shenandoah/c2/shenandoahBarrierSetC2.hpp"29#include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"30#include "gc/shenandoah/shenandoahForwarding.hpp"31#include "gc/shenandoah/shenandoahHeap.hpp"32#include "gc/shenandoah/shenandoahHeapRegion.hpp"33#include "gc/shenandoah/shenandoahRuntime.hpp"34#include "gc/shenandoah/shenandoahThreadLocalData.hpp"35#include "opto/arraycopynode.hpp"36#include "opto/block.hpp"37#include "opto/callnode.hpp"38#include "opto/castnode.hpp"39#include "opto/movenode.hpp"40#include "opto/phaseX.hpp"41#include "opto/rootnode.hpp"42#include "opto/runtime.hpp"43#include "opto/subnode.hpp"4445bool ShenandoahBarrierC2Support::expand(Compile* C, PhaseIterGVN& igvn) {46ShenandoahBarrierSetC2State* state = ShenandoahBarrierSetC2::bsc2()->state();47if ((state->iu_barriers_count() +48state->load_reference_barriers_count()) > 0) {49assert(C->post_loop_opts_phase(), "no loop opts allowed");50C->reset_post_loop_opts_phase(); // ... but we know what we are doing51bool attempt_more_loopopts = ShenandoahLoopOptsAfterExpansion;52C->clear_major_progress();53PhaseIdealLoop::optimize(igvn, LoopOptsShenandoahExpand);54if (C->failing()) return false;55PhaseIdealLoop::verify(igvn);56DEBUG_ONLY(verify_raw_mem(C->root());)57if (attempt_more_loopopts) {58C->set_major_progress();59if (!C->optimize_loops(igvn, LoopOptsShenandoahPostExpand)) {60return false;61}62C->clear_major_progress();6364C->process_for_post_loop_opts_igvn(igvn);65}66C->set_post_loop_opts_phase(); // now for real!67}68return true;69}7071bool ShenandoahBarrierC2Support::is_gc_state_test(Node* iff, int mask) {72if (!UseShenandoahGC) {73return false;74}75assert(iff->is_If(), "bad input");76if (iff->Opcode() != Op_If) {77return false;78}79Node* bol = iff->in(1);80if (!bol->is_Bool() || bol->as_Bool()->_test._test != BoolTest::ne) {81return false;82}83Node* cmp = bol->in(1);84if (cmp->Opcode() != Op_CmpI) {85return false;86}87Node* in1 = cmp->in(1);88Node* in2 = cmp->in(2);89if (in2->find_int_con(-1) != 0) {90return false;91}92if (in1->Opcode() != Op_AndI) {93return false;94}95in2 = in1->in(2);96if (in2->find_int_con(-1) != mask) {97return false;98}99in1 = in1->in(1);100101return is_gc_state_load(in1);102}103104bool ShenandoahBarrierC2Support::is_heap_stable_test(Node* iff) {105return is_gc_state_test(iff, ShenandoahHeap::HAS_FORWARDED);106}107108bool ShenandoahBarrierC2Support::is_gc_state_load(Node *n) {109if (!UseShenandoahGC) {110return false;111}112if (n->Opcode() != Op_LoadB && n->Opcode() != Op_LoadUB) {113return false;114}115Node* addp = n->in(MemNode::Address);116if (!addp->is_AddP()) {117return false;118}119Node* base = addp->in(AddPNode::Address);120Node* off = addp->in(AddPNode::Offset);121if (base->Opcode() != Op_ThreadLocal) {122return false;123}124if (off->find_intptr_t_con(-1) != in_bytes(ShenandoahThreadLocalData::gc_state_offset())) {125return false;126}127return true;128}129130bool ShenandoahBarrierC2Support::has_safepoint_between(Node* start, Node* stop, PhaseIdealLoop *phase) {131assert(phase->is_dominator(stop, start), "bad inputs");132ResourceMark rm;133Unique_Node_List wq;134wq.push(start);135for (uint next = 0; next < wq.size(); next++) {136Node *m = wq.at(next);137if (m == stop) {138continue;139}140if (m->is_SafePoint() && !m->is_CallLeaf()) {141return true;142}143if (m->is_Region()) {144for (uint i = 1; i < m->req(); i++) {145wq.push(m->in(i));146}147} else {148wq.push(m->in(0));149}150}151return false;152}153154#ifdef ASSERT155bool ShenandoahBarrierC2Support::verify_helper(Node* in, Node_Stack& phis, VectorSet& visited, verify_type t, bool trace, Unique_Node_List& barriers_used) {156assert(phis.size() == 0, "");157158while (true) {159if (in->bottom_type() == TypePtr::NULL_PTR) {160if (trace) {tty->print_cr("NULL");}161} else if (!in->bottom_type()->make_ptr()->make_oopptr()) {162if (trace) {tty->print_cr("Non oop");}163} else {164if (in->is_ConstraintCast()) {165in = in->in(1);166continue;167} else if (in->is_AddP()) {168assert(!in->in(AddPNode::Address)->is_top(), "no raw memory access");169in = in->in(AddPNode::Address);170continue;171} else if (in->is_Con()) {172if (trace) {173tty->print("Found constant");174in->dump();175}176} else if (in->Opcode() == Op_Parm) {177if (trace) {178tty->print("Found argument");179}180} else if (in->Opcode() == Op_CreateEx) {181if (trace) {182tty->print("Found create-exception");183}184} else if (in->Opcode() == Op_LoadP && in->adr_type() == TypeRawPtr::BOTTOM) {185if (trace) {186tty->print("Found raw LoadP (OSR argument?)");187}188} else if (in->Opcode() == Op_ShenandoahLoadReferenceBarrier) {189if (t == ShenandoahOopStore) {190uint i = 0;191for (; i < phis.size(); i++) {192Node* n = phis.node_at(i);193if (n->Opcode() == Op_ShenandoahIUBarrier) {194break;195}196}197if (i == phis.size()) {198return false;199}200}201barriers_used.push(in);202if (trace) {tty->print("Found barrier"); in->dump();}203} else if (in->Opcode() == Op_ShenandoahIUBarrier) {204if (t != ShenandoahOopStore) {205in = in->in(1);206continue;207}208if (trace) {tty->print("Found enqueue barrier"); in->dump();}209phis.push(in, in->req());210in = in->in(1);211continue;212} else if (in->is_Proj() && in->in(0)->is_Allocate()) {213if (trace) {214tty->print("Found alloc");215in->in(0)->dump();216}217} else if (in->is_Proj() && (in->in(0)->Opcode() == Op_CallStaticJava || in->in(0)->Opcode() == Op_CallDynamicJava)) {218if (trace) {219tty->print("Found Java call");220}221} else if (in->is_Phi()) {222if (!visited.test_set(in->_idx)) {223if (trace) {tty->print("Pushed phi:"); in->dump();}224phis.push(in, 2);225in = in->in(1);226continue;227}228if (trace) {tty->print("Already seen phi:"); in->dump();}229} else if (in->Opcode() == Op_CMoveP || in->Opcode() == Op_CMoveN) {230if (!visited.test_set(in->_idx)) {231if (trace) {tty->print("Pushed cmovep:"); in->dump();}232phis.push(in, CMoveNode::IfTrue);233in = in->in(CMoveNode::IfFalse);234continue;235}236if (trace) {tty->print("Already seen cmovep:"); in->dump();}237} else if (in->Opcode() == Op_EncodeP || in->Opcode() == Op_DecodeN) {238in = in->in(1);239continue;240} else {241return false;242}243}244bool cont = false;245while (phis.is_nonempty()) {246uint idx = phis.index();247Node* phi = phis.node();248if (idx >= phi->req()) {249if (trace) {tty->print("Popped phi:"); phi->dump();}250phis.pop();251continue;252}253if (trace) {tty->print("Next entry(%d) for phi:", idx); phi->dump();}254in = phi->in(idx);255phis.set_index(idx+1);256cont = true;257break;258}259if (!cont) {260break;261}262}263return true;264}265266void ShenandoahBarrierC2Support::report_verify_failure(const char* msg, Node* n1, Node* n2) {267if (n1 != NULL) {268n1->dump(+10);269}270if (n2 != NULL) {271n2->dump(+10);272}273fatal("%s", msg);274}275276void ShenandoahBarrierC2Support::verify(RootNode* root) {277ResourceMark rm;278Unique_Node_List wq;279GrowableArray<Node*> barriers;280Unique_Node_List barriers_used;281Node_Stack phis(0);282VectorSet visited;283const bool trace = false;284const bool verify_no_useless_barrier = false;285286wq.push(root);287for (uint next = 0; next < wq.size(); next++) {288Node *n = wq.at(next);289if (n->is_Load()) {290const bool trace = false;291if (trace) {tty->print("Verifying"); n->dump();}292if (n->Opcode() == Op_LoadRange || n->Opcode() == Op_LoadKlass || n->Opcode() == Op_LoadNKlass) {293if (trace) {tty->print_cr("Load range/klass");}294} else {295const TypePtr* adr_type = n->as_Load()->adr_type();296297if (adr_type->isa_oopptr() && adr_type->is_oopptr()->offset() == oopDesc::mark_offset_in_bytes()) {298if (trace) {tty->print_cr("Mark load");}299} else if (adr_type->isa_instptr() &&300adr_type->is_instptr()->klass()->is_subtype_of(Compile::current()->env()->Reference_klass()) &&301adr_type->is_instptr()->offset() == java_lang_ref_Reference::referent_offset()) {302if (trace) {tty->print_cr("Reference.get()");}303} else if (!verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahLoad, trace, barriers_used)) {304report_verify_failure("Shenandoah verification: Load should have barriers", n);305}306}307} else if (n->is_Store()) {308const bool trace = false;309310if (trace) {tty->print("Verifying"); n->dump();}311if (n->in(MemNode::ValueIn)->bottom_type()->make_oopptr()) {312Node* adr = n->in(MemNode::Address);313bool verify = true;314315if (adr->is_AddP() && adr->in(AddPNode::Base)->is_top()) {316adr = adr->in(AddPNode::Address);317if (adr->is_AddP()) {318assert(adr->in(AddPNode::Base)->is_top(), "");319adr = adr->in(AddPNode::Address);320if (adr->Opcode() == Op_LoadP &&321adr->in(MemNode::Address)->in(AddPNode::Base)->is_top() &&322adr->in(MemNode::Address)->in(AddPNode::Address)->Opcode() == Op_ThreadLocal &&323adr->in(MemNode::Address)->in(AddPNode::Offset)->find_intptr_t_con(-1) == in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset())) {324if (trace) {tty->print_cr("SATB prebarrier");}325verify = false;326}327}328}329330if (verify && !verify_helper(n->in(MemNode::ValueIn), phis, visited, ShenandoahIUBarrier ? ShenandoahOopStore : ShenandoahValue, trace, barriers_used)) {331report_verify_failure("Shenandoah verification: Store should have barriers", n);332}333}334if (!verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahStore, trace, barriers_used)) {335report_verify_failure("Shenandoah verification: Store (address) should have barriers", n);336}337} else if (n->Opcode() == Op_CmpP) {338const bool trace = false;339340Node* in1 = n->in(1);341Node* in2 = n->in(2);342if (in1->bottom_type()->isa_oopptr()) {343if (trace) {tty->print("Verifying"); n->dump();}344345bool mark_inputs = false;346if (in1->bottom_type() == TypePtr::NULL_PTR || in2->bottom_type() == TypePtr::NULL_PTR ||347(in1->is_Con() || in2->is_Con())) {348if (trace) {tty->print_cr("Comparison against a constant");}349mark_inputs = true;350} else if ((in1->is_CheckCastPP() && in1->in(1)->is_Proj() && in1->in(1)->in(0)->is_Allocate()) ||351(in2->is_CheckCastPP() && in2->in(1)->is_Proj() && in2->in(1)->in(0)->is_Allocate())) {352if (trace) {tty->print_cr("Comparison with newly alloc'ed object");}353mark_inputs = true;354} else {355assert(in2->bottom_type()->isa_oopptr(), "");356357if (!verify_helper(in1, phis, visited, ShenandoahStore, trace, barriers_used) ||358!verify_helper(in2, phis, visited, ShenandoahStore, trace, barriers_used)) {359report_verify_failure("Shenandoah verification: Cmp should have barriers", n);360}361}362if (verify_no_useless_barrier &&363mark_inputs &&364(!verify_helper(in1, phis, visited, ShenandoahValue, trace, barriers_used) ||365!verify_helper(in2, phis, visited, ShenandoahValue, trace, barriers_used))) {366phis.clear();367visited.reset();368}369}370} else if (n->is_LoadStore()) {371if (n->in(MemNode::ValueIn)->bottom_type()->make_ptr() &&372!verify_helper(n->in(MemNode::ValueIn), phis, visited, ShenandoahIUBarrier ? ShenandoahOopStore : ShenandoahValue, trace, barriers_used)) {373report_verify_failure("Shenandoah verification: LoadStore (value) should have barriers", n);374}375376if (n->in(MemNode::Address)->bottom_type()->make_oopptr() && !verify_helper(n->in(MemNode::Address), phis, visited, ShenandoahStore, trace, barriers_used)) {377report_verify_failure("Shenandoah verification: LoadStore (address) should have barriers", n);378}379} else if (n->Opcode() == Op_CallLeafNoFP || n->Opcode() == Op_CallLeaf) {380CallNode* call = n->as_Call();381382static struct {383const char* name;384struct {385int pos;386verify_type t;387} args[6];388} calls[] = {389"aescrypt_encryptBlock",390{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad },391{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },392"aescrypt_decryptBlock",393{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad },394{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },395"multiplyToLen",396{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+2, ShenandoahLoad }, { TypeFunc::Parms+4, ShenandoahStore },397{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },398"squareToLen",399{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+2, ShenandoahLoad }, { -1, ShenandoahNone},400{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },401"montgomery_multiply",402{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahLoad }, { TypeFunc::Parms+2, ShenandoahLoad },403{ TypeFunc::Parms+6, ShenandoahStore }, { -1, ShenandoahNone}, { -1, ShenandoahNone} },404"montgomery_square",405{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahLoad }, { TypeFunc::Parms+5, ShenandoahStore },406{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },407"mulAdd",408{ { TypeFunc::Parms, ShenandoahStore }, { TypeFunc::Parms+1, ShenandoahLoad }, { -1, ShenandoahNone},409{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },410"vectorizedMismatch",411{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahLoad }, { -1, ShenandoahNone},412{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },413"updateBytesCRC32",414{ { TypeFunc::Parms+1, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone},415{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },416"updateBytesAdler32",417{ { TypeFunc::Parms+1, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone},418{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },419"updateBytesCRC32C",420{ { TypeFunc::Parms+1, ShenandoahLoad }, { TypeFunc::Parms+3, ShenandoahLoad}, { -1, ShenandoahNone},421{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },422"counterMode_AESCrypt",423{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad },424{ TypeFunc::Parms+3, ShenandoahStore }, { TypeFunc::Parms+5, ShenandoahStore }, { TypeFunc::Parms+6, ShenandoahStore } },425"cipherBlockChaining_encryptAESCrypt",426{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad },427{ TypeFunc::Parms+3, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone} },428"cipherBlockChaining_decryptAESCrypt",429{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { TypeFunc::Parms+2, ShenandoahLoad },430{ TypeFunc::Parms+3, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone} },431"shenandoah_clone_barrier",432{ { TypeFunc::Parms, ShenandoahLoad }, { -1, ShenandoahNone}, { -1, ShenandoahNone},433{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },434"ghash_processBlocks",435{ { TypeFunc::Parms, ShenandoahStore }, { TypeFunc::Parms+1, ShenandoahLoad }, { TypeFunc::Parms+2, ShenandoahLoad },436{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },437"sha1_implCompress",438{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone },439{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },440"sha256_implCompress",441{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone },442{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },443"sha512_implCompress",444{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone },445{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },446"sha1_implCompressMB",447{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone },448{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },449"sha256_implCompressMB",450{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone },451{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },452"sha512_implCompressMB",453{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+1, ShenandoahStore }, { -1, ShenandoahNone },454{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },455"encodeBlock",456{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+3, ShenandoahStore }, { -1, ShenandoahNone },457{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },458"decodeBlock",459{ { TypeFunc::Parms, ShenandoahLoad }, { TypeFunc::Parms+3, ShenandoahStore }, { -1, ShenandoahNone },460{ -1, ShenandoahNone}, { -1, ShenandoahNone}, { -1, ShenandoahNone} },461};462463if (call->is_call_to_arraycopystub()) {464Node* dest = NULL;465const TypeTuple* args = n->as_Call()->_tf->domain();466for (uint i = TypeFunc::Parms, j = 0; i < args->cnt(); i++) {467if (args->field_at(i)->isa_ptr()) {468j++;469if (j == 2) {470dest = n->in(i);471break;472}473}474}475if (!verify_helper(n->in(TypeFunc::Parms), phis, visited, ShenandoahLoad, trace, barriers_used) ||476!verify_helper(dest, phis, visited, ShenandoahStore, trace, barriers_used)) {477report_verify_failure("Shenandoah verification: ArrayCopy should have barriers", n);478}479} else if (strlen(call->_name) > 5 &&480!strcmp(call->_name + strlen(call->_name) - 5, "_fill")) {481if (!verify_helper(n->in(TypeFunc::Parms), phis, visited, ShenandoahStore, trace, barriers_used)) {482report_verify_failure("Shenandoah verification: _fill should have barriers", n);483}484} else if (!strcmp(call->_name, "shenandoah_wb_pre")) {485// skip486} else {487const int calls_len = sizeof(calls) / sizeof(calls[0]);488int i = 0;489for (; i < calls_len; i++) {490if (!strcmp(calls[i].name, call->_name)) {491break;492}493}494if (i != calls_len) {495const uint args_len = sizeof(calls[0].args) / sizeof(calls[0].args[0]);496for (uint j = 0; j < args_len; j++) {497int pos = calls[i].args[j].pos;498if (pos == -1) {499break;500}501if (!verify_helper(call->in(pos), phis, visited, calls[i].args[j].t, trace, barriers_used)) {502report_verify_failure("Shenandoah verification: intrinsic calls should have barriers", n);503}504}505for (uint j = TypeFunc::Parms; j < call->req(); j++) {506if (call->in(j)->bottom_type()->make_ptr() &&507call->in(j)->bottom_type()->make_ptr()->isa_oopptr()) {508uint k = 0;509for (; k < args_len && calls[i].args[k].pos != (int)j; k++);510if (k == args_len) {511fatal("arg %d for call %s not covered", j, call->_name);512}513}514}515} else {516for (uint j = TypeFunc::Parms; j < call->req(); j++) {517if (call->in(j)->bottom_type()->make_ptr() &&518call->in(j)->bottom_type()->make_ptr()->isa_oopptr()) {519fatal("%s not covered", call->_name);520}521}522}523}524} else if (n->Opcode() == Op_ShenandoahIUBarrier || n->Opcode() == Op_ShenandoahLoadReferenceBarrier) {525// skip526} else if (n->is_AddP()527|| n->is_Phi()528|| n->is_ConstraintCast()529|| n->Opcode() == Op_Return530|| n->Opcode() == Op_CMoveP531|| n->Opcode() == Op_CMoveN532|| n->Opcode() == Op_Rethrow533|| n->is_MemBar()534|| n->Opcode() == Op_Conv2B535|| n->Opcode() == Op_SafePoint536|| n->is_CallJava()537|| n->Opcode() == Op_Unlock538|| n->Opcode() == Op_EncodeP539|| n->Opcode() == Op_DecodeN) {540// nothing to do541} else {542static struct {543int opcode;544struct {545int pos;546verify_type t;547} inputs[2];548} others[] = {549Op_FastLock,550{ { 1, ShenandoahLoad }, { -1, ShenandoahNone} },551Op_Lock,552{ { TypeFunc::Parms, ShenandoahLoad }, { -1, ShenandoahNone} },553Op_ArrayCopy,554{ { ArrayCopyNode::Src, ShenandoahLoad }, { ArrayCopyNode::Dest, ShenandoahStore } },555Op_StrCompressedCopy,556{ { 2, ShenandoahLoad }, { 3, ShenandoahStore } },557Op_StrInflatedCopy,558{ { 2, ShenandoahLoad }, { 3, ShenandoahStore } },559Op_AryEq,560{ { 2, ShenandoahLoad }, { 3, ShenandoahLoad } },561Op_StrIndexOf,562{ { 2, ShenandoahLoad }, { 4, ShenandoahLoad } },563Op_StrComp,564{ { 2, ShenandoahLoad }, { 4, ShenandoahLoad } },565Op_StrEquals,566{ { 2, ShenandoahLoad }, { 3, ShenandoahLoad } },567Op_EncodeISOArray,568{ { 2, ShenandoahLoad }, { 3, ShenandoahStore } },569Op_HasNegatives,570{ { 2, ShenandoahLoad }, { -1, ShenandoahNone} },571Op_CastP2X,572{ { 1, ShenandoahLoad }, { -1, ShenandoahNone} },573Op_StrIndexOfChar,574{ { 2, ShenandoahLoad }, { -1, ShenandoahNone } },575};576577const int others_len = sizeof(others) / sizeof(others[0]);578int i = 0;579for (; i < others_len; i++) {580if (others[i].opcode == n->Opcode()) {581break;582}583}584uint stop = n->is_Call() ? n->as_Call()->tf()->domain()->cnt() : n->req();585if (i != others_len) {586const uint inputs_len = sizeof(others[0].inputs) / sizeof(others[0].inputs[0]);587for (uint j = 0; j < inputs_len; j++) {588int pos = others[i].inputs[j].pos;589if (pos == -1) {590break;591}592if (!verify_helper(n->in(pos), phis, visited, others[i].inputs[j].t, trace, barriers_used)) {593report_verify_failure("Shenandoah verification: intrinsic calls should have barriers", n);594}595}596for (uint j = 1; j < stop; j++) {597if (n->in(j) != NULL && n->in(j)->bottom_type()->make_ptr() &&598n->in(j)->bottom_type()->make_ptr()->make_oopptr()) {599uint k = 0;600for (; k < inputs_len && others[i].inputs[k].pos != (int)j; k++);601if (k == inputs_len) {602fatal("arg %d for node %s not covered", j, n->Name());603}604}605}606} else {607for (uint j = 1; j < stop; j++) {608if (n->in(j) != NULL && n->in(j)->bottom_type()->make_ptr() &&609n->in(j)->bottom_type()->make_ptr()->make_oopptr()) {610fatal("%s not covered", n->Name());611}612}613}614}615616if (n->is_SafePoint()) {617SafePointNode* sfpt = n->as_SafePoint();618if (verify_no_useless_barrier && sfpt->jvms() != NULL) {619for (uint i = sfpt->jvms()->scloff(); i < sfpt->jvms()->endoff(); i++) {620if (!verify_helper(sfpt->in(i), phis, visited, ShenandoahLoad, trace, barriers_used)) {621phis.clear();622visited.reset();623}624}625}626}627}628629if (verify_no_useless_barrier) {630for (int i = 0; i < barriers.length(); i++) {631Node* n = barriers.at(i);632if (!barriers_used.member(n)) {633tty->print("XXX useless barrier"); n->dump(-2);634ShouldNotReachHere();635}636}637}638}639#endif640641bool ShenandoahBarrierC2Support::is_dominator_same_ctrl(Node* c, Node* d, Node* n, PhaseIdealLoop* phase) {642// That both nodes have the same control is not sufficient to prove643// domination, verify that there's no path from d to n644ResourceMark rm;645Unique_Node_List wq;646wq.push(d);647for (uint next = 0; next < wq.size(); next++) {648Node *m = wq.at(next);649if (m == n) {650return false;651}652if (m->is_Phi() && m->in(0)->is_Loop()) {653assert(phase->ctrl_or_self(m->in(LoopNode::EntryControl)) != c, "following loop entry should lead to new control");654} else {655if (m->is_Store() || m->is_LoadStore()) {656// Take anti-dependencies into account657Node* mem = m->in(MemNode::Memory);658for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) {659Node* u = mem->fast_out(i);660if (u->is_Load() && phase->C->can_alias(m->adr_type(), phase->C->get_alias_index(u->adr_type())) &&661phase->ctrl_or_self(u) == c) {662wq.push(u);663}664}665}666for (uint i = 0; i < m->req(); i++) {667if (m->in(i) != NULL && phase->ctrl_or_self(m->in(i)) == c) {668wq.push(m->in(i));669}670}671}672}673return true;674}675676bool ShenandoahBarrierC2Support::is_dominator(Node* d_c, Node* n_c, Node* d, Node* n, PhaseIdealLoop* phase) {677if (d_c != n_c) {678return phase->is_dominator(d_c, n_c);679}680return is_dominator_same_ctrl(d_c, d, n, phase);681}682683Node* next_mem(Node* mem, int alias) {684Node* res = NULL;685if (mem->is_Proj()) {686res = mem->in(0);687} else if (mem->is_SafePoint() || mem->is_MemBar()) {688res = mem->in(TypeFunc::Memory);689} else if (mem->is_Phi()) {690res = mem->in(1);691} else if (mem->is_MergeMem()) {692res = mem->as_MergeMem()->memory_at(alias);693} else if (mem->is_Store() || mem->is_LoadStore() || mem->is_ClearArray()) {694assert(alias == Compile::AliasIdxRaw, "following raw memory can't lead to a barrier");695res = mem->in(MemNode::Memory);696} else {697#ifdef ASSERT698mem->dump();699#endif700ShouldNotReachHere();701}702return res;703}704705Node* ShenandoahBarrierC2Support::no_branches(Node* c, Node* dom, bool allow_one_proj, PhaseIdealLoop* phase) {706Node* iffproj = NULL;707while (c != dom) {708Node* next = phase->idom(c);709assert(next->unique_ctrl_out() == c || c->is_Proj() || c->is_Region(), "multiple control flow out but no proj or region?");710if (c->is_Region()) {711ResourceMark rm;712Unique_Node_List wq;713wq.push(c);714for (uint i = 0; i < wq.size(); i++) {715Node *n = wq.at(i);716if (n == next) {717continue;718}719if (n->is_Region()) {720for (uint j = 1; j < n->req(); j++) {721wq.push(n->in(j));722}723} else {724wq.push(n->in(0));725}726}727for (uint i = 0; i < wq.size(); i++) {728Node *n = wq.at(i);729assert(n->is_CFG(), "");730if (n->is_Multi()) {731for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) {732Node* u = n->fast_out(j);733if (u->is_CFG()) {734if (!wq.member(u) && !u->as_Proj()->is_uncommon_trap_proj(Deoptimization::Reason_none)) {735return NodeSentinel;736}737}738}739}740}741} else if (c->is_Proj()) {742if (c->is_IfProj()) {743if (c->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) != NULL) {744// continue;745} else {746if (!allow_one_proj) {747return NodeSentinel;748}749if (iffproj == NULL) {750iffproj = c;751} else {752return NodeSentinel;753}754}755} else if (c->Opcode() == Op_JumpProj) {756return NodeSentinel; // unsupported757} else if (c->Opcode() == Op_CatchProj) {758return NodeSentinel; // unsupported759} else if (c->Opcode() == Op_CProj && next->Opcode() == Op_NeverBranch) {760return NodeSentinel; // unsupported761} else {762assert(next->unique_ctrl_out() == c, "unsupported branch pattern");763}764}765c = next;766}767return iffproj;768}769770Node* ShenandoahBarrierC2Support::dom_mem(Node* mem, Node* ctrl, int alias, Node*& mem_ctrl, PhaseIdealLoop* phase) {771ResourceMark rm;772VectorSet wq;773wq.set(mem->_idx);774mem_ctrl = phase->ctrl_or_self(mem);775while (!phase->is_dominator(mem_ctrl, ctrl) || mem_ctrl == ctrl) {776mem = next_mem(mem, alias);777if (wq.test_set(mem->_idx)) {778return NULL;779}780mem_ctrl = phase->ctrl_or_self(mem);781}782if (mem->is_MergeMem()) {783mem = mem->as_MergeMem()->memory_at(alias);784mem_ctrl = phase->ctrl_or_self(mem);785}786return mem;787}788789Node* ShenandoahBarrierC2Support::find_bottom_mem(Node* ctrl, PhaseIdealLoop* phase) {790Node* mem = NULL;791Node* c = ctrl;792do {793if (c->is_Region()) {794for (DUIterator_Fast imax, i = c->fast_outs(imax); i < imax && mem == NULL; i++) {795Node* u = c->fast_out(i);796if (u->is_Phi() && u->bottom_type() == Type::MEMORY) {797if (u->adr_type() == TypePtr::BOTTOM) {798mem = u;799}800}801}802} else {803if (c->is_Call() && c->as_Call()->adr_type() != NULL) {804CallProjections projs;805c->as_Call()->extract_projections(&projs, true, false);806if (projs.fallthrough_memproj != NULL) {807if (projs.fallthrough_memproj->adr_type() == TypePtr::BOTTOM) {808if (projs.catchall_memproj == NULL) {809mem = projs.fallthrough_memproj;810} else {811if (phase->is_dominator(projs.fallthrough_catchproj, ctrl)) {812mem = projs.fallthrough_memproj;813} else {814assert(phase->is_dominator(projs.catchall_catchproj, ctrl), "one proj must dominate barrier");815mem = projs.catchall_memproj;816}817}818}819} else {820Node* proj = c->as_Call()->proj_out(TypeFunc::Memory);821if (proj != NULL &&822proj->adr_type() == TypePtr::BOTTOM) {823mem = proj;824}825}826} else {827for (DUIterator_Fast imax, i = c->fast_outs(imax); i < imax; i++) {828Node* u = c->fast_out(i);829if (u->is_Proj() &&830u->bottom_type() == Type::MEMORY &&831u->adr_type() == TypePtr::BOTTOM) {832assert(c->is_SafePoint() || c->is_MemBar() || c->is_Start(), "");833assert(mem == NULL, "only one proj");834mem = u;835}836}837assert(!c->is_Call() || c->as_Call()->adr_type() != NULL || mem == NULL, "no mem projection expected");838}839}840c = phase->idom(c);841} while (mem == NULL);842return mem;843}844845void ShenandoahBarrierC2Support::follow_barrier_uses(Node* n, Node* ctrl, Unique_Node_List& uses, PhaseIdealLoop* phase) {846for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {847Node* u = n->fast_out(i);848if (!u->is_CFG() && phase->get_ctrl(u) == ctrl && (!u->is_Phi() || !u->in(0)->is_Loop() || u->in(LoopNode::LoopBackControl) != n)) {849uses.push(u);850}851}852}853854static void hide_strip_mined_loop(OuterStripMinedLoopNode* outer, CountedLoopNode* inner, PhaseIdealLoop* phase) {855OuterStripMinedLoopEndNode* le = inner->outer_loop_end();856Node* new_outer = new LoopNode(outer->in(LoopNode::EntryControl), outer->in(LoopNode::LoopBackControl));857phase->register_control(new_outer, phase->get_loop(outer), outer->in(LoopNode::EntryControl));858Node* new_le = new IfNode(le->in(0), le->in(1), le->_prob, le->_fcnt);859phase->register_control(new_le, phase->get_loop(le), le->in(0));860phase->lazy_replace(outer, new_outer);861phase->lazy_replace(le, new_le);862inner->clear_strip_mined();863}864865void ShenandoahBarrierC2Support::test_gc_state(Node*& ctrl, Node* raw_mem, Node*& test_fail_ctrl,866PhaseIdealLoop* phase, int flags) {867PhaseIterGVN& igvn = phase->igvn();868Node* old_ctrl = ctrl;869870Node* thread = new ThreadLocalNode();871Node* gc_state_offset = igvn.MakeConX(in_bytes(ShenandoahThreadLocalData::gc_state_offset()));872Node* gc_state_addr = new AddPNode(phase->C->top(), thread, gc_state_offset);873Node* gc_state = new LoadBNode(old_ctrl, raw_mem, gc_state_addr,874DEBUG_ONLY(phase->C->get_adr_type(Compile::AliasIdxRaw)) NOT_DEBUG(NULL),875TypeInt::BYTE, MemNode::unordered);876Node* gc_state_and = new AndINode(gc_state, igvn.intcon(flags));877Node* gc_state_cmp = new CmpINode(gc_state_and, igvn.zerocon(T_INT));878Node* gc_state_bool = new BoolNode(gc_state_cmp, BoolTest::ne);879880IfNode* gc_state_iff = new IfNode(old_ctrl, gc_state_bool, PROB_UNLIKELY(0.999), COUNT_UNKNOWN);881ctrl = new IfTrueNode(gc_state_iff);882test_fail_ctrl = new IfFalseNode(gc_state_iff);883884IdealLoopTree* loop = phase->get_loop(old_ctrl);885phase->register_control(gc_state_iff, loop, old_ctrl);886phase->register_control(ctrl, loop, gc_state_iff);887phase->register_control(test_fail_ctrl, loop, gc_state_iff);888889phase->register_new_node(thread, old_ctrl);890phase->register_new_node(gc_state_addr, old_ctrl);891phase->register_new_node(gc_state, old_ctrl);892phase->register_new_node(gc_state_and, old_ctrl);893phase->register_new_node(gc_state_cmp, old_ctrl);894phase->register_new_node(gc_state_bool, old_ctrl);895896phase->set_ctrl(gc_state_offset, phase->C->root());897898assert(is_gc_state_test(gc_state_iff, flags), "Should match the shape");899}900901void ShenandoahBarrierC2Support::test_null(Node*& ctrl, Node* val, Node*& null_ctrl, PhaseIdealLoop* phase) {902Node* old_ctrl = ctrl;903PhaseIterGVN& igvn = phase->igvn();904905const Type* val_t = igvn.type(val);906if (val_t->meet(TypePtr::NULL_PTR) == val_t) {907Node* null_cmp = new CmpPNode(val, igvn.zerocon(T_OBJECT));908Node* null_test = new BoolNode(null_cmp, BoolTest::ne);909910IfNode* null_iff = new IfNode(old_ctrl, null_test, PROB_LIKELY(0.999), COUNT_UNKNOWN);911ctrl = new IfTrueNode(null_iff);912null_ctrl = new IfFalseNode(null_iff);913914IdealLoopTree* loop = phase->get_loop(old_ctrl);915phase->register_control(null_iff, loop, old_ctrl);916phase->register_control(ctrl, loop, null_iff);917phase->register_control(null_ctrl, loop, null_iff);918919phase->register_new_node(null_cmp, old_ctrl);920phase->register_new_node(null_test, old_ctrl);921}922}923924void ShenandoahBarrierC2Support::test_in_cset(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase) {925Node* old_ctrl = ctrl;926PhaseIterGVN& igvn = phase->igvn();927928Node* raw_val = new CastP2XNode(old_ctrl, val);929Node* cset_idx = new URShiftXNode(raw_val, igvn.intcon(ShenandoahHeapRegion::region_size_bytes_shift_jint()));930931// Figure out the target cset address with raw pointer math.932// This avoids matching AddP+LoadB that would emit inefficient code.933// See JDK-8245465.934Node* cset_addr_ptr = igvn.makecon(TypeRawPtr::make(ShenandoahHeap::in_cset_fast_test_addr()));935Node* cset_addr = new CastP2XNode(old_ctrl, cset_addr_ptr);936Node* cset_load_addr = new AddXNode(cset_addr, cset_idx);937Node* cset_load_ptr = new CastX2PNode(cset_load_addr);938939Node* cset_load = new LoadBNode(old_ctrl, raw_mem, cset_load_ptr,940DEBUG_ONLY(phase->C->get_adr_type(Compile::AliasIdxRaw)) NOT_DEBUG(NULL),941TypeInt::BYTE, MemNode::unordered);942Node* cset_cmp = new CmpINode(cset_load, igvn.zerocon(T_INT));943Node* cset_bool = new BoolNode(cset_cmp, BoolTest::ne);944945IfNode* cset_iff = new IfNode(old_ctrl, cset_bool, PROB_UNLIKELY(0.999), COUNT_UNKNOWN);946ctrl = new IfTrueNode(cset_iff);947not_cset_ctrl = new IfFalseNode(cset_iff);948949IdealLoopTree *loop = phase->get_loop(old_ctrl);950phase->register_control(cset_iff, loop, old_ctrl);951phase->register_control(ctrl, loop, cset_iff);952phase->register_control(not_cset_ctrl, loop, cset_iff);953954phase->set_ctrl(cset_addr_ptr, phase->C->root());955956phase->register_new_node(raw_val, old_ctrl);957phase->register_new_node(cset_idx, old_ctrl);958phase->register_new_node(cset_addr, old_ctrl);959phase->register_new_node(cset_load_addr, old_ctrl);960phase->register_new_node(cset_load_ptr, old_ctrl);961phase->register_new_node(cset_load, old_ctrl);962phase->register_new_node(cset_cmp, old_ctrl);963phase->register_new_node(cset_bool, old_ctrl);964}965966void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr, Node*& result_mem, Node* raw_mem,967DecoratorSet decorators, PhaseIdealLoop* phase) {968IdealLoopTree*loop = phase->get_loop(ctrl);969const TypePtr* obj_type = phase->igvn().type(val)->is_oopptr();970971// The slow path stub consumes and produces raw memory in addition972// to the existing memory edges973Node* base = find_bottom_mem(ctrl, phase);974MergeMemNode* mm = MergeMemNode::make(base);975mm->set_memory_at(Compile::AliasIdxRaw, raw_mem);976phase->register_new_node(mm, ctrl);977978address calladdr = NULL;979const char* name = NULL;980bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators);981bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators);982bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators);983bool is_native = ShenandoahBarrierSet::is_native_access(decorators);984bool is_narrow = UseCompressedOops && !is_native;985if (is_strong) {986if (is_narrow) {987calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong_narrow);988name = "load_reference_barrier_strong_narrow";989} else {990calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong);991name = "load_reference_barrier_strong";992}993} else if (is_weak) {994if (is_narrow) {995calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak_narrow);996name = "load_reference_barrier_weak_narrow";997} else {998calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak);999name = "load_reference_barrier_weak";1000}1001} else {1002assert(is_phantom, "only remaining strength");1003if (is_narrow) {1004calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom_narrow);1005name = "load_reference_barrier_phantom_narrow";1006} else {1007calladdr = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom);1008name = "load_reference_barrier_phantom";1009}1010}1011Node* call = new CallLeafNode(ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type(), calladdr, name, TypeRawPtr::BOTTOM);10121013call->init_req(TypeFunc::Control, ctrl);1014call->init_req(TypeFunc::I_O, phase->C->top());1015call->init_req(TypeFunc::Memory, mm);1016call->init_req(TypeFunc::FramePtr, phase->C->top());1017call->init_req(TypeFunc::ReturnAdr, phase->C->top());1018call->init_req(TypeFunc::Parms, val);1019call->init_req(TypeFunc::Parms+1, load_addr);1020phase->register_control(call, loop, ctrl);1021ctrl = new ProjNode(call, TypeFunc::Control);1022phase->register_control(ctrl, loop, call);1023result_mem = new ProjNode(call, TypeFunc::Memory);1024phase->register_new_node(result_mem, call);1025val = new ProjNode(call, TypeFunc::Parms);1026phase->register_new_node(val, call);1027val = new CheckCastPPNode(ctrl, val, obj_type);1028phase->register_new_node(val, ctrl);1029}10301031void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase) {1032Node* ctrl = phase->get_ctrl(barrier);1033Node* init_raw_mem = fixer.find_mem(ctrl, barrier);10341035// Update the control of all nodes that should be after the1036// barrier control flow1037uses.clear();1038// Every node that is control dependent on the barrier's input1039// control will be after the expanded barrier. The raw memory (if1040// its memory is control dependent on the barrier's input control)1041// must stay above the barrier.1042uses_to_ignore.clear();1043if (phase->has_ctrl(init_raw_mem) && phase->get_ctrl(init_raw_mem) == ctrl && !init_raw_mem->is_Phi()) {1044uses_to_ignore.push(init_raw_mem);1045}1046for (uint next = 0; next < uses_to_ignore.size(); next++) {1047Node *n = uses_to_ignore.at(next);1048for (uint i = 0; i < n->req(); i++) {1049Node* in = n->in(i);1050if (in != NULL && phase->has_ctrl(in) && phase->get_ctrl(in) == ctrl) {1051uses_to_ignore.push(in);1052}1053}1054}1055for (DUIterator_Fast imax, i = ctrl->fast_outs(imax); i < imax; i++) {1056Node* u = ctrl->fast_out(i);1057if (u->_idx < last &&1058u != barrier &&1059!uses_to_ignore.member(u) &&1060(u->in(0) != ctrl || (!u->is_Region() && !u->is_Phi())) &&1061(ctrl->Opcode() != Op_CatchProj || u->Opcode() != Op_CreateEx)) {1062Node* old_c = phase->ctrl_or_self(u);1063Node* c = old_c;1064if (c != ctrl ||1065is_dominator_same_ctrl(old_c, barrier, u, phase) ||1066ShenandoahBarrierSetC2::is_shenandoah_state_load(u)) {1067phase->igvn().rehash_node_delayed(u);1068int nb = u->replace_edge(ctrl, region, &phase->igvn());1069if (u->is_CFG()) {1070if (phase->idom(u) == ctrl) {1071phase->set_idom(u, region, phase->dom_depth(region));1072}1073} else if (phase->get_ctrl(u) == ctrl) {1074assert(u != init_raw_mem, "should leave input raw mem above the barrier");1075uses.push(u);1076}1077assert(nb == 1, "more than 1 ctrl input?");1078--i, imax -= nb;1079}1080}1081}1082}10831084static Node* create_phis_on_call_return(Node* ctrl, Node* c, Node* n, Node* n_clone, const CallProjections& projs, PhaseIdealLoop* phase) {1085Node* region = NULL;1086while (c != ctrl) {1087if (c->is_Region()) {1088region = c;1089}1090c = phase->idom(c);1091}1092assert(region != NULL, "");1093Node* phi = new PhiNode(region, n->bottom_type());1094for (uint j = 1; j < region->req(); j++) {1095Node* in = region->in(j);1096if (phase->is_dominator(projs.fallthrough_catchproj, in)) {1097phi->init_req(j, n);1098} else if (phase->is_dominator(projs.catchall_catchproj, in)) {1099phi->init_req(j, n_clone);1100} else {1101phi->init_req(j, create_phis_on_call_return(ctrl, in, n, n_clone, projs, phase));1102}1103}1104phase->register_new_node(phi, region);1105return phi;1106}11071108void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {1109ShenandoahBarrierSetC2State* state = ShenandoahBarrierSetC2::bsc2()->state();11101111Unique_Node_List uses;1112for (int i = 0; i < state->iu_barriers_count(); i++) {1113Node* barrier = state->iu_barrier(i);1114Node* ctrl = phase->get_ctrl(barrier);1115IdealLoopTree* loop = phase->get_loop(ctrl);1116Node* head = loop->head();1117if (head->is_OuterStripMinedLoop()) {1118// Expanding a barrier here will break loop strip mining1119// verification. Transform the loop so the loop nest doesn't1120// appear as strip mined.1121OuterStripMinedLoopNode* outer = head->as_OuterStripMinedLoop();1122hide_strip_mined_loop(outer, outer->unique_ctrl_out()->as_CountedLoop(), phase);1123}1124}11251126Node_Stack stack(0);1127Node_List clones;1128for (int i = state->load_reference_barriers_count() - 1; i >= 0; i--) {1129ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i);11301131Node* ctrl = phase->get_ctrl(lrb);1132Node* val = lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn);11331134CallStaticJavaNode* unc = NULL;1135Node* unc_ctrl = NULL;1136Node* uncasted_val = val;11371138for (DUIterator_Fast imax, i = lrb->fast_outs(imax); i < imax; i++) {1139Node* u = lrb->fast_out(i);1140if (u->Opcode() == Op_CastPP &&1141u->in(0) != NULL &&1142phase->is_dominator(u->in(0), ctrl)) {1143const Type* u_t = phase->igvn().type(u);11441145if (u_t->meet(TypePtr::NULL_PTR) != u_t &&1146u->in(0)->Opcode() == Op_IfTrue &&1147u->in(0)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) &&1148u->in(0)->in(0)->is_If() &&1149u->in(0)->in(0)->in(1)->Opcode() == Op_Bool &&1150u->in(0)->in(0)->in(1)->as_Bool()->_test._test == BoolTest::ne &&1151u->in(0)->in(0)->in(1)->in(1)->Opcode() == Op_CmpP &&1152u->in(0)->in(0)->in(1)->in(1)->in(1) == val &&1153u->in(0)->in(0)->in(1)->in(1)->in(2)->bottom_type() == TypePtr::NULL_PTR) {1154IdealLoopTree* loop = phase->get_loop(ctrl);1155IdealLoopTree* unc_loop = phase->get_loop(u->in(0));11561157if (!unc_loop->is_member(loop)) {1158continue;1159}11601161Node* branch = no_branches(ctrl, u->in(0), false, phase);1162assert(branch == NULL || branch == NodeSentinel, "was not looking for a branch");1163if (branch == NodeSentinel) {1164continue;1165}11661167Node* iff = u->in(0)->in(0);1168Node* bol = iff->in(1)->clone();1169Node* cmp = bol->in(1)->clone();1170cmp->set_req(1, lrb);1171bol->set_req(1, cmp);1172phase->igvn().replace_input_of(iff, 1, bol);1173phase->set_ctrl(lrb, iff->in(0));1174phase->register_new_node(cmp, iff->in(0));1175phase->register_new_node(bol, iff->in(0));1176break;1177}1178}1179}1180if ((ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) || ctrl->is_CallJava()) {1181CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_CallJava() : ctrl->as_CallJava();1182if (call->entry_point() == OptoRuntime::rethrow_stub()) {1183// The rethrow call may have too many projections to be1184// properly handled here. Given there's no reason for a1185// barrier to depend on the call, move it above the call1186stack.push(lrb, 0);1187do {1188Node* n = stack.node();1189uint idx = stack.index();1190if (idx < n->req()) {1191Node* in = n->in(idx);1192stack.set_index(idx+1);1193if (in != NULL) {1194if (phase->has_ctrl(in)) {1195if (phase->is_dominator(call, phase->get_ctrl(in))) {1196#ifdef ASSERT1197for (uint i = 0; i < stack.size(); i++) {1198assert(stack.node_at(i) != in, "node shouldn't have been seen yet");1199}1200#endif1201stack.push(in, 0);1202}1203} else {1204assert(phase->is_dominator(in, call->in(0)), "no dependency on the call");1205}1206}1207} else {1208phase->set_ctrl(n, call->in(0));1209stack.pop();1210}1211} while(stack.size() > 0);1212continue;1213}1214CallProjections projs;1215call->extract_projections(&projs, false, false);12161217#ifdef ASSERT1218VectorSet cloned;1219#endif1220Node* lrb_clone = lrb->clone();1221phase->register_new_node(lrb_clone, projs.catchall_catchproj);1222phase->set_ctrl(lrb, projs.fallthrough_catchproj);12231224stack.push(lrb, 0);1225clones.push(lrb_clone);12261227do {1228assert(stack.size() == clones.size(), "");1229Node* n = stack.node();1230#ifdef ASSERT1231if (n->is_Load()) {1232Node* mem = n->in(MemNode::Memory);1233for (DUIterator_Fast jmax, j = mem->fast_outs(jmax); j < jmax; j++) {1234Node* u = mem->fast_out(j);1235assert(!u->is_Store() || !u->is_LoadStore() || phase->get_ctrl(u) != ctrl, "anti dependent store?");1236}1237}1238#endif1239uint idx = stack.index();1240Node* n_clone = clones.at(clones.size()-1);1241if (idx < n->outcnt()) {1242Node* u = n->raw_out(idx);1243Node* c = phase->ctrl_or_self(u);1244if (phase->is_dominator(call, c) && phase->is_dominator(c, projs.fallthrough_proj)) {1245stack.set_index(idx+1);1246assert(!u->is_CFG(), "");1247stack.push(u, 0);1248assert(!cloned.test_set(u->_idx), "only one clone");1249Node* u_clone = u->clone();1250int nb = u_clone->replace_edge(n, n_clone, &phase->igvn());1251assert(nb > 0, "should have replaced some uses");1252phase->register_new_node(u_clone, projs.catchall_catchproj);1253clones.push(u_clone);1254phase->set_ctrl(u, projs.fallthrough_catchproj);1255} else {1256bool replaced = false;1257if (u->is_Phi()) {1258for (uint k = 1; k < u->req(); k++) {1259if (u->in(k) == n) {1260if (phase->is_dominator(projs.catchall_catchproj, u->in(0)->in(k))) {1261phase->igvn().replace_input_of(u, k, n_clone);1262replaced = true;1263} else if (!phase->is_dominator(projs.fallthrough_catchproj, u->in(0)->in(k))) {1264phase->igvn().replace_input_of(u, k, create_phis_on_call_return(ctrl, u->in(0)->in(k), n, n_clone, projs, phase));1265replaced = true;1266}1267}1268}1269} else {1270if (phase->is_dominator(projs.catchall_catchproj, c)) {1271phase->igvn().rehash_node_delayed(u);1272int nb = u->replace_edge(n, n_clone, &phase->igvn());1273assert(nb > 0, "should have replaced some uses");1274replaced = true;1275} else if (!phase->is_dominator(projs.fallthrough_catchproj, c)) {1276if (u->is_If()) {1277// Can't break If/Bool/Cmp chain1278assert(n->is_Bool(), "unexpected If shape");1279assert(stack.node_at(stack.size()-2)->is_Cmp(), "unexpected If shape");1280assert(n_clone->is_Bool(), "unexpected clone");1281assert(clones.at(clones.size()-2)->is_Cmp(), "unexpected clone");1282Node* bol_clone = n->clone();1283Node* cmp_clone = stack.node_at(stack.size()-2)->clone();1284bol_clone->set_req(1, cmp_clone);12851286Node* nn = stack.node_at(stack.size()-3);1287Node* nn_clone = clones.at(clones.size()-3);1288assert(nn->Opcode() == nn_clone->Opcode(), "mismatch");12891290int nb = cmp_clone->replace_edge(nn, create_phis_on_call_return(ctrl, c, nn, nn_clone, projs, phase),1291&phase->igvn());1292assert(nb > 0, "should have replaced some uses");12931294phase->register_new_node(bol_clone, u->in(0));1295phase->register_new_node(cmp_clone, u->in(0));12961297phase->igvn().replace_input_of(u, 1, bol_clone);12981299} else {1300phase->igvn().rehash_node_delayed(u);1301int nb = u->replace_edge(n, create_phis_on_call_return(ctrl, c, n, n_clone, projs, phase), &phase->igvn());1302assert(nb > 0, "should have replaced some uses");1303}1304replaced = true;1305}1306}1307if (!replaced) {1308stack.set_index(idx+1);1309}1310}1311} else {1312stack.pop();1313clones.pop();1314}1315} while (stack.size() > 0);1316assert(stack.size() == 0 && clones.size() == 0, "");1317}1318}13191320for (int i = 0; i < state->load_reference_barriers_count(); i++) {1321ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i);1322Node* ctrl = phase->get_ctrl(lrb);1323IdealLoopTree* loop = phase->get_loop(ctrl);1324Node* head = loop->head();1325if (head->is_OuterStripMinedLoop()) {1326// Expanding a barrier here will break loop strip mining1327// verification. Transform the loop so the loop nest doesn't1328// appear as strip mined.1329OuterStripMinedLoopNode* outer = head->as_OuterStripMinedLoop();1330hide_strip_mined_loop(outer, outer->unique_ctrl_out()->as_CountedLoop(), phase);1331}1332}13331334// Expand load-reference-barriers1335MemoryGraphFixer fixer(Compile::AliasIdxRaw, true, phase);1336Unique_Node_List uses_to_ignore;1337for (int i = state->load_reference_barriers_count() - 1; i >= 0; i--) {1338ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i);1339uint last = phase->C->unique();1340Node* ctrl = phase->get_ctrl(lrb);1341Node* val = lrb->in(ShenandoahLoadReferenceBarrierNode::ValueIn);134213431344Node* orig_ctrl = ctrl;13451346Node* raw_mem = fixer.find_mem(ctrl, lrb);1347Node* init_raw_mem = raw_mem;1348Node* raw_mem_for_ctrl = fixer.find_mem(ctrl, NULL);13491350IdealLoopTree *loop = phase->get_loop(ctrl);13511352Node* heap_stable_ctrl = NULL;1353Node* null_ctrl = NULL;13541355assert(val->bottom_type()->make_oopptr(), "need oop");1356assert(val->bottom_type()->make_oopptr()->const_oop() == NULL, "expect non-constant");13571358enum { _heap_stable = 1, _evac_path, _not_cset, PATH_LIMIT };1359Node* region = new RegionNode(PATH_LIMIT);1360Node* val_phi = new PhiNode(region, val->bottom_type()->is_oopptr());1361Node* raw_mem_phi = PhiNode::make(region, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM);13621363// Stable path.1364int flags = ShenandoahHeap::HAS_FORWARDED;1365if (!ShenandoahBarrierSet::is_strong_access(lrb->decorators())) {1366flags |= ShenandoahHeap::WEAK_ROOTS;1367}1368test_gc_state(ctrl, raw_mem, heap_stable_ctrl, phase, flags);1369IfNode* heap_stable_iff = heap_stable_ctrl->in(0)->as_If();13701371// Heap stable case1372region->init_req(_heap_stable, heap_stable_ctrl);1373val_phi->init_req(_heap_stable, val);1374raw_mem_phi->init_req(_heap_stable, raw_mem);13751376// Test for in-cset, unless it's a native-LRB. Native LRBs need to return NULL1377// even for non-cset objects to prevent ressurrection of such objects.1378// Wires !in_cset(obj) to slot 2 of region and phis1379Node* not_cset_ctrl = NULL;1380if (ShenandoahBarrierSet::is_strong_access(lrb->decorators())) {1381test_in_cset(ctrl, not_cset_ctrl, val, raw_mem, phase);1382}1383if (not_cset_ctrl != NULL) {1384region->init_req(_not_cset, not_cset_ctrl);1385val_phi->init_req(_not_cset, val);1386raw_mem_phi->init_req(_not_cset, raw_mem);1387} else {1388region->del_req(_not_cset);1389val_phi->del_req(_not_cset);1390raw_mem_phi->del_req(_not_cset);1391}13921393// Resolve object when orig-value is in cset.1394// Make the unconditional resolve for fwdptr.13951396// Call lrb-stub and wire up that path in slots 41397Node* result_mem = NULL;13981399Node* addr;1400if (ShenandoahSelfFixing) {1401VectorSet visited;1402addr = get_load_addr(phase, visited, lrb);1403} else {1404addr = phase->igvn().zerocon(T_OBJECT);1405}1406if (addr->Opcode() == Op_AddP) {1407Node* orig_base = addr->in(AddPNode::Base);1408Node* base = new CheckCastPPNode(ctrl, orig_base, orig_base->bottom_type(), true);1409phase->register_new_node(base, ctrl);1410if (addr->in(AddPNode::Base) == addr->in((AddPNode::Address))) {1411// Field access1412addr = addr->clone();1413addr->set_req(AddPNode::Base, base);1414addr->set_req(AddPNode::Address, base);1415phase->register_new_node(addr, ctrl);1416} else {1417Node* addr2 = addr->in(AddPNode::Address);1418if (addr2->Opcode() == Op_AddP && addr2->in(AddPNode::Base) == addr2->in(AddPNode::Address) &&1419addr2->in(AddPNode::Base) == orig_base) {1420addr2 = addr2->clone();1421addr2->set_req(AddPNode::Base, base);1422addr2->set_req(AddPNode::Address, base);1423phase->register_new_node(addr2, ctrl);1424addr = addr->clone();1425addr->set_req(AddPNode::Base, base);1426addr->set_req(AddPNode::Address, addr2);1427phase->register_new_node(addr, ctrl);1428}1429}1430}1431call_lrb_stub(ctrl, val, addr, result_mem, raw_mem, lrb->decorators(), phase);1432region->init_req(_evac_path, ctrl);1433val_phi->init_req(_evac_path, val);1434raw_mem_phi->init_req(_evac_path, result_mem);14351436phase->register_control(region, loop, heap_stable_iff);1437Node* out_val = val_phi;1438phase->register_new_node(val_phi, region);1439phase->register_new_node(raw_mem_phi, region);14401441fix_ctrl(lrb, region, fixer, uses, uses_to_ignore, last, phase);14421443ctrl = orig_ctrl;14441445phase->igvn().replace_node(lrb, out_val);14461447follow_barrier_uses(out_val, ctrl, uses, phase);14481449for(uint next = 0; next < uses.size(); next++ ) {1450Node *n = uses.at(next);1451assert(phase->get_ctrl(n) == ctrl, "bad control");1452assert(n != init_raw_mem, "should leave input raw mem above the barrier");1453phase->set_ctrl(n, region);1454follow_barrier_uses(n, ctrl, uses, phase);1455}14561457// The slow path call produces memory: hook the raw memory phi1458// from the expanded load reference barrier with the rest of the graph1459// which may require adding memory phis at every post dominated1460// region and at enclosing loop heads. Use the memory state1461// collected in memory_nodes to fix the memory graph. Update that1462// memory state as we go.1463fixer.fix_mem(ctrl, region, init_raw_mem, raw_mem_for_ctrl, raw_mem_phi, uses);1464}1465// Done expanding load-reference-barriers.1466assert(ShenandoahBarrierSetC2::bsc2()->state()->load_reference_barriers_count() == 0, "all load reference barrier nodes should have been replaced");14671468for (int i = state->iu_barriers_count() - 1; i >= 0; i--) {1469Node* barrier = state->iu_barrier(i);1470Node* pre_val = barrier->in(1);14711472if (phase->igvn().type(pre_val)->higher_equal(TypePtr::NULL_PTR)) {1473ShouldNotReachHere();1474continue;1475}14761477Node* ctrl = phase->get_ctrl(barrier);14781479if (ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) {1480assert(is_dominator(phase->get_ctrl(pre_val), ctrl->in(0)->in(0), pre_val, ctrl->in(0), phase), "can't move");1481ctrl = ctrl->in(0)->in(0);1482phase->set_ctrl(barrier, ctrl);1483} else if (ctrl->is_CallRuntime()) {1484assert(is_dominator(phase->get_ctrl(pre_val), ctrl->in(0), pre_val, ctrl, phase), "can't move");1485ctrl = ctrl->in(0);1486phase->set_ctrl(barrier, ctrl);1487}14881489Node* init_ctrl = ctrl;1490IdealLoopTree* loop = phase->get_loop(ctrl);1491Node* raw_mem = fixer.find_mem(ctrl, barrier);1492Node* init_raw_mem = raw_mem;1493Node* raw_mem_for_ctrl = fixer.find_mem(ctrl, NULL);1494Node* heap_stable_ctrl = NULL;1495Node* null_ctrl = NULL;1496uint last = phase->C->unique();14971498enum { _heap_stable = 1, _heap_unstable, PATH_LIMIT };1499Node* region = new RegionNode(PATH_LIMIT);1500Node* phi = PhiNode::make(region, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM);15011502enum { _fast_path = 1, _slow_path, _null_path, PATH_LIMIT2 };1503Node* region2 = new RegionNode(PATH_LIMIT2);1504Node* phi2 = PhiNode::make(region2, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM);15051506// Stable path.1507test_gc_state(ctrl, raw_mem, heap_stable_ctrl, phase, ShenandoahHeap::MARKING);1508region->init_req(_heap_stable, heap_stable_ctrl);1509phi->init_req(_heap_stable, raw_mem);15101511// Null path1512Node* reg2_ctrl = NULL;1513test_null(ctrl, pre_val, null_ctrl, phase);1514if (null_ctrl != NULL) {1515reg2_ctrl = null_ctrl->in(0);1516region2->init_req(_null_path, null_ctrl);1517phi2->init_req(_null_path, raw_mem);1518} else {1519region2->del_req(_null_path);1520phi2->del_req(_null_path);1521}15221523const int index_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset());1524const int buffer_offset = in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset());1525Node* thread = new ThreadLocalNode();1526phase->register_new_node(thread, ctrl);1527Node* buffer_adr = new AddPNode(phase->C->top(), thread, phase->igvn().MakeConX(buffer_offset));1528phase->register_new_node(buffer_adr, ctrl);1529Node* index_adr = new AddPNode(phase->C->top(), thread, phase->igvn().MakeConX(index_offset));1530phase->register_new_node(index_adr, ctrl);15311532BasicType index_bt = TypeX_X->basic_type();1533assert(sizeof(size_t) == type2aelembytes(index_bt), "Loading Shenandoah SATBMarkQueue::_index with wrong size.");1534const TypePtr* adr_type = TypeRawPtr::BOTTOM;1535Node* index = new LoadXNode(ctrl, raw_mem, index_adr, adr_type, TypeX_X, MemNode::unordered);1536phase->register_new_node(index, ctrl);1537Node* index_cmp = new CmpXNode(index, phase->igvn().MakeConX(0));1538phase->register_new_node(index_cmp, ctrl);1539Node* index_test = new BoolNode(index_cmp, BoolTest::ne);1540phase->register_new_node(index_test, ctrl);1541IfNode* queue_full_iff = new IfNode(ctrl, index_test, PROB_LIKELY(0.999), COUNT_UNKNOWN);1542if (reg2_ctrl == NULL) reg2_ctrl = queue_full_iff;1543phase->register_control(queue_full_iff, loop, ctrl);1544Node* not_full = new IfTrueNode(queue_full_iff);1545phase->register_control(not_full, loop, queue_full_iff);1546Node* full = new IfFalseNode(queue_full_iff);1547phase->register_control(full, loop, queue_full_iff);15481549ctrl = not_full;15501551Node* next_index = new SubXNode(index, phase->igvn().MakeConX(sizeof(intptr_t)));1552phase->register_new_node(next_index, ctrl);15531554Node* buffer = new LoadPNode(ctrl, raw_mem, buffer_adr, adr_type, TypeRawPtr::NOTNULL, MemNode::unordered);1555phase->register_new_node(buffer, ctrl);1556Node *log_addr = new AddPNode(phase->C->top(), buffer, next_index);1557phase->register_new_node(log_addr, ctrl);1558Node* log_store = new StorePNode(ctrl, raw_mem, log_addr, adr_type, pre_val, MemNode::unordered);1559phase->register_new_node(log_store, ctrl);1560// update the index1561Node* index_update = new StoreXNode(ctrl, log_store, index_adr, adr_type, next_index, MemNode::unordered);1562phase->register_new_node(index_update, ctrl);15631564// Fast-path case1565region2->init_req(_fast_path, ctrl);1566phi2->init_req(_fast_path, index_update);15671568ctrl = full;15691570Node* base = find_bottom_mem(ctrl, phase);15711572MergeMemNode* mm = MergeMemNode::make(base);1573mm->set_memory_at(Compile::AliasIdxRaw, raw_mem);1574phase->register_new_node(mm, ctrl);15751576Node* call = new CallLeafNode(ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type(), CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), "shenandoah_wb_pre", TypeRawPtr::BOTTOM);1577call->init_req(TypeFunc::Control, ctrl);1578call->init_req(TypeFunc::I_O, phase->C->top());1579call->init_req(TypeFunc::Memory, mm);1580call->init_req(TypeFunc::FramePtr, phase->C->top());1581call->init_req(TypeFunc::ReturnAdr, phase->C->top());1582call->init_req(TypeFunc::Parms, pre_val);1583call->init_req(TypeFunc::Parms+1, thread);1584phase->register_control(call, loop, ctrl);15851586Node* ctrl_proj = new ProjNode(call, TypeFunc::Control);1587phase->register_control(ctrl_proj, loop, call);1588Node* mem_proj = new ProjNode(call, TypeFunc::Memory);1589phase->register_new_node(mem_proj, call);15901591// Slow-path case1592region2->init_req(_slow_path, ctrl_proj);1593phi2->init_req(_slow_path, mem_proj);15941595phase->register_control(region2, loop, reg2_ctrl);1596phase->register_new_node(phi2, region2);15971598region->init_req(_heap_unstable, region2);1599phi->init_req(_heap_unstable, phi2);16001601phase->register_control(region, loop, heap_stable_ctrl->in(0));1602phase->register_new_node(phi, region);16031604fix_ctrl(barrier, region, fixer, uses, uses_to_ignore, last, phase);1605for(uint next = 0; next < uses.size(); next++ ) {1606Node *n = uses.at(next);1607assert(phase->get_ctrl(n) == init_ctrl, "bad control");1608assert(n != init_raw_mem, "should leave input raw mem above the barrier");1609phase->set_ctrl(n, region);1610follow_barrier_uses(n, init_ctrl, uses, phase);1611}1612fixer.fix_mem(init_ctrl, region, init_raw_mem, raw_mem_for_ctrl, phi, uses);16131614phase->igvn().replace_node(barrier, pre_val);1615}1616assert(state->iu_barriers_count() == 0, "all enqueue barrier nodes should have been replaced");16171618}16191620Node* ShenandoahBarrierC2Support::get_load_addr(PhaseIdealLoop* phase, VectorSet& visited, Node* in) {1621if (visited.test_set(in->_idx)) {1622return NULL;1623}1624switch (in->Opcode()) {1625case Op_Proj:1626return get_load_addr(phase, visited, in->in(0));1627case Op_CastPP:1628case Op_CheckCastPP:1629case Op_DecodeN:1630case Op_EncodeP:1631return get_load_addr(phase, visited, in->in(1));1632case Op_LoadN:1633case Op_LoadP:1634return in->in(MemNode::Address);1635case Op_CompareAndExchangeN:1636case Op_CompareAndExchangeP:1637case Op_GetAndSetN:1638case Op_GetAndSetP:1639case Op_ShenandoahCompareAndExchangeP:1640case Op_ShenandoahCompareAndExchangeN:1641// Those instructions would just have stored a different1642// value into the field. No use to attempt to fix it at this point.1643return phase->igvn().zerocon(T_OBJECT);1644case Op_CMoveP:1645case Op_CMoveN: {1646Node* t = get_load_addr(phase, visited, in->in(CMoveNode::IfTrue));1647Node* f = get_load_addr(phase, visited, in->in(CMoveNode::IfFalse));1648// Handle unambiguous cases: single address reported on both branches.1649if (t != NULL && f == NULL) return t;1650if (t == NULL && f != NULL) return f;1651if (t != NULL && t == f) return t;1652// Ambiguity.1653return phase->igvn().zerocon(T_OBJECT);1654}1655case Op_Phi: {1656Node* addr = NULL;1657for (uint i = 1; i < in->req(); i++) {1658Node* addr1 = get_load_addr(phase, visited, in->in(i));1659if (addr == NULL) {1660addr = addr1;1661}1662if (addr != addr1) {1663return phase->igvn().zerocon(T_OBJECT);1664}1665}1666return addr;1667}1668case Op_ShenandoahLoadReferenceBarrier:1669return get_load_addr(phase, visited, in->in(ShenandoahLoadReferenceBarrierNode::ValueIn));1670case Op_ShenandoahIUBarrier:1671return get_load_addr(phase, visited, in->in(1));1672case Op_CallDynamicJava:1673case Op_CallLeaf:1674case Op_CallStaticJava:1675case Op_ConN:1676case Op_ConP:1677case Op_Parm:1678case Op_CreateEx:1679return phase->igvn().zerocon(T_OBJECT);1680default:1681#ifdef ASSERT1682fatal("Unknown node in get_load_addr: %s", NodeClassNames[in->Opcode()]);1683#endif1684return phase->igvn().zerocon(T_OBJECT);1685}16861687}16881689void ShenandoahBarrierC2Support::move_gc_state_test_out_of_loop(IfNode* iff, PhaseIdealLoop* phase) {1690IdealLoopTree *loop = phase->get_loop(iff);1691Node* loop_head = loop->_head;1692Node* entry_c = loop_head->in(LoopNode::EntryControl);16931694Node* bol = iff->in(1);1695Node* cmp = bol->in(1);1696Node* andi = cmp->in(1);1697Node* load = andi->in(1);16981699assert(is_gc_state_load(load), "broken");1700if (!phase->is_dominator(load->in(0), entry_c)) {1701Node* mem_ctrl = NULL;1702Node* mem = dom_mem(load->in(MemNode::Memory), loop_head, Compile::AliasIdxRaw, mem_ctrl, phase);1703load = load->clone();1704load->set_req(MemNode::Memory, mem);1705load->set_req(0, entry_c);1706phase->register_new_node(load, entry_c);1707andi = andi->clone();1708andi->set_req(1, load);1709phase->register_new_node(andi, entry_c);1710cmp = cmp->clone();1711cmp->set_req(1, andi);1712phase->register_new_node(cmp, entry_c);1713bol = bol->clone();1714bol->set_req(1, cmp);1715phase->register_new_node(bol, entry_c);17161717phase->igvn().replace_input_of(iff, 1, bol);1718}1719}17201721bool ShenandoahBarrierC2Support::identical_backtoback_ifs(Node* n, PhaseIdealLoop* phase) {1722if (!n->is_If() || n->is_CountedLoopEnd()) {1723return false;1724}1725Node* region = n->in(0);17261727if (!region->is_Region()) {1728return false;1729}1730Node* dom = phase->idom(region);1731if (!dom->is_If()) {1732return false;1733}17341735if (!is_heap_stable_test(n) || !is_heap_stable_test(dom)) {1736return false;1737}17381739IfNode* dom_if = dom->as_If();1740Node* proj_true = dom_if->proj_out(1);1741Node* proj_false = dom_if->proj_out(0);17421743for (uint i = 1; i < region->req(); i++) {1744if (phase->is_dominator(proj_true, region->in(i))) {1745continue;1746}1747if (phase->is_dominator(proj_false, region->in(i))) {1748continue;1749}1750return false;1751}17521753return true;1754}17551756void ShenandoahBarrierC2Support::merge_back_to_back_tests(Node* n, PhaseIdealLoop* phase) {1757assert(is_heap_stable_test(n), "no other tests");1758if (identical_backtoback_ifs(n, phase)) {1759Node* n_ctrl = n->in(0);1760if (phase->can_split_if(n_ctrl)) {1761IfNode* dom_if = phase->idom(n_ctrl)->as_If();1762if (is_heap_stable_test(n)) {1763Node* gc_state_load = n->in(1)->in(1)->in(1)->in(1);1764assert(is_gc_state_load(gc_state_load), "broken");1765Node* dom_gc_state_load = dom_if->in(1)->in(1)->in(1)->in(1);1766assert(is_gc_state_load(dom_gc_state_load), "broken");1767if (gc_state_load != dom_gc_state_load) {1768phase->igvn().replace_node(gc_state_load, dom_gc_state_load);1769}1770}1771PhiNode* bolphi = PhiNode::make_blank(n_ctrl, n->in(1));1772Node* proj_true = dom_if->proj_out(1);1773Node* proj_false = dom_if->proj_out(0);1774Node* con_true = phase->igvn().makecon(TypeInt::ONE);1775Node* con_false = phase->igvn().makecon(TypeInt::ZERO);17761777for (uint i = 1; i < n_ctrl->req(); i++) {1778if (phase->is_dominator(proj_true, n_ctrl->in(i))) {1779bolphi->init_req(i, con_true);1780} else {1781assert(phase->is_dominator(proj_false, n_ctrl->in(i)), "bad if");1782bolphi->init_req(i, con_false);1783}1784}1785phase->register_new_node(bolphi, n_ctrl);1786phase->igvn().replace_input_of(n, 1, bolphi);1787phase->do_split_if(n);1788}1789}1790}17911792IfNode* ShenandoahBarrierC2Support::find_unswitching_candidate(const IdealLoopTree* loop, PhaseIdealLoop* phase) {1793// Find first invariant test that doesn't exit the loop1794LoopNode *head = loop->_head->as_Loop();1795IfNode* unswitch_iff = NULL;1796Node* n = head->in(LoopNode::LoopBackControl);1797int loop_has_sfpts = -1;1798while (n != head) {1799Node* n_dom = phase->idom(n);1800if (n->is_Region()) {1801if (n_dom->is_If()) {1802IfNode* iff = n_dom->as_If();1803if (iff->in(1)->is_Bool()) {1804BoolNode* bol = iff->in(1)->as_Bool();1805if (bol->in(1)->is_Cmp()) {1806// If condition is invariant and not a loop exit,1807// then found reason to unswitch.1808if (is_heap_stable_test(iff) &&1809(loop_has_sfpts == -1 || loop_has_sfpts == 0)) {1810assert(!loop->is_loop_exit(iff), "both branches should be in the loop");1811if (loop_has_sfpts == -1) {1812for(uint i = 0; i < loop->_body.size(); i++) {1813Node *m = loop->_body[i];1814if (m->is_SafePoint() && !m->is_CallLeaf()) {1815loop_has_sfpts = 1;1816break;1817}1818}1819if (loop_has_sfpts == -1) {1820loop_has_sfpts = 0;1821}1822}1823if (!loop_has_sfpts) {1824unswitch_iff = iff;1825}1826}1827}1828}1829}1830}1831n = n_dom;1832}1833return unswitch_iff;1834}183518361837void ShenandoahBarrierC2Support::optimize_after_expansion(VectorSet &visited, Node_Stack &stack, Node_List &old_new, PhaseIdealLoop* phase) {1838Node_List heap_stable_tests;1839stack.push(phase->C->start(), 0);1840do {1841Node* n = stack.node();1842uint i = stack.index();18431844if (i < n->outcnt()) {1845Node* u = n->raw_out(i);1846stack.set_index(i+1);1847if (!visited.test_set(u->_idx)) {1848stack.push(u, 0);1849}1850} else {1851stack.pop();1852if (n->is_If() && is_heap_stable_test(n)) {1853heap_stable_tests.push(n);1854}1855}1856} while (stack.size() > 0);18571858for (uint i = 0; i < heap_stable_tests.size(); i++) {1859Node* n = heap_stable_tests.at(i);1860assert(is_heap_stable_test(n), "only evacuation test");1861merge_back_to_back_tests(n, phase);1862}18631864if (!phase->C->major_progress()) {1865VectorSet seen;1866for (uint i = 0; i < heap_stable_tests.size(); i++) {1867Node* n = heap_stable_tests.at(i);1868IdealLoopTree* loop = phase->get_loop(n);1869if (loop != phase->ltree_root() &&1870loop->_child == NULL &&1871!loop->_irreducible) {1872Node* head = loop->_head;1873if (head->is_Loop() &&1874(!head->is_CountedLoop() || head->as_CountedLoop()->is_main_loop() || head->as_CountedLoop()->is_normal_loop()) &&1875!seen.test_set(head->_idx)) {1876IfNode* iff = find_unswitching_candidate(loop, phase);1877if (iff != NULL) {1878Node* bol = iff->in(1);1879if (head->as_Loop()->is_strip_mined()) {1880head->as_Loop()->verify_strip_mined(0);1881}1882move_gc_state_test_out_of_loop(iff, phase);18831884AutoNodeBudget node_budget(phase);18851886if (loop->policy_unswitching(phase)) {1887if (head->as_Loop()->is_strip_mined()) {1888OuterStripMinedLoopNode* outer = head->as_CountedLoop()->outer_loop();1889hide_strip_mined_loop(outer, head->as_CountedLoop(), phase);1890}1891phase->do_unswitching(loop, old_new);1892} else {1893// Not proceeding with unswitching. Move load back in1894// the loop.1895phase->igvn().replace_input_of(iff, 1, bol);1896}1897}1898}1899}1900}1901}1902}19031904#ifdef ASSERT1905void ShenandoahBarrierC2Support::verify_raw_mem(RootNode* root) {1906const bool trace = false;1907ResourceMark rm;1908Unique_Node_List nodes;1909Unique_Node_List controls;1910Unique_Node_List memories;19111912nodes.push(root);1913for (uint next = 0; next < nodes.size(); next++) {1914Node *n = nodes.at(next);1915if (ShenandoahBarrierSetC2::is_shenandoah_lrb_call(n)) {1916controls.push(n);1917if (trace) { tty->print("XXXXXX verifying"); n->dump(); }1918for (uint next2 = 0; next2 < controls.size(); next2++) {1919Node *m = controls.at(next2);1920for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) {1921Node* u = m->fast_out(i);1922if (u->is_CFG() && !u->is_Root() &&1923!(u->Opcode() == Op_CProj && u->in(0)->Opcode() == Op_NeverBranch && u->as_Proj()->_con == 1) &&1924!(u->is_Region() && u->unique_ctrl_out()->Opcode() == Op_Halt)) {1925if (trace) { tty->print("XXXXXX pushing control"); u->dump(); }1926controls.push(u);1927}1928}1929}1930memories.push(n->as_Call()->proj_out(TypeFunc::Memory));1931for (uint next2 = 0; next2 < memories.size(); next2++) {1932Node *m = memories.at(next2);1933assert(m->bottom_type() == Type::MEMORY, "");1934for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) {1935Node* u = m->fast_out(i);1936if (u->bottom_type() == Type::MEMORY && (u->is_Mem() || u->is_ClearArray())) {1937if (trace) { tty->print("XXXXXX pushing memory"); u->dump(); }1938memories.push(u);1939} else if (u->is_LoadStore()) {1940if (trace) { tty->print("XXXXXX pushing memory"); u->find_out_with(Op_SCMemProj)->dump(); }1941memories.push(u->find_out_with(Op_SCMemProj));1942} else if (u->is_MergeMem() && u->as_MergeMem()->memory_at(Compile::AliasIdxRaw) == m) {1943if (trace) { tty->print("XXXXXX pushing memory"); u->dump(); }1944memories.push(u);1945} else if (u->is_Phi()) {1946assert(u->bottom_type() == Type::MEMORY, "");1947if (u->adr_type() == TypeRawPtr::BOTTOM || u->adr_type() == TypePtr::BOTTOM) {1948assert(controls.member(u->in(0)), "");1949if (trace) { tty->print("XXXXXX pushing memory"); u->dump(); }1950memories.push(u);1951}1952} else if (u->is_SafePoint() || u->is_MemBar()) {1953for (DUIterator_Fast jmax, j = u->fast_outs(jmax); j < jmax; j++) {1954Node* uu = u->fast_out(j);1955if (uu->bottom_type() == Type::MEMORY) {1956if (trace) { tty->print("XXXXXX pushing memory"); uu->dump(); }1957memories.push(uu);1958}1959}1960}1961}1962}1963for (uint next2 = 0; next2 < controls.size(); next2++) {1964Node *m = controls.at(next2);1965if (m->is_Region()) {1966bool all_in = true;1967for (uint i = 1; i < m->req(); i++) {1968if (!controls.member(m->in(i))) {1969all_in = false;1970break;1971}1972}1973if (trace) { tty->print("XXX verifying %s", all_in ? "all in" : ""); m->dump(); }1974bool found_phi = false;1975for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax && !found_phi; j++) {1976Node* u = m->fast_out(j);1977if (u->is_Phi() && memories.member(u)) {1978found_phi = true;1979for (uint i = 1; i < u->req() && found_phi; i++) {1980Node* k = u->in(i);1981if (memories.member(k) != controls.member(m->in(i))) {1982found_phi = false;1983}1984}1985}1986}1987assert(found_phi || all_in, "");1988}1989}1990controls.clear();1991memories.clear();1992}1993for( uint i = 0; i < n->len(); ++i ) {1994Node *m = n->in(i);1995if (m != NULL) {1996nodes.push(m);1997}1998}1999}2000}2001#endif20022003ShenandoahIUBarrierNode::ShenandoahIUBarrierNode(Node* val) : Node(NULL, val) {2004ShenandoahBarrierSetC2::bsc2()->state()->add_iu_barrier(this);2005}20062007const Type* ShenandoahIUBarrierNode::bottom_type() const {2008if (in(1) == NULL || in(1)->is_top()) {2009return Type::TOP;2010}2011const Type* t = in(1)->bottom_type();2012if (t == TypePtr::NULL_PTR) {2013return t;2014}2015return t->is_oopptr();2016}20172018const Type* ShenandoahIUBarrierNode::Value(PhaseGVN* phase) const {2019if (in(1) == NULL) {2020return Type::TOP;2021}2022const Type* t = phase->type(in(1));2023if (t == Type::TOP) {2024return Type::TOP;2025}2026if (t == TypePtr::NULL_PTR) {2027return t;2028}2029return t->is_oopptr();2030}20312032int ShenandoahIUBarrierNode::needed(Node* n) {2033if (n == NULL ||2034n->is_Allocate() ||2035n->Opcode() == Op_ShenandoahIUBarrier ||2036n->bottom_type() == TypePtr::NULL_PTR ||2037(n->bottom_type()->make_oopptr() != NULL && n->bottom_type()->make_oopptr()->const_oop() != NULL)) {2038return NotNeeded;2039}2040if (n->is_Phi() ||2041n->is_CMove()) {2042return MaybeNeeded;2043}2044return Needed;2045}20462047Node* ShenandoahIUBarrierNode::next(Node* n) {2048for (;;) {2049if (n == NULL) {2050return n;2051} else if (n->bottom_type() == TypePtr::NULL_PTR) {2052return n;2053} else if (n->bottom_type()->make_oopptr() != NULL && n->bottom_type()->make_oopptr()->const_oop() != NULL) {2054return n;2055} else if (n->is_ConstraintCast() ||2056n->Opcode() == Op_DecodeN ||2057n->Opcode() == Op_EncodeP) {2058n = n->in(1);2059} else if (n->is_Proj()) {2060n = n->in(0);2061} else {2062return n;2063}2064}2065ShouldNotReachHere();2066return NULL;2067}20682069Node* ShenandoahIUBarrierNode::Identity(PhaseGVN* phase) {2070PhaseIterGVN* igvn = phase->is_IterGVN();20712072Node* n = next(in(1));20732074int cont = needed(n);20752076if (cont == NotNeeded) {2077return in(1);2078} else if (cont == MaybeNeeded) {2079if (igvn == NULL) {2080phase->record_for_igvn(this);2081return this;2082} else {2083ResourceMark rm;2084Unique_Node_List wq;2085uint wq_i = 0;20862087for (;;) {2088if (n->is_Phi()) {2089for (uint i = 1; i < n->req(); i++) {2090Node* m = n->in(i);2091if (m != NULL) {2092wq.push(m);2093}2094}2095} else {2096assert(n->is_CMove(), "nothing else here");2097Node* m = n->in(CMoveNode::IfFalse);2098wq.push(m);2099m = n->in(CMoveNode::IfTrue);2100wq.push(m);2101}2102Node* orig_n = NULL;2103do {2104if (wq_i >= wq.size()) {2105return in(1);2106}2107n = wq.at(wq_i);2108wq_i++;2109orig_n = n;2110n = next(n);2111cont = needed(n);2112if (cont == Needed) {2113return this;2114}2115} while (cont != MaybeNeeded || (orig_n != n && wq.member(n)));2116}2117}2118}21192120return this;2121}21222123#ifdef ASSERT2124static bool has_never_branch(Node* root) {2125for (uint i = 1; i < root->req(); i++) {2126Node* in = root->in(i);2127if (in != NULL && in->Opcode() == Op_Halt && in->in(0)->is_Proj() && in->in(0)->in(0)->Opcode() == Op_NeverBranch) {2128return true;2129}2130}2131return false;2132}2133#endif21342135void MemoryGraphFixer::collect_memory_nodes() {2136Node_Stack stack(0);2137VectorSet visited;2138Node_List regions;21392140// Walk the raw memory graph and create a mapping from CFG node to2141// memory node. Exclude phis for now.2142stack.push(_phase->C->root(), 1);2143do {2144Node* n = stack.node();2145int opc = n->Opcode();2146uint i = stack.index();2147if (i < n->req()) {2148Node* mem = NULL;2149if (opc == Op_Root) {2150Node* in = n->in(i);2151int in_opc = in->Opcode();2152if (in_opc == Op_Return || in_opc == Op_Rethrow) {2153mem = in->in(TypeFunc::Memory);2154} else if (in_opc == Op_Halt) {2155if (in->in(0)->is_Region()) {2156Node* r = in->in(0);2157for (uint j = 1; j < r->req(); j++) {2158assert(r->in(j)->Opcode() != Op_NeverBranch, "");2159}2160} else {2161Node* proj = in->in(0);2162assert(proj->is_Proj(), "");2163Node* in = proj->in(0);2164assert(in->is_CallStaticJava() || in->Opcode() == Op_NeverBranch || in->Opcode() == Op_Catch || proj->is_IfProj(), "");2165if (in->is_CallStaticJava()) {2166mem = in->in(TypeFunc::Memory);2167} else if (in->Opcode() == Op_Catch) {2168Node* call = in->in(0)->in(0);2169assert(call->is_Call(), "");2170mem = call->in(TypeFunc::Memory);2171} else if (in->Opcode() == Op_NeverBranch) {2172Node* head = in->in(0);2173assert(head->is_Region(), "unexpected infinite loop graph shape");21742175Node* phi_mem = NULL;2176for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) {2177Node* u = head->fast_out(j);2178if (u->is_Phi() && u->bottom_type() == Type::MEMORY) {2179if (_phase->C->get_alias_index(u->adr_type()) == _alias) {2180assert(phi_mem == NULL || phi_mem->adr_type() == TypePtr::BOTTOM, "");2181phi_mem = u;2182} else if (u->adr_type() == TypePtr::BOTTOM) {2183assert(phi_mem == NULL || _phase->C->get_alias_index(phi_mem->adr_type()) == _alias, "");2184if (phi_mem == NULL) {2185phi_mem = u;2186}2187}2188}2189}2190if (phi_mem == NULL) {2191for (uint j = 1; j < head->req(); j++) {2192Node* tail = head->in(j);2193if (!_phase->is_dominator(head, tail)) {2194continue;2195}2196Node* c = tail;2197while (c != head) {2198if (c->is_SafePoint() && !c->is_CallLeaf()) {2199Node* m =c->in(TypeFunc::Memory);2200if (m->is_MergeMem()) {2201m = m->as_MergeMem()->memory_at(_alias);2202}2203assert(mem == NULL || mem == m, "several memory states");2204mem = m;2205}2206c = _phase->idom(c);2207}2208assert(mem != NULL, "should have found safepoint");2209}2210assert(mem != NULL, "should have found safepoint");2211} else {2212mem = phi_mem;2213}2214}2215}2216} else {2217#ifdef ASSERT2218n->dump();2219in->dump();2220#endif2221ShouldNotReachHere();2222}2223} else {2224assert(n->is_Phi() && n->bottom_type() == Type::MEMORY, "");2225assert(n->adr_type() == TypePtr::BOTTOM || _phase->C->get_alias_index(n->adr_type()) == _alias, "");2226mem = n->in(i);2227}2228i++;2229stack.set_index(i);2230if (mem == NULL) {2231continue;2232}2233for (;;) {2234if (visited.test_set(mem->_idx) || mem->is_Start()) {2235break;2236}2237if (mem->is_Phi()) {2238stack.push(mem, 2);2239mem = mem->in(1);2240} else if (mem->is_Proj()) {2241stack.push(mem, mem->req());2242mem = mem->in(0);2243} else if (mem->is_SafePoint() || mem->is_MemBar()) {2244mem = mem->in(TypeFunc::Memory);2245} else if (mem->is_MergeMem()) {2246MergeMemNode* mm = mem->as_MergeMem();2247mem = mm->memory_at(_alias);2248} else if (mem->is_Store() || mem->is_LoadStore() || mem->is_ClearArray()) {2249assert(_alias == Compile::AliasIdxRaw, "");2250stack.push(mem, mem->req());2251mem = mem->in(MemNode::Memory);2252} else {2253#ifdef ASSERT2254mem->dump();2255#endif2256ShouldNotReachHere();2257}2258}2259} else {2260if (n->is_Phi()) {2261// Nothing2262} else if (!n->is_Root()) {2263Node* c = get_ctrl(n);2264_memory_nodes.map(c->_idx, n);2265}2266stack.pop();2267}2268} while(stack.is_nonempty());22692270// Iterate over CFG nodes in rpo and propagate memory state to2271// compute memory state at regions, creating new phis if needed.2272Node_List rpo_list;2273visited.clear();2274_phase->rpo(_phase->C->root(), stack, visited, rpo_list);2275Node* root = rpo_list.pop();2276assert(root == _phase->C->root(), "");22772278const bool trace = false;2279#ifdef ASSERT2280if (trace) {2281for (int i = rpo_list.size() - 1; i >= 0; i--) {2282Node* c = rpo_list.at(i);2283if (_memory_nodes[c->_idx] != NULL) {2284tty->print("X %d", c->_idx); _memory_nodes[c->_idx]->dump();2285}2286}2287}2288#endif2289uint last = _phase->C->unique();22902291#ifdef ASSERT2292uint16_t max_depth = 0;2293for (LoopTreeIterator iter(_phase->ltree_root()); !iter.done(); iter.next()) {2294IdealLoopTree* lpt = iter.current();2295max_depth = MAX2(max_depth, lpt->_nest);2296}2297#endif22982299bool progress = true;2300int iteration = 0;2301Node_List dead_phis;2302while (progress) {2303progress = false;2304iteration++;2305assert(iteration <= 2+max_depth || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "");2306if (trace) { tty->print_cr("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); }23072308for (int i = rpo_list.size() - 1; i >= 0; i--) {2309Node* c = rpo_list.at(i);23102311Node* prev_mem = _memory_nodes[c->_idx];2312if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) {2313Node* prev_region = regions[c->_idx];2314Node* unique = NULL;2315for (uint j = 1; j < c->req() && unique != NodeSentinel; j++) {2316Node* m = _memory_nodes[c->in(j)->_idx];2317assert(m != NULL || (c->is_Loop() && j == LoopNode::LoopBackControl && iteration == 1) || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "expect memory state");2318if (m != NULL) {2319if (m == prev_region && ((c->is_Loop() && j == LoopNode::LoopBackControl) || (prev_region->is_Phi() && prev_region->in(0) == c))) {2320assert(c->is_Loop() && j == LoopNode::LoopBackControl || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "");2321// continue2322} else if (unique == NULL) {2323unique = m;2324} else if (m == unique) {2325// continue2326} else {2327unique = NodeSentinel;2328}2329}2330}2331assert(unique != NULL, "empty phi???");2332if (unique != NodeSentinel) {2333if (prev_region != NULL && prev_region->is_Phi() && prev_region->in(0) == c) {2334dead_phis.push(prev_region);2335}2336regions.map(c->_idx, unique);2337} else {2338Node* phi = NULL;2339if (prev_region != NULL && prev_region->is_Phi() && prev_region->in(0) == c && prev_region->_idx >= last) {2340phi = prev_region;2341for (uint k = 1; k < c->req(); k++) {2342Node* m = _memory_nodes[c->in(k)->_idx];2343assert(m != NULL, "expect memory state");2344phi->set_req(k, m);2345}2346} else {2347for (DUIterator_Fast jmax, j = c->fast_outs(jmax); j < jmax && phi == NULL; j++) {2348Node* u = c->fast_out(j);2349if (u->is_Phi() && u->bottom_type() == Type::MEMORY &&2350(u->adr_type() == TypePtr::BOTTOM || _phase->C->get_alias_index(u->adr_type()) == _alias)) {2351phi = u;2352for (uint k = 1; k < c->req() && phi != NULL; k++) {2353Node* m = _memory_nodes[c->in(k)->_idx];2354assert(m != NULL, "expect memory state");2355if (u->in(k) != m) {2356phi = NodeSentinel;2357}2358}2359}2360}2361if (phi == NodeSentinel) {2362phi = new PhiNode(c, Type::MEMORY, _phase->C->get_adr_type(_alias));2363for (uint k = 1; k < c->req(); k++) {2364Node* m = _memory_nodes[c->in(k)->_idx];2365assert(m != NULL, "expect memory state");2366phi->init_req(k, m);2367}2368}2369}2370if (phi != NULL) {2371regions.map(c->_idx, phi);2372} else {2373assert(c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state");2374}2375}2376Node* current_region = regions[c->_idx];2377if (current_region != prev_region) {2378progress = true;2379if (prev_region == prev_mem) {2380_memory_nodes.map(c->_idx, current_region);2381}2382}2383} else if (prev_mem == NULL || prev_mem->is_Phi() || ctrl_or_self(prev_mem) != c) {2384Node* m = _memory_nodes[_phase->idom(c)->_idx];2385assert(m != NULL || c->Opcode() == Op_Halt, "expect memory state");2386if (m != prev_mem) {2387_memory_nodes.map(c->_idx, m);2388progress = true;2389}2390}2391#ifdef ASSERT2392if (trace) { tty->print("X %d", c->_idx); _memory_nodes[c->_idx]->dump(); }2393#endif2394}2395}23962397// Replace existing phi with computed memory state for that region2398// if different (could be a new phi or a dominating memory node if2399// that phi was found to be useless).2400while (dead_phis.size() > 0) {2401Node* n = dead_phis.pop();2402n->replace_by(_phase->C->top());2403n->destruct(&_phase->igvn());2404}2405for (int i = rpo_list.size() - 1; i >= 0; i--) {2406Node* c = rpo_list.at(i);2407if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) {2408Node* n = regions[c->_idx];2409assert(n != NULL || c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state");2410if (n != NULL && n->is_Phi() && n->_idx >= last && n->in(0) == c) {2411_phase->register_new_node(n, c);2412}2413}2414}2415for (int i = rpo_list.size() - 1; i >= 0; i--) {2416Node* c = rpo_list.at(i);2417if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) {2418Node* n = regions[c->_idx];2419assert(n != NULL || c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state");2420for (DUIterator_Fast imax, i = c->fast_outs(imax); i < imax; i++) {2421Node* u = c->fast_out(i);2422if (u->is_Phi() && u->bottom_type() == Type::MEMORY &&2423u != n) {2424assert(c->unique_ctrl_out()->Opcode() != Op_Halt, "expected memory state");2425if (u->adr_type() == TypePtr::BOTTOM) {2426fix_memory_uses(u, n, n, c);2427} else if (_phase->C->get_alias_index(u->adr_type()) == _alias) {2428_phase->lazy_replace(u, n);2429--i; --imax;2430}2431}2432}2433}2434}2435}24362437Node* MemoryGraphFixer::get_ctrl(Node* n) const {2438Node* c = _phase->get_ctrl(n);2439if (n->is_Proj() && n->in(0) != NULL && n->in(0)->is_Call()) {2440assert(c == n->in(0), "");2441CallNode* call = c->as_Call();2442CallProjections projs;2443call->extract_projections(&projs, true, false);2444if (projs.catchall_memproj != NULL) {2445if (projs.fallthrough_memproj == n) {2446c = projs.fallthrough_catchproj;2447} else {2448assert(projs.catchall_memproj == n, "");2449c = projs.catchall_catchproj;2450}2451}2452}2453return c;2454}24552456Node* MemoryGraphFixer::ctrl_or_self(Node* n) const {2457if (_phase->has_ctrl(n))2458return get_ctrl(n);2459else {2460assert (n->is_CFG(), "must be a CFG node");2461return n;2462}2463}24642465bool MemoryGraphFixer::mem_is_valid(Node* m, Node* c) const {2466return m != NULL && get_ctrl(m) == c;2467}24682469Node* MemoryGraphFixer::find_mem(Node* ctrl, Node* n) const {2470assert(n == NULL || _phase->ctrl_or_self(n) == ctrl, "");2471assert(!ctrl->is_Call() || ctrl == n, "projection expected");2472#ifdef ASSERT2473if ((ctrl->is_Proj() && ctrl->in(0)->is_Call()) ||2474(ctrl->is_Catch() && ctrl->in(0)->in(0)->is_Call())) {2475CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_Call() : ctrl->in(0)->in(0)->as_Call();2476int mems = 0;2477for (DUIterator_Fast imax, i = call->fast_outs(imax); i < imax; i++) {2478Node* u = call->fast_out(i);2479if (u->bottom_type() == Type::MEMORY) {2480mems++;2481}2482}2483assert(mems <= 1, "No node right after call if multiple mem projections");2484}2485#endif2486Node* mem = _memory_nodes[ctrl->_idx];2487Node* c = ctrl;2488while (!mem_is_valid(mem, c) &&2489(!c->is_CatchProj() || mem == NULL || c->in(0)->in(0)->in(0) != get_ctrl(mem))) {2490c = _phase->idom(c);2491mem = _memory_nodes[c->_idx];2492}2493if (n != NULL && mem_is_valid(mem, c)) {2494while (!ShenandoahBarrierC2Support::is_dominator_same_ctrl(c, mem, n, _phase) && _phase->ctrl_or_self(mem) == ctrl) {2495mem = next_mem(mem, _alias);2496}2497if (mem->is_MergeMem()) {2498mem = mem->as_MergeMem()->memory_at(_alias);2499}2500if (!mem_is_valid(mem, c)) {2501do {2502c = _phase->idom(c);2503mem = _memory_nodes[c->_idx];2504} while (!mem_is_valid(mem, c) &&2505(!c->is_CatchProj() || mem == NULL || c->in(0)->in(0)->in(0) != get_ctrl(mem)));2506}2507}2508assert(mem->bottom_type() == Type::MEMORY, "");2509return mem;2510}25112512bool MemoryGraphFixer::has_mem_phi(Node* region) const {2513for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {2514Node* use = region->fast_out(i);2515if (use->is_Phi() && use->bottom_type() == Type::MEMORY &&2516(_phase->C->get_alias_index(use->adr_type()) == _alias)) {2517return true;2518}2519}2520return false;2521}25222523void MemoryGraphFixer::fix_mem(Node* ctrl, Node* new_ctrl, Node* mem, Node* mem_for_ctrl, Node* new_mem, Unique_Node_List& uses) {2524assert(_phase->ctrl_or_self(new_mem) == new_ctrl, "");2525const bool trace = false;2526DEBUG_ONLY(if (trace) { tty->print("ZZZ control is"); ctrl->dump(); });2527DEBUG_ONLY(if (trace) { tty->print("ZZZ mem is"); mem->dump(); });2528GrowableArray<Node*> phis;2529if (mem_for_ctrl != mem) {2530Node* old = mem_for_ctrl;2531Node* prev = NULL;2532while (old != mem) {2533prev = old;2534if (old->is_Store() || old->is_ClearArray() || old->is_LoadStore()) {2535assert(_alias == Compile::AliasIdxRaw, "");2536old = old->in(MemNode::Memory);2537} else if (old->Opcode() == Op_SCMemProj) {2538assert(_alias == Compile::AliasIdxRaw, "");2539old = old->in(0);2540} else {2541ShouldNotReachHere();2542}2543}2544assert(prev != NULL, "");2545if (new_ctrl != ctrl) {2546_memory_nodes.map(ctrl->_idx, mem);2547_memory_nodes.map(new_ctrl->_idx, mem_for_ctrl);2548}2549uint input = (uint)MemNode::Memory;2550_phase->igvn().replace_input_of(prev, input, new_mem);2551} else {2552uses.clear();2553_memory_nodes.map(new_ctrl->_idx, new_mem);2554uses.push(new_ctrl);2555for(uint next = 0; next < uses.size(); next++ ) {2556Node *n = uses.at(next);2557assert(n->is_CFG(), "");2558DEBUG_ONLY(if (trace) { tty->print("ZZZ ctrl"); n->dump(); });2559for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {2560Node* u = n->fast_out(i);2561if (!u->is_Root() && u->is_CFG() && u != n) {2562Node* m = _memory_nodes[u->_idx];2563if (u->is_Region() && (!u->is_OuterStripMinedLoop() || _include_lsm) &&2564!has_mem_phi(u) &&2565u->unique_ctrl_out()->Opcode() != Op_Halt) {2566DEBUG_ONLY(if (trace) { tty->print("ZZZ region"); u->dump(); });2567DEBUG_ONLY(if (trace && m != NULL) { tty->print("ZZZ mem"); m->dump(); });25682569if (!mem_is_valid(m, u) || !m->is_Phi()) {2570bool push = true;2571bool create_phi = true;2572if (_phase->is_dominator(new_ctrl, u)) {2573create_phi = false;2574}2575if (create_phi) {2576Node* phi = new PhiNode(u, Type::MEMORY, _phase->C->get_adr_type(_alias));2577_phase->register_new_node(phi, u);2578phis.push(phi);2579DEBUG_ONLY(if (trace) { tty->print("ZZZ new phi"); phi->dump(); });2580if (!mem_is_valid(m, u)) {2581DEBUG_ONLY(if (trace) { tty->print("ZZZ setting mem"); phi->dump(); });2582_memory_nodes.map(u->_idx, phi);2583} else {2584DEBUG_ONLY(if (trace) { tty->print("ZZZ NOT setting mem"); m->dump(); });2585for (;;) {2586assert(m->is_Mem() || m->is_LoadStore() || m->is_Proj(), "");2587Node* next = NULL;2588if (m->is_Proj()) {2589next = m->in(0);2590} else {2591assert(m->is_Mem() || m->is_LoadStore(), "");2592assert(_alias == Compile::AliasIdxRaw, "");2593next = m->in(MemNode::Memory);2594}2595if (_phase->get_ctrl(next) != u) {2596break;2597}2598if (next->is_MergeMem()) {2599assert(_phase->get_ctrl(next->as_MergeMem()->memory_at(_alias)) != u, "");2600break;2601}2602if (next->is_Phi()) {2603assert(next->adr_type() == TypePtr::BOTTOM && next->in(0) == u, "");2604break;2605}2606m = next;2607}26082609DEBUG_ONLY(if (trace) { tty->print("ZZZ setting to phi"); m->dump(); });2610assert(m->is_Mem() || m->is_LoadStore(), "");2611uint input = (uint)MemNode::Memory;2612_phase->igvn().replace_input_of(m, input, phi);2613push = false;2614}2615} else {2616DEBUG_ONLY(if (trace) { tty->print("ZZZ skipping region"); u->dump(); });2617}2618if (push) {2619uses.push(u);2620}2621}2622} else if (!mem_is_valid(m, u) &&2623!(u->Opcode() == Op_CProj && u->in(0)->Opcode() == Op_NeverBranch && u->as_Proj()->_con == 1)) {2624uses.push(u);2625}2626}2627}2628}2629for (int i = 0; i < phis.length(); i++) {2630Node* n = phis.at(i);2631Node* r = n->in(0);2632DEBUG_ONLY(if (trace) { tty->print("ZZZ fixing new phi"); n->dump(); });2633for (uint j = 1; j < n->req(); j++) {2634Node* m = find_mem(r->in(j), NULL);2635_phase->igvn().replace_input_of(n, j, m);2636DEBUG_ONLY(if (trace) { tty->print("ZZZ fixing new phi: %d", j); m->dump(); });2637}2638}2639}2640uint last = _phase->C->unique();2641MergeMemNode* mm = NULL;2642int alias = _alias;2643DEBUG_ONLY(if (trace) { tty->print("ZZZ raw mem is"); mem->dump(); });2644// Process loads first to not miss an anti-dependency: if the memory2645// edge of a store is updated before a load is processed then an2646// anti-dependency may be missed.2647for (DUIterator i = mem->outs(); mem->has_out(i); i++) {2648Node* u = mem->out(i);2649if (u->_idx < last && u->is_Load() && _phase->C->get_alias_index(u->adr_type()) == alias) {2650Node* m = find_mem(_phase->get_ctrl(u), u);2651if (m != mem) {2652DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });2653_phase->igvn().replace_input_of(u, MemNode::Memory, m);2654--i;2655}2656}2657}2658for (DUIterator i = mem->outs(); mem->has_out(i); i++) {2659Node* u = mem->out(i);2660if (u->_idx < last) {2661if (u->is_Mem()) {2662if (_phase->C->get_alias_index(u->adr_type()) == alias) {2663Node* m = find_mem(_phase->get_ctrl(u), u);2664if (m != mem) {2665DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });2666_phase->igvn().replace_input_of(u, MemNode::Memory, m);2667--i;2668}2669}2670} else if (u->is_MergeMem()) {2671MergeMemNode* u_mm = u->as_MergeMem();2672if (u_mm->memory_at(alias) == mem) {2673MergeMemNode* newmm = NULL;2674for (DUIterator_Fast jmax, j = u->fast_outs(jmax); j < jmax; j++) {2675Node* uu = u->fast_out(j);2676assert(!uu->is_MergeMem(), "chain of MergeMems?");2677if (uu->is_Phi()) {2678assert(uu->adr_type() == TypePtr::BOTTOM, "");2679Node* region = uu->in(0);2680int nb = 0;2681for (uint k = 1; k < uu->req(); k++) {2682if (uu->in(k) == u) {2683Node* m = find_mem(region->in(k), NULL);2684if (m != mem) {2685DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of phi %d", k); uu->dump(); });2686newmm = clone_merge_mem(u, mem, m, _phase->ctrl_or_self(m), i);2687if (newmm != u) {2688_phase->igvn().replace_input_of(uu, k, newmm);2689nb++;2690--jmax;2691}2692}2693}2694}2695if (nb > 0) {2696--j;2697}2698} else {2699Node* m = find_mem(_phase->ctrl_or_self(uu), uu);2700if (m != mem) {2701DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); uu->dump(); });2702newmm = clone_merge_mem(u, mem, m, _phase->ctrl_or_self(m), i);2703if (newmm != u) {2704_phase->igvn().replace_input_of(uu, uu->find_edge(u), newmm);2705--j, --jmax;2706}2707}2708}2709}2710}2711} else if (u->is_Phi()) {2712assert(u->bottom_type() == Type::MEMORY, "what else?");2713if (_phase->C->get_alias_index(u->adr_type()) == alias || u->adr_type() == TypePtr::BOTTOM) {2714Node* region = u->in(0);2715bool replaced = false;2716for (uint j = 1; j < u->req(); j++) {2717if (u->in(j) == mem) {2718Node* m = find_mem(region->in(j), NULL);2719Node* nnew = m;2720if (m != mem) {2721if (u->adr_type() == TypePtr::BOTTOM) {2722mm = allocate_merge_mem(mem, m, _phase->ctrl_or_self(m));2723nnew = mm;2724}2725DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of phi %d", j); u->dump(); });2726_phase->igvn().replace_input_of(u, j, nnew);2727replaced = true;2728}2729}2730}2731if (replaced) {2732--i;2733}2734}2735} else if ((u->adr_type() == TypePtr::BOTTOM && u->Opcode() != Op_StrInflatedCopy) ||2736u->adr_type() == NULL) {2737assert(u->adr_type() != NULL ||2738u->Opcode() == Op_Rethrow ||2739u->Opcode() == Op_Return ||2740u->Opcode() == Op_SafePoint ||2741(u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) ||2742(u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) ||2743u->Opcode() == Op_CallLeaf, "");2744Node* m = find_mem(_phase->ctrl_or_self(u), u);2745if (m != mem) {2746mm = allocate_merge_mem(mem, m, _phase->get_ctrl(m));2747_phase->igvn().replace_input_of(u, u->find_edge(mem), mm);2748--i;2749}2750} else if (_phase->C->get_alias_index(u->adr_type()) == alias) {2751Node* m = find_mem(_phase->ctrl_or_self(u), u);2752if (m != mem) {2753DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });2754_phase->igvn().replace_input_of(u, u->find_edge(mem), m);2755--i;2756}2757} else if (u->adr_type() != TypePtr::BOTTOM &&2758_memory_nodes[_phase->ctrl_or_self(u)->_idx] == u) {2759Node* m = find_mem(_phase->ctrl_or_self(u), u);2760assert(m != mem, "");2761// u is on the wrong slice...2762assert(u->is_ClearArray(), "");2763DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });2764_phase->igvn().replace_input_of(u, u->find_edge(mem), m);2765--i;2766}2767}2768}2769#ifdef ASSERT2770assert(new_mem->outcnt() > 0, "");2771for (int i = 0; i < phis.length(); i++) {2772Node* n = phis.at(i);2773assert(n->outcnt() > 0, "new phi must have uses now");2774}2775#endif2776}27772778MergeMemNode* MemoryGraphFixer::allocate_merge_mem(Node* mem, Node* rep_proj, Node* rep_ctrl) const {2779MergeMemNode* mm = MergeMemNode::make(mem);2780mm->set_memory_at(_alias, rep_proj);2781_phase->register_new_node(mm, rep_ctrl);2782return mm;2783}27842785MergeMemNode* MemoryGraphFixer::clone_merge_mem(Node* u, Node* mem, Node* rep_proj, Node* rep_ctrl, DUIterator& i) const {2786MergeMemNode* newmm = NULL;2787MergeMemNode* u_mm = u->as_MergeMem();2788Node* c = _phase->get_ctrl(u);2789if (_phase->is_dominator(c, rep_ctrl)) {2790c = rep_ctrl;2791} else {2792assert(_phase->is_dominator(rep_ctrl, c), "one must dominate the other");2793}2794if (u->outcnt() == 1) {2795if (u->req() > (uint)_alias && u->in(_alias) == mem) {2796_phase->igvn().replace_input_of(u, _alias, rep_proj);2797--i;2798} else {2799_phase->igvn().rehash_node_delayed(u);2800u_mm->set_memory_at(_alias, rep_proj);2801}2802newmm = u_mm;2803_phase->set_ctrl_and_loop(u, c);2804} else {2805// can't simply clone u and then change one of its input because2806// it adds and then removes an edge which messes with the2807// DUIterator2808newmm = MergeMemNode::make(u_mm->base_memory());2809for (uint j = 0; j < u->req(); j++) {2810if (j < newmm->req()) {2811if (j == (uint)_alias) {2812newmm->set_req(j, rep_proj);2813} else if (newmm->in(j) != u->in(j)) {2814newmm->set_req(j, u->in(j));2815}2816} else if (j == (uint)_alias) {2817newmm->add_req(rep_proj);2818} else {2819newmm->add_req(u->in(j));2820}2821}2822if ((uint)_alias >= u->req()) {2823newmm->set_memory_at(_alias, rep_proj);2824}2825_phase->register_new_node(newmm, c);2826}2827return newmm;2828}28292830bool MemoryGraphFixer::should_process_phi(Node* phi) const {2831if (phi->adr_type() == TypePtr::BOTTOM) {2832Node* region = phi->in(0);2833for (DUIterator_Fast jmax, j = region->fast_outs(jmax); j < jmax; j++) {2834Node* uu = region->fast_out(j);2835if (uu->is_Phi() && uu != phi && uu->bottom_type() == Type::MEMORY && _phase->C->get_alias_index(uu->adr_type()) == _alias) {2836return false;2837}2838}2839return true;2840}2841return _phase->C->get_alias_index(phi->adr_type()) == _alias;2842}28432844void MemoryGraphFixer::fix_memory_uses(Node* mem, Node* replacement, Node* rep_proj, Node* rep_ctrl) const {2845uint last = _phase-> C->unique();2846MergeMemNode* mm = NULL;2847assert(mem->bottom_type() == Type::MEMORY, "");2848for (DUIterator i = mem->outs(); mem->has_out(i); i++) {2849Node* u = mem->out(i);2850if (u != replacement && u->_idx < last) {2851if (u->is_MergeMem()) {2852MergeMemNode* u_mm = u->as_MergeMem();2853if (u_mm->memory_at(_alias) == mem) {2854MergeMemNode* newmm = NULL;2855for (DUIterator_Fast jmax, j = u->fast_outs(jmax); j < jmax; j++) {2856Node* uu = u->fast_out(j);2857assert(!uu->is_MergeMem(), "chain of MergeMems?");2858if (uu->is_Phi()) {2859if (should_process_phi(uu)) {2860Node* region = uu->in(0);2861int nb = 0;2862for (uint k = 1; k < uu->req(); k++) {2863if (uu->in(k) == u && _phase->is_dominator(rep_ctrl, region->in(k))) {2864if (newmm == NULL) {2865newmm = clone_merge_mem(u, mem, rep_proj, rep_ctrl, i);2866}2867if (newmm != u) {2868_phase->igvn().replace_input_of(uu, k, newmm);2869nb++;2870--jmax;2871}2872}2873}2874if (nb > 0) {2875--j;2876}2877}2878} else {2879if (rep_ctrl != uu && ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(uu), replacement, uu, _phase)) {2880if (newmm == NULL) {2881newmm = clone_merge_mem(u, mem, rep_proj, rep_ctrl, i);2882}2883if (newmm != u) {2884_phase->igvn().replace_input_of(uu, uu->find_edge(u), newmm);2885--j, --jmax;2886}2887}2888}2889}2890}2891} else if (u->is_Phi()) {2892assert(u->bottom_type() == Type::MEMORY, "what else?");2893Node* region = u->in(0);2894if (should_process_phi(u)) {2895bool replaced = false;2896for (uint j = 1; j < u->req(); j++) {2897if (u->in(j) == mem && _phase->is_dominator(rep_ctrl, region->in(j))) {2898Node* nnew = rep_proj;2899if (u->adr_type() == TypePtr::BOTTOM) {2900if (mm == NULL) {2901mm = allocate_merge_mem(mem, rep_proj, rep_ctrl);2902}2903nnew = mm;2904}2905_phase->igvn().replace_input_of(u, j, nnew);2906replaced = true;2907}2908}2909if (replaced) {2910--i;2911}29122913}2914} else if ((u->adr_type() == TypePtr::BOTTOM && u->Opcode() != Op_StrInflatedCopy) ||2915u->adr_type() == NULL) {2916assert(u->adr_type() != NULL ||2917u->Opcode() == Op_Rethrow ||2918u->Opcode() == Op_Return ||2919u->Opcode() == Op_SafePoint ||2920u->Opcode() == Op_StoreIConditional ||2921u->Opcode() == Op_StoreLConditional ||2922(u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) ||2923(u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) ||2924u->Opcode() == Op_CallLeaf, "%s", u->Name());2925if (ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {2926if (mm == NULL) {2927mm = allocate_merge_mem(mem, rep_proj, rep_ctrl);2928}2929_phase->igvn().replace_input_of(u, u->find_edge(mem), mm);2930--i;2931}2932} else if (_phase->C->get_alias_index(u->adr_type()) == _alias) {2933if (ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {2934_phase->igvn().replace_input_of(u, u->find_edge(mem), rep_proj);2935--i;2936}2937}2938}2939}2940}29412942ShenandoahLoadReferenceBarrierNode::ShenandoahLoadReferenceBarrierNode(Node* ctrl, Node* obj, DecoratorSet decorators)2943: Node(ctrl, obj), _decorators(decorators) {2944ShenandoahBarrierSetC2::bsc2()->state()->add_load_reference_barrier(this);2945}29462947DecoratorSet ShenandoahLoadReferenceBarrierNode::decorators() const {2948return _decorators;2949}29502951uint ShenandoahLoadReferenceBarrierNode::size_of() const {2952return sizeof(*this);2953}29542955static DecoratorSet mask_decorators(DecoratorSet decorators) {2956return decorators & (ON_STRONG_OOP_REF | ON_WEAK_OOP_REF | ON_PHANTOM_OOP_REF | ON_UNKNOWN_OOP_REF | IN_NATIVE);2957}29582959uint ShenandoahLoadReferenceBarrierNode::hash() const {2960uint hash = Node::hash();2961hash += mask_decorators(_decorators);2962return hash;2963}29642965bool ShenandoahLoadReferenceBarrierNode::cmp( const Node &n ) const {2966return Node::cmp(n) && n.Opcode() == Op_ShenandoahLoadReferenceBarrier &&2967mask_decorators(_decorators) == mask_decorators(((const ShenandoahLoadReferenceBarrierNode&)n)._decorators);2968}29692970const Type* ShenandoahLoadReferenceBarrierNode::bottom_type() const {2971if (in(ValueIn) == NULL || in(ValueIn)->is_top()) {2972return Type::TOP;2973}2974const Type* t = in(ValueIn)->bottom_type();2975if (t == TypePtr::NULL_PTR) {2976return t;2977}29782979if (ShenandoahBarrierSet::is_strong_access(decorators())) {2980return t;2981}29822983return t->meet(TypePtr::NULL_PTR);2984}29852986const Type* ShenandoahLoadReferenceBarrierNode::Value(PhaseGVN* phase) const {2987// Either input is TOP ==> the result is TOP2988const Type *t2 = phase->type(in(ValueIn));2989if( t2 == Type::TOP ) return Type::TOP;29902991if (t2 == TypePtr::NULL_PTR) {2992return t2;2993}29942995if (ShenandoahBarrierSet::is_strong_access(decorators())) {2996return t2;2997}29982999return t2->meet(TypePtr::NULL_PTR);3000}30013002Node* ShenandoahLoadReferenceBarrierNode::Identity(PhaseGVN* phase) {3003Node* value = in(ValueIn);3004if (!needs_barrier(phase, value)) {3005return value;3006}3007return this;3008}30093010bool ShenandoahLoadReferenceBarrierNode::needs_barrier(PhaseGVN* phase, Node* n) {3011Unique_Node_List visited;3012return needs_barrier_impl(phase, n, visited);3013}30143015bool ShenandoahLoadReferenceBarrierNode::needs_barrier_impl(PhaseGVN* phase, Node* n, Unique_Node_List &visited) {3016if (n == NULL) return false;3017if (visited.member(n)) {3018return false; // Been there.3019}3020visited.push(n);30213022if (n->is_Allocate()) {3023// tty->print_cr("optimize barrier on alloc");3024return false;3025}3026if (n->is_Call()) {3027// tty->print_cr("optimize barrier on call");3028return false;3029}30303031const Type* type = phase->type(n);3032if (type == Type::TOP) {3033return false;3034}3035if (type->make_ptr()->higher_equal(TypePtr::NULL_PTR)) {3036// tty->print_cr("optimize barrier on null");3037return false;3038}3039if (type->make_oopptr() && type->make_oopptr()->const_oop() != NULL) {3040// tty->print_cr("optimize barrier on constant");3041return false;3042}30433044switch (n->Opcode()) {3045case Op_AddP:3046return true; // TODO: Can refine?3047case Op_LoadP:3048case Op_ShenandoahCompareAndExchangeN:3049case Op_ShenandoahCompareAndExchangeP:3050case Op_CompareAndExchangeN:3051case Op_CompareAndExchangeP:3052case Op_GetAndSetN:3053case Op_GetAndSetP:3054return true;3055case Op_Phi: {3056for (uint i = 1; i < n->req(); i++) {3057if (needs_barrier_impl(phase, n->in(i), visited)) return true;3058}3059return false;3060}3061case Op_CheckCastPP:3062case Op_CastPP:3063return needs_barrier_impl(phase, n->in(1), visited);3064case Op_Proj:3065return needs_barrier_impl(phase, n->in(0), visited);3066case Op_ShenandoahLoadReferenceBarrier:3067// tty->print_cr("optimize barrier on barrier");3068return false;3069case Op_Parm:3070// tty->print_cr("optimize barrier on input arg");3071return false;3072case Op_DecodeN:3073case Op_EncodeP:3074return needs_barrier_impl(phase, n->in(1), visited);3075case Op_LoadN:3076return true;3077case Op_CMoveN:3078case Op_CMoveP:3079return needs_barrier_impl(phase, n->in(2), visited) ||3080needs_barrier_impl(phase, n->in(3), visited);3081case Op_ShenandoahIUBarrier:3082return needs_barrier_impl(phase, n->in(1), visited);3083case Op_CreateEx:3084return false;3085default:3086break;3087}3088#ifdef ASSERT3089tty->print("need barrier on?: ");3090tty->print_cr("ins:");3091n->dump(2);3092tty->print_cr("outs:");3093n->dump(-2);3094ShouldNotReachHere();3095#endif3096return true;3097}309830993100