Path: blob/master/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp
66646 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(), ConstraintCastNode::StrongDependency);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) {2172mem = collect_memory_for_infinite_loop(in);2173}2174}2175} else {2176#ifdef ASSERT2177n->dump();2178in->dump();2179#endif2180ShouldNotReachHere();2181}2182} else {2183assert(n->is_Phi() && n->bottom_type() == Type::MEMORY, "");2184assert(n->adr_type() == TypePtr::BOTTOM || _phase->C->get_alias_index(n->adr_type()) == _alias, "");2185mem = n->in(i);2186}2187i++;2188stack.set_index(i);2189if (mem == NULL) {2190continue;2191}2192for (;;) {2193if (visited.test_set(mem->_idx) || mem->is_Start()) {2194break;2195}2196if (mem->is_Phi()) {2197stack.push(mem, 2);2198mem = mem->in(1);2199} else if (mem->is_Proj()) {2200stack.push(mem, mem->req());2201mem = mem->in(0);2202} else if (mem->is_SafePoint() || mem->is_MemBar()) {2203mem = mem->in(TypeFunc::Memory);2204} else if (mem->is_MergeMem()) {2205MergeMemNode* mm = mem->as_MergeMem();2206mem = mm->memory_at(_alias);2207} else if (mem->is_Store() || mem->is_LoadStore() || mem->is_ClearArray()) {2208assert(_alias == Compile::AliasIdxRaw, "");2209stack.push(mem, mem->req());2210mem = mem->in(MemNode::Memory);2211} else {2212#ifdef ASSERT2213mem->dump();2214#endif2215ShouldNotReachHere();2216}2217}2218} else {2219if (n->is_Phi()) {2220// Nothing2221} else if (!n->is_Root()) {2222Node* c = get_ctrl(n);2223_memory_nodes.map(c->_idx, n);2224}2225stack.pop();2226}2227} while(stack.is_nonempty());22282229// Iterate over CFG nodes in rpo and propagate memory state to2230// compute memory state at regions, creating new phis if needed.2231Node_List rpo_list;2232visited.clear();2233_phase->rpo(_phase->C->root(), stack, visited, rpo_list);2234Node* root = rpo_list.pop();2235assert(root == _phase->C->root(), "");22362237const bool trace = false;2238#ifdef ASSERT2239if (trace) {2240for (int i = rpo_list.size() - 1; i >= 0; i--) {2241Node* c = rpo_list.at(i);2242if (_memory_nodes[c->_idx] != NULL) {2243tty->print("X %d", c->_idx); _memory_nodes[c->_idx]->dump();2244}2245}2246}2247#endif2248uint last = _phase->C->unique();22492250#ifdef ASSERT2251uint16_t max_depth = 0;2252for (LoopTreeIterator iter(_phase->ltree_root()); !iter.done(); iter.next()) {2253IdealLoopTree* lpt = iter.current();2254max_depth = MAX2(max_depth, lpt->_nest);2255}2256#endif22572258bool progress = true;2259int iteration = 0;2260Node_List dead_phis;2261while (progress) {2262progress = false;2263iteration++;2264assert(iteration <= 2+max_depth || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "");2265if (trace) { tty->print_cr("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"); }22662267for (int i = rpo_list.size() - 1; i >= 0; i--) {2268Node* c = rpo_list.at(i);22692270Node* prev_mem = _memory_nodes[c->_idx];2271if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) {2272Node* prev_region = regions[c->_idx];2273Node* unique = NULL;2274for (uint j = 1; j < c->req() && unique != NodeSentinel; j++) {2275Node* m = _memory_nodes[c->in(j)->_idx];2276assert(m != NULL || (c->is_Loop() && j == LoopNode::LoopBackControl && iteration == 1) || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "expect memory state");2277if (m != NULL) {2278if (m == prev_region && ((c->is_Loop() && j == LoopNode::LoopBackControl) || (prev_region->is_Phi() && prev_region->in(0) == c))) {2279assert(c->is_Loop() && j == LoopNode::LoopBackControl || _phase->C->has_irreducible_loop() || has_never_branch(_phase->C->root()), "");2280// continue2281} else if (unique == NULL) {2282unique = m;2283} else if (m == unique) {2284// continue2285} else {2286unique = NodeSentinel;2287}2288}2289}2290assert(unique != NULL, "empty phi???");2291if (unique != NodeSentinel) {2292if (prev_region != NULL && prev_region->is_Phi() && prev_region->in(0) == c) {2293dead_phis.push(prev_region);2294}2295regions.map(c->_idx, unique);2296} else {2297Node* phi = NULL;2298if (prev_region != NULL && prev_region->is_Phi() && prev_region->in(0) == c && prev_region->_idx >= last) {2299phi = prev_region;2300for (uint k = 1; k < c->req(); k++) {2301Node* m = _memory_nodes[c->in(k)->_idx];2302assert(m != NULL, "expect memory state");2303phi->set_req(k, m);2304}2305} else {2306for (DUIterator_Fast jmax, j = c->fast_outs(jmax); j < jmax && phi == NULL; j++) {2307Node* u = c->fast_out(j);2308if (u->is_Phi() && u->bottom_type() == Type::MEMORY &&2309(u->adr_type() == TypePtr::BOTTOM || _phase->C->get_alias_index(u->adr_type()) == _alias)) {2310phi = u;2311for (uint k = 1; k < c->req() && phi != NULL; k++) {2312Node* m = _memory_nodes[c->in(k)->_idx];2313assert(m != NULL, "expect memory state");2314if (u->in(k) != m) {2315phi = NodeSentinel;2316}2317}2318}2319}2320if (phi == NodeSentinel) {2321phi = new PhiNode(c, Type::MEMORY, _phase->C->get_adr_type(_alias));2322for (uint k = 1; k < c->req(); k++) {2323Node* m = _memory_nodes[c->in(k)->_idx];2324assert(m != NULL, "expect memory state");2325phi->init_req(k, m);2326}2327}2328}2329if (phi != NULL) {2330regions.map(c->_idx, phi);2331} else {2332assert(c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state");2333}2334}2335Node* current_region = regions[c->_idx];2336if (current_region != prev_region) {2337progress = true;2338if (prev_region == prev_mem) {2339_memory_nodes.map(c->_idx, current_region);2340}2341}2342} else if (prev_mem == NULL || prev_mem->is_Phi() || ctrl_or_self(prev_mem) != c) {2343Node* m = _memory_nodes[_phase->idom(c)->_idx];2344assert(m != NULL || c->Opcode() == Op_Halt, "expect memory state");2345if (m != prev_mem) {2346_memory_nodes.map(c->_idx, m);2347progress = true;2348}2349}2350#ifdef ASSERT2351if (trace) { tty->print("X %d", c->_idx); _memory_nodes[c->_idx]->dump(); }2352#endif2353}2354}23552356// Replace existing phi with computed memory state for that region2357// if different (could be a new phi or a dominating memory node if2358// that phi was found to be useless).2359while (dead_phis.size() > 0) {2360Node* n = dead_phis.pop();2361n->replace_by(_phase->C->top());2362n->destruct(&_phase->igvn());2363}2364for (int i = rpo_list.size() - 1; i >= 0; i--) {2365Node* c = rpo_list.at(i);2366if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) {2367Node* n = regions[c->_idx];2368assert(n != NULL || c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state");2369if (n != NULL && n->is_Phi() && n->_idx >= last && n->in(0) == c) {2370_phase->register_new_node(n, c);2371}2372}2373}2374for (int i = rpo_list.size() - 1; i >= 0; i--) {2375Node* c = rpo_list.at(i);2376if (c->is_Region() && (_include_lsm || !c->is_OuterStripMinedLoop())) {2377Node* n = regions[c->_idx];2378assert(n != NULL || c->unique_ctrl_out()->Opcode() == Op_Halt, "expected memory state");2379for (DUIterator_Fast imax, i = c->fast_outs(imax); i < imax; i++) {2380Node* u = c->fast_out(i);2381if (u->is_Phi() && u->bottom_type() == Type::MEMORY &&2382u != n) {2383assert(c->unique_ctrl_out()->Opcode() != Op_Halt, "expected memory state");2384if (u->adr_type() == TypePtr::BOTTOM) {2385fix_memory_uses(u, n, n, c);2386} else if (_phase->C->get_alias_index(u->adr_type()) == _alias) {2387_phase->lazy_replace(u, n);2388--i; --imax;2389}2390}2391}2392}2393}2394}23952396Node* MemoryGraphFixer::collect_memory_for_infinite_loop(const Node* in) {2397Node* mem = NULL;2398Node* head = in->in(0);2399assert(head->is_Region(), "unexpected infinite loop graph shape");24002401Node* phi_mem = NULL;2402for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) {2403Node* u = head->fast_out(j);2404if (u->is_Phi() && u->bottom_type() == Type::MEMORY) {2405if (_phase->C->get_alias_index(u->adr_type()) == _alias) {2406assert(phi_mem == NULL || phi_mem->adr_type() == TypePtr::BOTTOM, "");2407phi_mem = u;2408} else if (u->adr_type() == TypePtr::BOTTOM) {2409assert(phi_mem == NULL || _phase->C->get_alias_index(phi_mem->adr_type()) == _alias, "");2410if (phi_mem == NULL) {2411phi_mem = u;2412}2413}2414}2415}2416if (phi_mem == NULL) {2417ResourceMark rm;2418Node_Stack stack(0);2419stack.push(head, 1);2420do {2421Node* n = stack.node();2422uint i = stack.index();2423if (i >= n->req()) {2424stack.pop();2425} else {2426stack.set_index(i + 1);2427Node* c = n->in(i);2428assert(c != head, "should have found a safepoint on the way");2429if (stack.size() != 1 || _phase->is_dominator(head, c)) {2430for (;;) {2431if (c->is_Region()) {2432stack.push(c, 1);2433break;2434} else if (c->is_SafePoint() && !c->is_CallLeaf()) {2435Node* m = c->in(TypeFunc::Memory);2436if (m->is_MergeMem()) {2437m = m->as_MergeMem()->memory_at(_alias);2438}2439assert(mem == NULL || mem == m, "several memory states");2440mem = m;2441break;2442} else {2443assert(c != c->in(0), "");2444c = c->in(0);2445}2446}2447}2448}2449} while (stack.size() > 0);2450assert(mem != NULL, "should have found safepoint");2451} else {2452mem = phi_mem;2453}2454return mem;2455}24562457Node* MemoryGraphFixer::get_ctrl(Node* n) const {2458Node* c = _phase->get_ctrl(n);2459if (n->is_Proj() && n->in(0) != NULL && n->in(0)->is_Call()) {2460assert(c == n->in(0), "");2461CallNode* call = c->as_Call();2462CallProjections projs;2463call->extract_projections(&projs, true, false);2464if (projs.catchall_memproj != NULL) {2465if (projs.fallthrough_memproj == n) {2466c = projs.fallthrough_catchproj;2467} else {2468assert(projs.catchall_memproj == n, "");2469c = projs.catchall_catchproj;2470}2471}2472}2473return c;2474}24752476Node* MemoryGraphFixer::ctrl_or_self(Node* n) const {2477if (_phase->has_ctrl(n))2478return get_ctrl(n);2479else {2480assert (n->is_CFG(), "must be a CFG node");2481return n;2482}2483}24842485bool MemoryGraphFixer::mem_is_valid(Node* m, Node* c) const {2486return m != NULL && get_ctrl(m) == c;2487}24882489Node* MemoryGraphFixer::find_mem(Node* ctrl, Node* n) const {2490assert(n == NULL || _phase->ctrl_or_self(n) == ctrl, "");2491assert(!ctrl->is_Call() || ctrl == n, "projection expected");2492#ifdef ASSERT2493if ((ctrl->is_Proj() && ctrl->in(0)->is_Call()) ||2494(ctrl->is_Catch() && ctrl->in(0)->in(0)->is_Call())) {2495CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_Call() : ctrl->in(0)->in(0)->as_Call();2496int mems = 0;2497for (DUIterator_Fast imax, i = call->fast_outs(imax); i < imax; i++) {2498Node* u = call->fast_out(i);2499if (u->bottom_type() == Type::MEMORY) {2500mems++;2501}2502}2503assert(mems <= 1, "No node right after call if multiple mem projections");2504}2505#endif2506Node* mem = _memory_nodes[ctrl->_idx];2507Node* c = ctrl;2508while (!mem_is_valid(mem, c) &&2509(!c->is_CatchProj() || mem == NULL || c->in(0)->in(0)->in(0) != get_ctrl(mem))) {2510c = _phase->idom(c);2511mem = _memory_nodes[c->_idx];2512}2513if (n != NULL && mem_is_valid(mem, c)) {2514while (!ShenandoahBarrierC2Support::is_dominator_same_ctrl(c, mem, n, _phase) && _phase->ctrl_or_self(mem) == ctrl) {2515mem = next_mem(mem, _alias);2516}2517if (mem->is_MergeMem()) {2518mem = mem->as_MergeMem()->memory_at(_alias);2519}2520if (!mem_is_valid(mem, c)) {2521do {2522c = _phase->idom(c);2523mem = _memory_nodes[c->_idx];2524} while (!mem_is_valid(mem, c) &&2525(!c->is_CatchProj() || mem == NULL || c->in(0)->in(0)->in(0) != get_ctrl(mem)));2526}2527}2528assert(mem->bottom_type() == Type::MEMORY, "");2529return mem;2530}25312532bool MemoryGraphFixer::has_mem_phi(Node* region) const {2533for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {2534Node* use = region->fast_out(i);2535if (use->is_Phi() && use->bottom_type() == Type::MEMORY &&2536(_phase->C->get_alias_index(use->adr_type()) == _alias)) {2537return true;2538}2539}2540return false;2541}25422543void MemoryGraphFixer::fix_mem(Node* ctrl, Node* new_ctrl, Node* mem, Node* mem_for_ctrl, Node* new_mem, Unique_Node_List& uses) {2544assert(_phase->ctrl_or_self(new_mem) == new_ctrl, "");2545const bool trace = false;2546DEBUG_ONLY(if (trace) { tty->print("ZZZ control is"); ctrl->dump(); });2547DEBUG_ONLY(if (trace) { tty->print("ZZZ mem is"); mem->dump(); });2548GrowableArray<Node*> phis;2549if (mem_for_ctrl != mem) {2550Node* old = mem_for_ctrl;2551Node* prev = NULL;2552while (old != mem) {2553prev = old;2554if (old->is_Store() || old->is_ClearArray() || old->is_LoadStore()) {2555assert(_alias == Compile::AliasIdxRaw, "");2556old = old->in(MemNode::Memory);2557} else if (old->Opcode() == Op_SCMemProj) {2558assert(_alias == Compile::AliasIdxRaw, "");2559old = old->in(0);2560} else {2561ShouldNotReachHere();2562}2563}2564assert(prev != NULL, "");2565if (new_ctrl != ctrl) {2566_memory_nodes.map(ctrl->_idx, mem);2567_memory_nodes.map(new_ctrl->_idx, mem_for_ctrl);2568}2569uint input = (uint)MemNode::Memory;2570_phase->igvn().replace_input_of(prev, input, new_mem);2571} else {2572uses.clear();2573_memory_nodes.map(new_ctrl->_idx, new_mem);2574uses.push(new_ctrl);2575for(uint next = 0; next < uses.size(); next++ ) {2576Node *n = uses.at(next);2577assert(n->is_CFG(), "");2578DEBUG_ONLY(if (trace) { tty->print("ZZZ ctrl"); n->dump(); });2579for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {2580Node* u = n->fast_out(i);2581if (!u->is_Root() && u->is_CFG() && u != n) {2582Node* m = _memory_nodes[u->_idx];2583if (u->is_Region() && (!u->is_OuterStripMinedLoop() || _include_lsm) &&2584!has_mem_phi(u) &&2585u->unique_ctrl_out()->Opcode() != Op_Halt) {2586DEBUG_ONLY(if (trace) { tty->print("ZZZ region"); u->dump(); });2587DEBUG_ONLY(if (trace && m != NULL) { tty->print("ZZZ mem"); m->dump(); });25882589if (!mem_is_valid(m, u) || !m->is_Phi()) {2590bool push = true;2591bool create_phi = true;2592if (_phase->is_dominator(new_ctrl, u)) {2593create_phi = false;2594}2595if (create_phi) {2596Node* phi = new PhiNode(u, Type::MEMORY, _phase->C->get_adr_type(_alias));2597_phase->register_new_node(phi, u);2598phis.push(phi);2599DEBUG_ONLY(if (trace) { tty->print("ZZZ new phi"); phi->dump(); });2600if (!mem_is_valid(m, u)) {2601DEBUG_ONLY(if (trace) { tty->print("ZZZ setting mem"); phi->dump(); });2602_memory_nodes.map(u->_idx, phi);2603} else {2604DEBUG_ONLY(if (trace) { tty->print("ZZZ NOT setting mem"); m->dump(); });2605for (;;) {2606assert(m->is_Mem() || m->is_LoadStore() || m->is_Proj(), "");2607Node* next = NULL;2608if (m->is_Proj()) {2609next = m->in(0);2610} else {2611assert(m->is_Mem() || m->is_LoadStore(), "");2612assert(_alias == Compile::AliasIdxRaw, "");2613next = m->in(MemNode::Memory);2614}2615if (_phase->get_ctrl(next) != u) {2616break;2617}2618if (next->is_MergeMem()) {2619assert(_phase->get_ctrl(next->as_MergeMem()->memory_at(_alias)) != u, "");2620break;2621}2622if (next->is_Phi()) {2623assert(next->adr_type() == TypePtr::BOTTOM && next->in(0) == u, "");2624break;2625}2626m = next;2627}26282629DEBUG_ONLY(if (trace) { tty->print("ZZZ setting to phi"); m->dump(); });2630assert(m->is_Mem() || m->is_LoadStore(), "");2631uint input = (uint)MemNode::Memory;2632_phase->igvn().replace_input_of(m, input, phi);2633push = false;2634}2635} else {2636DEBUG_ONLY(if (trace) { tty->print("ZZZ skipping region"); u->dump(); });2637}2638if (push) {2639uses.push(u);2640}2641}2642} else if (!mem_is_valid(m, u) &&2643!(u->Opcode() == Op_CProj && u->in(0)->Opcode() == Op_NeverBranch && u->as_Proj()->_con == 1)) {2644uses.push(u);2645}2646}2647}2648}2649for (int i = 0; i < phis.length(); i++) {2650Node* n = phis.at(i);2651Node* r = n->in(0);2652DEBUG_ONLY(if (trace) { tty->print("ZZZ fixing new phi"); n->dump(); });2653for (uint j = 1; j < n->req(); j++) {2654Node* m = find_mem(r->in(j), NULL);2655_phase->igvn().replace_input_of(n, j, m);2656DEBUG_ONLY(if (trace) { tty->print("ZZZ fixing new phi: %d", j); m->dump(); });2657}2658}2659}2660uint last = _phase->C->unique();2661MergeMemNode* mm = NULL;2662int alias = _alias;2663DEBUG_ONLY(if (trace) { tty->print("ZZZ raw mem is"); mem->dump(); });2664// Process loads first to not miss an anti-dependency: if the memory2665// edge of a store is updated before a load is processed then an2666// anti-dependency may be missed.2667for (DUIterator i = mem->outs(); mem->has_out(i); i++) {2668Node* u = mem->out(i);2669if (u->_idx < last && u->is_Load() && _phase->C->get_alias_index(u->adr_type()) == alias) {2670Node* m = find_mem(_phase->get_ctrl(u), u);2671if (m != mem) {2672DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });2673_phase->igvn().replace_input_of(u, MemNode::Memory, m);2674--i;2675}2676}2677}2678for (DUIterator i = mem->outs(); mem->has_out(i); i++) {2679Node* u = mem->out(i);2680if (u->_idx < last) {2681if (u->is_Mem()) {2682if (_phase->C->get_alias_index(u->adr_type()) == alias) {2683Node* m = find_mem(_phase->get_ctrl(u), u);2684if (m != mem) {2685DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });2686_phase->igvn().replace_input_of(u, MemNode::Memory, m);2687--i;2688}2689}2690} else if (u->is_MergeMem()) {2691MergeMemNode* u_mm = u->as_MergeMem();2692if (u_mm->memory_at(alias) == mem) {2693MergeMemNode* newmm = NULL;2694for (DUIterator_Fast jmax, j = u->fast_outs(jmax); j < jmax; j++) {2695Node* uu = u->fast_out(j);2696assert(!uu->is_MergeMem(), "chain of MergeMems?");2697if (uu->is_Phi()) {2698assert(uu->adr_type() == TypePtr::BOTTOM, "");2699Node* region = uu->in(0);2700int nb = 0;2701for (uint k = 1; k < uu->req(); k++) {2702if (uu->in(k) == u) {2703Node* m = find_mem(region->in(k), NULL);2704if (m != mem) {2705DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of phi %d", k); uu->dump(); });2706newmm = clone_merge_mem(u, mem, m, _phase->ctrl_or_self(m), i);2707if (newmm != u) {2708_phase->igvn().replace_input_of(uu, k, newmm);2709nb++;2710--jmax;2711}2712}2713}2714}2715if (nb > 0) {2716--j;2717}2718} else {2719Node* m = find_mem(_phase->ctrl_or_self(uu), uu);2720if (m != mem) {2721DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); uu->dump(); });2722newmm = clone_merge_mem(u, mem, m, _phase->ctrl_or_self(m), i);2723if (newmm != u) {2724_phase->igvn().replace_input_of(uu, uu->find_edge(u), newmm);2725--j, --jmax;2726}2727}2728}2729}2730}2731} else if (u->is_Phi()) {2732assert(u->bottom_type() == Type::MEMORY, "what else?");2733if (_phase->C->get_alias_index(u->adr_type()) == alias || u->adr_type() == TypePtr::BOTTOM) {2734Node* region = u->in(0);2735bool replaced = false;2736for (uint j = 1; j < u->req(); j++) {2737if (u->in(j) == mem) {2738Node* m = find_mem(region->in(j), NULL);2739Node* nnew = m;2740if (m != mem) {2741if (u->adr_type() == TypePtr::BOTTOM) {2742mm = allocate_merge_mem(mem, m, _phase->ctrl_or_self(m));2743nnew = mm;2744}2745DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of phi %d", j); u->dump(); });2746_phase->igvn().replace_input_of(u, j, nnew);2747replaced = true;2748}2749}2750}2751if (replaced) {2752--i;2753}2754}2755} else if ((u->adr_type() == TypePtr::BOTTOM && u->Opcode() != Op_StrInflatedCopy) ||2756u->adr_type() == NULL) {2757assert(u->adr_type() != NULL ||2758u->Opcode() == Op_Rethrow ||2759u->Opcode() == Op_Return ||2760u->Opcode() == Op_SafePoint ||2761(u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) ||2762(u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) ||2763u->Opcode() == Op_CallLeaf, "");2764Node* m = find_mem(_phase->ctrl_or_self(u), u);2765if (m != mem) {2766mm = allocate_merge_mem(mem, m, _phase->get_ctrl(m));2767_phase->igvn().replace_input_of(u, u->find_edge(mem), mm);2768--i;2769}2770} else if (_phase->C->get_alias_index(u->adr_type()) == alias) {2771Node* m = find_mem(_phase->ctrl_or_self(u), u);2772if (m != mem) {2773DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });2774_phase->igvn().replace_input_of(u, u->find_edge(mem), m);2775--i;2776}2777} else if (u->adr_type() != TypePtr::BOTTOM &&2778_memory_nodes[_phase->ctrl_or_self(u)->_idx] == u) {2779Node* m = find_mem(_phase->ctrl_or_self(u), u);2780assert(m != mem, "");2781// u is on the wrong slice...2782assert(u->is_ClearArray(), "");2783DEBUG_ONLY(if (trace) { tty->print("ZZZ setting memory of use"); u->dump(); });2784_phase->igvn().replace_input_of(u, u->find_edge(mem), m);2785--i;2786}2787}2788}2789#ifdef ASSERT2790assert(new_mem->outcnt() > 0, "");2791for (int i = 0; i < phis.length(); i++) {2792Node* n = phis.at(i);2793assert(n->outcnt() > 0, "new phi must have uses now");2794}2795#endif2796}27972798MergeMemNode* MemoryGraphFixer::allocate_merge_mem(Node* mem, Node* rep_proj, Node* rep_ctrl) const {2799MergeMemNode* mm = MergeMemNode::make(mem);2800mm->set_memory_at(_alias, rep_proj);2801_phase->register_new_node(mm, rep_ctrl);2802return mm;2803}28042805MergeMemNode* MemoryGraphFixer::clone_merge_mem(Node* u, Node* mem, Node* rep_proj, Node* rep_ctrl, DUIterator& i) const {2806MergeMemNode* newmm = NULL;2807MergeMemNode* u_mm = u->as_MergeMem();2808Node* c = _phase->get_ctrl(u);2809if (_phase->is_dominator(c, rep_ctrl)) {2810c = rep_ctrl;2811} else {2812assert(_phase->is_dominator(rep_ctrl, c), "one must dominate the other");2813}2814if (u->outcnt() == 1) {2815if (u->req() > (uint)_alias && u->in(_alias) == mem) {2816_phase->igvn().replace_input_of(u, _alias, rep_proj);2817--i;2818} else {2819_phase->igvn().rehash_node_delayed(u);2820u_mm->set_memory_at(_alias, rep_proj);2821}2822newmm = u_mm;2823_phase->set_ctrl_and_loop(u, c);2824} else {2825// can't simply clone u and then change one of its input because2826// it adds and then removes an edge which messes with the2827// DUIterator2828newmm = MergeMemNode::make(u_mm->base_memory());2829for (uint j = 0; j < u->req(); j++) {2830if (j < newmm->req()) {2831if (j == (uint)_alias) {2832newmm->set_req(j, rep_proj);2833} else if (newmm->in(j) != u->in(j)) {2834newmm->set_req(j, u->in(j));2835}2836} else if (j == (uint)_alias) {2837newmm->add_req(rep_proj);2838} else {2839newmm->add_req(u->in(j));2840}2841}2842if ((uint)_alias >= u->req()) {2843newmm->set_memory_at(_alias, rep_proj);2844}2845_phase->register_new_node(newmm, c);2846}2847return newmm;2848}28492850bool MemoryGraphFixer::should_process_phi(Node* phi) const {2851if (phi->adr_type() == TypePtr::BOTTOM) {2852Node* region = phi->in(0);2853for (DUIterator_Fast jmax, j = region->fast_outs(jmax); j < jmax; j++) {2854Node* uu = region->fast_out(j);2855if (uu->is_Phi() && uu != phi && uu->bottom_type() == Type::MEMORY && _phase->C->get_alias_index(uu->adr_type()) == _alias) {2856return false;2857}2858}2859return true;2860}2861return _phase->C->get_alias_index(phi->adr_type()) == _alias;2862}28632864void MemoryGraphFixer::fix_memory_uses(Node* mem, Node* replacement, Node* rep_proj, Node* rep_ctrl) const {2865uint last = _phase-> C->unique();2866MergeMemNode* mm = NULL;2867assert(mem->bottom_type() == Type::MEMORY, "");2868for (DUIterator i = mem->outs(); mem->has_out(i); i++) {2869Node* u = mem->out(i);2870if (u != replacement && u->_idx < last) {2871if (u->is_MergeMem()) {2872MergeMemNode* u_mm = u->as_MergeMem();2873if (u_mm->memory_at(_alias) == mem) {2874MergeMemNode* newmm = NULL;2875for (DUIterator_Fast jmax, j = u->fast_outs(jmax); j < jmax; j++) {2876Node* uu = u->fast_out(j);2877assert(!uu->is_MergeMem(), "chain of MergeMems?");2878if (uu->is_Phi()) {2879if (should_process_phi(uu)) {2880Node* region = uu->in(0);2881int nb = 0;2882for (uint k = 1; k < uu->req(); k++) {2883if (uu->in(k) == u && _phase->is_dominator(rep_ctrl, region->in(k))) {2884if (newmm == NULL) {2885newmm = clone_merge_mem(u, mem, rep_proj, rep_ctrl, i);2886}2887if (newmm != u) {2888_phase->igvn().replace_input_of(uu, k, newmm);2889nb++;2890--jmax;2891}2892}2893}2894if (nb > 0) {2895--j;2896}2897}2898} else {2899if (rep_ctrl != uu && ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(uu), replacement, uu, _phase)) {2900if (newmm == NULL) {2901newmm = clone_merge_mem(u, mem, rep_proj, rep_ctrl, i);2902}2903if (newmm != u) {2904_phase->igvn().replace_input_of(uu, uu->find_edge(u), newmm);2905--j, --jmax;2906}2907}2908}2909}2910}2911} else if (u->is_Phi()) {2912assert(u->bottom_type() == Type::MEMORY, "what else?");2913Node* region = u->in(0);2914if (should_process_phi(u)) {2915bool replaced = false;2916for (uint j = 1; j < u->req(); j++) {2917if (u->in(j) == mem && _phase->is_dominator(rep_ctrl, region->in(j))) {2918Node* nnew = rep_proj;2919if (u->adr_type() == TypePtr::BOTTOM) {2920if (mm == NULL) {2921mm = allocate_merge_mem(mem, rep_proj, rep_ctrl);2922}2923nnew = mm;2924}2925_phase->igvn().replace_input_of(u, j, nnew);2926replaced = true;2927}2928}2929if (replaced) {2930--i;2931}29322933}2934} else if ((u->adr_type() == TypePtr::BOTTOM && u->Opcode() != Op_StrInflatedCopy) ||2935u->adr_type() == NULL) {2936assert(u->adr_type() != NULL ||2937u->Opcode() == Op_Rethrow ||2938u->Opcode() == Op_Return ||2939u->Opcode() == Op_SafePoint ||2940u->Opcode() == Op_StoreIConditional ||2941u->Opcode() == Op_StoreLConditional ||2942(u->is_CallStaticJava() && u->as_CallStaticJava()->uncommon_trap_request() != 0) ||2943(u->is_CallStaticJava() && u->as_CallStaticJava()->_entry_point == OptoRuntime::rethrow_stub()) ||2944u->Opcode() == Op_CallLeaf, "%s", u->Name());2945if (ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {2946if (mm == NULL) {2947mm = allocate_merge_mem(mem, rep_proj, rep_ctrl);2948}2949_phase->igvn().replace_input_of(u, u->find_edge(mem), mm);2950--i;2951}2952} else if (_phase->C->get_alias_index(u->adr_type()) == _alias) {2953if (ShenandoahBarrierC2Support::is_dominator(rep_ctrl, _phase->ctrl_or_self(u), replacement, u, _phase)) {2954_phase->igvn().replace_input_of(u, u->find_edge(mem), rep_proj);2955--i;2956}2957}2958}2959}2960}29612962ShenandoahLoadReferenceBarrierNode::ShenandoahLoadReferenceBarrierNode(Node* ctrl, Node* obj, DecoratorSet decorators)2963: Node(ctrl, obj), _decorators(decorators) {2964ShenandoahBarrierSetC2::bsc2()->state()->add_load_reference_barrier(this);2965}29662967DecoratorSet ShenandoahLoadReferenceBarrierNode::decorators() const {2968return _decorators;2969}29702971uint ShenandoahLoadReferenceBarrierNode::size_of() const {2972return sizeof(*this);2973}29742975static DecoratorSet mask_decorators(DecoratorSet decorators) {2976return decorators & (ON_STRONG_OOP_REF | ON_WEAK_OOP_REF | ON_PHANTOM_OOP_REF | ON_UNKNOWN_OOP_REF | IN_NATIVE);2977}29782979uint ShenandoahLoadReferenceBarrierNode::hash() const {2980uint hash = Node::hash();2981hash += mask_decorators(_decorators);2982return hash;2983}29842985bool ShenandoahLoadReferenceBarrierNode::cmp( const Node &n ) const {2986return Node::cmp(n) && n.Opcode() == Op_ShenandoahLoadReferenceBarrier &&2987mask_decorators(_decorators) == mask_decorators(((const ShenandoahLoadReferenceBarrierNode&)n)._decorators);2988}29892990const Type* ShenandoahLoadReferenceBarrierNode::bottom_type() const {2991if (in(ValueIn) == NULL || in(ValueIn)->is_top()) {2992return Type::TOP;2993}2994const Type* t = in(ValueIn)->bottom_type();2995if (t == TypePtr::NULL_PTR) {2996return t;2997}29982999if (ShenandoahBarrierSet::is_strong_access(decorators())) {3000return t;3001}30023003return t->meet(TypePtr::NULL_PTR);3004}30053006const Type* ShenandoahLoadReferenceBarrierNode::Value(PhaseGVN* phase) const {3007// Either input is TOP ==> the result is TOP3008const Type *t2 = phase->type(in(ValueIn));3009if( t2 == Type::TOP ) return Type::TOP;30103011if (t2 == TypePtr::NULL_PTR) {3012return t2;3013}30143015if (ShenandoahBarrierSet::is_strong_access(decorators())) {3016return t2;3017}30183019return t2->meet(TypePtr::NULL_PTR);3020}30213022Node* ShenandoahLoadReferenceBarrierNode::Identity(PhaseGVN* phase) {3023Node* value = in(ValueIn);3024if (!needs_barrier(phase, value)) {3025return value;3026}3027return this;3028}30293030bool ShenandoahLoadReferenceBarrierNode::needs_barrier(PhaseGVN* phase, Node* n) {3031Unique_Node_List visited;3032return needs_barrier_impl(phase, n, visited);3033}30343035bool ShenandoahLoadReferenceBarrierNode::needs_barrier_impl(PhaseGVN* phase, Node* n, Unique_Node_List &visited) {3036if (n == NULL) return false;3037if (visited.member(n)) {3038return false; // Been there.3039}3040visited.push(n);30413042if (n->is_Allocate()) {3043// tty->print_cr("optimize barrier on alloc");3044return false;3045}3046if (n->is_Call()) {3047// tty->print_cr("optimize barrier on call");3048return false;3049}30503051const Type* type = phase->type(n);3052if (type == Type::TOP) {3053return false;3054}3055if (type->make_ptr()->higher_equal(TypePtr::NULL_PTR)) {3056// tty->print_cr("optimize barrier on null");3057return false;3058}3059if (type->make_oopptr() && type->make_oopptr()->const_oop() != NULL) {3060// tty->print_cr("optimize barrier on constant");3061return false;3062}30633064switch (n->Opcode()) {3065case Op_AddP:3066return true; // TODO: Can refine?3067case Op_LoadP:3068case Op_ShenandoahCompareAndExchangeN:3069case Op_ShenandoahCompareAndExchangeP:3070case Op_CompareAndExchangeN:3071case Op_CompareAndExchangeP:3072case Op_GetAndSetN:3073case Op_GetAndSetP:3074return true;3075case Op_Phi: {3076for (uint i = 1; i < n->req(); i++) {3077if (needs_barrier_impl(phase, n->in(i), visited)) return true;3078}3079return false;3080}3081case Op_CheckCastPP:3082case Op_CastPP:3083return needs_barrier_impl(phase, n->in(1), visited);3084case Op_Proj:3085return needs_barrier_impl(phase, n->in(0), visited);3086case Op_ShenandoahLoadReferenceBarrier:3087// tty->print_cr("optimize barrier on barrier");3088return false;3089case Op_Parm:3090// tty->print_cr("optimize barrier on input arg");3091return false;3092case Op_DecodeN:3093case Op_EncodeP:3094return needs_barrier_impl(phase, n->in(1), visited);3095case Op_LoadN:3096return true;3097case Op_CMoveN:3098case Op_CMoveP:3099return needs_barrier_impl(phase, n->in(2), visited) ||3100needs_barrier_impl(phase, n->in(3), visited);3101case Op_ShenandoahIUBarrier:3102return needs_barrier_impl(phase, n->in(1), visited);3103case Op_CreateEx:3104return false;3105default:3106break;3107}3108#ifdef ASSERT3109tty->print("need barrier on?: ");3110tty->print_cr("ins:");3111n->dump(2);3112tty->print_cr("outs:");3113n->dump(-2);3114ShouldNotReachHere();3115#endif3116return true;3117}311831193120