macro.cpp revision 1100
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * This code is free software; you can redistribute it and/or modify it
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * under the terms of the GNU General Public License version 2 only, as
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * published by the Free Software Foundation.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * This code is distributed in the hope that it will be useful, but WITHOUT
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * version 2 for more details (a copy is included in the LICENSE file that
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * accompanied this code).
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * You should have received a copy of the GNU General Public License version
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * 2 along with this work; if not, write to the Free Software Foundation,
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * CA 95054 USA or visit www.sun.com if you need additional information or
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici * have any questions.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici#include "incls/_precompiled.incl"
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici#include "incls/_macro.cpp.incl"
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici// Replace any references to "oldref" in inputs to "use" with "newref".
e60a1cf74ca44a3bb3e3fe63b106e6ef6dca910fPhill Cunnington// Returns the number of replacements made.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Briciint PhaseMacroExpand::replace_input(Node *use, Node *oldref, Node *newref) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Bricivoid PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcall) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Copy debug information and adjust JVMState information
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici uint old_dbg_start = oldcall->tf()->domain()->cnt();
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici uint new_dbg_start = newcall->tf()->domain()->cnt();
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert (new_dbg_start == newcall->req(), "argument count mismatch");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici for (uint i = old_dbg_start; i < oldcall->req(); i++) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Clone old SafePointScalarObjectNodes, adjusting their field contents.
e60a1cf74ca44a3bb3e3fe63b106e6ef6dca910fPhill Cunnington if (old_in != NULL && old_in->is_SafePointScalarObject()) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici SafePointScalarObjectNode* old_sosn = old_in->as_SafePointScalarObject();
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici Node* new_in = old_sosn->clone(jvms_adj, sosn_map);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici new_in->set_req(0, newcall->in(0)); // reset control edge
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici new_in = transform_later(new_in); // Register new node.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici for (JVMState *jvms = newcall->jvms(); jvms != NULL; jvms = jvms->caller()) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin BriciNode* PhaseMacroExpand::opt_bits_test(Node* ctrl, Node* region, int edge, Node* word, int mask, int bits, bool return_fast_path) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici Node* and_node = transform_later(new (C, 3) AndXNode(word, MakeConX(mask)));
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici cmp = transform_later(new (C, 3) CmpXNode(and_node, MakeConX(bits)));
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici Node* bol = transform_later(new (C, 2) BoolNode(cmp, BoolTest::ne));
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici IfNode* iff = new (C, 2) IfNode( ctrl, bol, PROB_MIN, COUNT_UNKNOWN );
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Fast path taken.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici Node *fast_taken = transform_later( new (C, 1) IfFalseNode(iff) );
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Fast path not-taken, i.e. slow path
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici Node *slow_taken = transform_later( new (C, 1) IfTrueNode(iff) );
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici region->init_req(edge, slow_taken); // Capture slow-control
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici region->init_req(edge, fast_taken); // Capture fast-control
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici//--------------------copy_predefined_input_for_runtime_call--------------------
0be6372051459d02acfe49de71e8d6653f0b412eAlin Bricivoid PhaseMacroExpand::copy_predefined_input_for_runtime_call(Node * ctrl, CallNode* oldcall, CallNode* call) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Set fixed predefined input arguments
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici call->init_req( TypeFunc::I_O , oldcall->in( TypeFunc::I_O) );
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici call->init_req( TypeFunc::Memory , oldcall->in( TypeFunc::Memory ) ); // ?????
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici call->init_req( TypeFunc::ReturnAdr, oldcall->in( TypeFunc::ReturnAdr ) );
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici call->init_req( TypeFunc::FramePtr, oldcall->in( TypeFunc::FramePtr ) );
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici//------------------------------make_slow_call---------------------------------
0be6372051459d02acfe49de71e8d6653f0b412eAlin BriciCallNode* PhaseMacroExpand::make_slow_call(CallNode *oldcall, const TypeFunc* slow_call_type, address slow_call, const char* leaf_name, Node* slow_path, Node* parm0, Node* parm1) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Slow-path call
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici ? (CallNode*)new (C, size) CallLeafNode ( slow_call_type, slow_call, leaf_name, TypeRawPtr::BOTTOM )
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici : (CallNode*)new (C, size) CallStaticJavaNode( slow_call_type, slow_call, OptoRuntime::stub_name(slow_call), oldcall->jvms()->bci(), TypeRawPtr::BOTTOM );
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Slow path call has no side-effects, uses few values
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici copy_predefined_input_for_runtime_call(slow_path, oldcall, call );
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (parm0 != NULL) call->init_req(TypeFunc::Parms+0, parm0);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (parm1 != NULL) call->init_req(TypeFunc::Parms+1, parm1);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici call->set_cnt(PROB_UNLIKELY_MAG(4)); // Same effect as RC_UNCOMMON.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Bricivoid PhaseMacroExpand::extract_call_projections(CallNode *call) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici for (DUIterator_Fast imax, i = call->fast_outs(imax); i < imax; i++) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // For Control (fallthrough) and I_O (catch_all_index) we have CatchProj -> Catch -> Proj
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici for (DUIterator_Fast kmax, k = cn->fast_outs(kmax); k < kmax; k++) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(cpn->is_CatchProj(), "must be a CatchProjNode");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (cpn->_con == CatchProjNode::fall_through_index)
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(cpn->_con == CatchProjNode::catch_all_index, "must be correct index.");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(false, "unexpected projection from allocation node.");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici// Eliminate a card mark sequence. p2x is a ConvP2XNode
0be6372051459d02acfe49de71e8d6653f0b412eAlin Bricivoid PhaseMacroExpand::eliminate_card_mark(Node* p2x) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(p2x->Opcode() == Op_CastP2X, "ConvP2XNode required");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // vanilla/CMS post barrier
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici for (DUIterator_Last jmin, j = addp->last_outs(jmin); j >= jmin; --j) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // G1 pre/post barriers
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(p2x->outcnt() == 2, "expects 2 users: Xor and URShift nodes");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // It could be only one user, URShift node, in Object.clone() instrinsic
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // but the new allocation is passed to arraycopy stub and it could not
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // be scalar replaced. So we don't check the case.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Remove G1 post barrier.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Search for CastP2X->Xor->URShift->Cmp path which
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // checks if the store done to a different from the value's region.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // And replace Cmp with #0 (false) to collapse G1 post barrier.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici for (DUIterator_Fast imax, i = p2x->fast_outs(imax); i < imax; i++) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(cmpx->is_Cmp() && cmpx->unique_out()->is_Bool() &&
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici cmpx->unique_out()->as_Bool()->_test._test == BoolTest::ne,
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici "missing region check in G1 post barrier");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici _igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ));
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Remove G1 pre barrier.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Search "if (marking != 0)" check and set it to "false".
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // There is no G1 pre barrier if previous stored value is NULL
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // (for example, after initialization).
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (this_region->is_Region() && this_region->req() == 3) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (bol->as_Bool()->_test._test == BoolTest::ne &&
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici Node* adr = cmpx->in(1)->as_Load()->in(MemNode::Address);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() +
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (adr->is_AddP() && adr->in(AddPNode::Base) == top() &&
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal &&
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici adr->in(AddPNode::Offset) == MakeConX(marking_offset)) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici _igvn.replace_node(cmpx, makecon(TypeInt::CC_EQ));
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Now CastP2X can be removed since it is used only on dead path
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // which currently still alive until igvn optimize it.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(p2x->unique_out()->Opcode() == Op_URShiftX, "");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici// Search for a memory operation for the specified memory slice.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Bricistatic Node *scan_mem_chain(Node *mem, int alias_idx, int offset, Node *start_mem, Node *alloc, PhaseGVN *phase) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici const TypeOopPtr *tinst = phase->C->get_adr_type(alias_idx)->isa_oopptr();
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici while (true) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici } else if (mem->is_Proj() && mem->as_Proj()->_con == TypeFunc::Memory) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // we can safely skip over safepoints, calls, locks and membars because we
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // already know that the object is safe to eliminate.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (in->is_Initialize() && in->as_Initialize()->allocation() == alloc) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici const TypePtr* atype = mem->as_Store()->adr_type();
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici int adr_idx = Compile::current()->get_alias_index(atype);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(atype->isa_oopptr(), "address type must be oopptr");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici uint adr_iid = atype->is_oopptr()->instance_id();
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Array elements references have the same alias_idx
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // but different offset and different instance_id.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (adr_offset == offset && adr_iid == alloc->_idx)
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(adr_idx == Compile::AliasIdxRaw, "address must match or be raw");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (!ClearArrayNode::step_through(&mem, alloc->_idx, phase)) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Can not bypass initialization of the instance
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // we are looking.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(alloc == AllocateNode::Ideal_allocation(mem->in(3), phase, offset), "sanity");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici InitializeNode* init = alloc->as_Allocate()->initialization();
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // We are looking for stored value, return Initialize node
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // or memory edge from Allocate node.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici return alloc->in(TypeFunc::Memory); // It will produce zero value (see callers).
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Otherwise skip it (the call updated 'mem' value).
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici const TypePtr* atype = mem->in(0)->in(MemNode::Address)->bottom_type()->is_ptr();
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici int adr_idx = Compile::current()->get_alias_index(atype);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(false, "Object is not scalar replaceable if a LoadStore node access its field");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici// Given a Memory Phi, compute a value Phi containing the values from stores
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici// on the input paths.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici// Note: this function is recursive, its depth is limied by the "level" argument
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici// Returns the computed Phi, or NULL if it cannot compute it.
0be6372051459d02acfe49de71e8d6653f0b412eAlin BriciNode *PhaseMacroExpand::value_from_mem_phi(Node *mem, BasicType ft, const Type *phi_type, const TypeOopPtr *adr_t, Node *alloc, Node_Stack *value_phis, int level) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Check if an appropriate value phi already exists.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici for (DUIterator_Fast kmax, k = region->fast_outs(kmax); k < kmax; k++) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici phi->as_Phi()->is_same_inst_field(phi_type, instance_id, alias_idx, offset)) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Check if an appropriate new value phi already exists.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici Node *start_mem = C->start()->proj_out(TypeFunc::Memory);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici GrowableArray <Node *> values(length, length, NULL);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // create a new Phi for the value
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici Node *val = scan_mem_chain(in, alias_idx, offset, start_mem, alloc, &_igvn);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // hit a sentinel, return appropriate 0 value
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici val = val->as_Initialize()->find_captured_store(offset, type2aelembytes(ft), &_igvn);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici } else if(val->is_Proj() && val->in(0) == alloc) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici val = value_from_mem_phi(val, ft, phi_type, adr_t, alloc, value_phis, level-1);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(false, "Object is not scalar replaceable if a LoadStore node access its field");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Set Phi's inputs
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici// Search the last value stored into the object's field.
0be6372051459d02acfe49de71e8d6653f0b412eAlin BriciNode *PhaseMacroExpand::value_from_mem(Node *sfpt_mem, BasicType ft, const Type *ftype, const TypeOopPtr *adr_t, Node *alloc) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(adr_t->is_known_instance_field(), "instance required");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert((uint)instance_id == alloc->_idx, "wrong allocation");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici Node *start_mem = C->start()->proj_out(TypeFunc::Memory);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici mem = scan_mem_chain(mem, alias_idx, offset, start_mem, alloc, &_igvn);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici done = true; // hit a sentinel, return appropriate 0 value
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici mem = mem->as_Initialize()->find_captured_store(offset, type2aelembytes(ft), &_igvn);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici const TypePtr* atype = mem->as_Store()->adr_type();
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(C->get_alias_index(atype) == Compile::AliasIdxRaw, "store is correct memory slice");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici const TypeOopPtr* atype = mem->as_Store()->adr_type()->isa_oopptr();
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici assert(atype != NULL, "address type must be oopptr");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici atype->is_known_instance_field() && atype->offset() == offset &&
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici atype->instance_id() == instance_id, "store is correct memory slice");
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // try to find a phi's unique input
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici Node *n = scan_mem_chain(mem->in(i), alias_idx, offset, start_mem, alloc, &_igvn);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici } else if (unique_input != n) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (unique_input != NULL && unique_input != top) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // hit a sentinel, return appropriate 0 value
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // attempt to produce a Phi reflecting the values on the input paths of the Phi
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici Node * phi = value_from_mem_phi(mem, ft, ftype, adr_t, alloc, &value_phis, ValueSearchLimit);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Kill all new Phis
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Something go wrong.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici// Check the possibility of scalar replacement.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Bricibool PhaseMacroExpand::can_eliminate_allocation(AllocateNode *alloc, GrowableArray <SafePointNode *>& safepoints) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // Scan the uses of the allocation to check for anything that would
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // prevent us from eliminating it.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici NOT_PRODUCT( const char* fail_eliminate = NULL; )
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici // All users were eliminated.
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici alloc->_is_scalar_replaceable = false; // don't try again
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici NOT_PRODUCT(fail_eliminate = "Allocation does not have unique CheckCastPP";)
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici NOT_PRODUCT(fail_eliminate = "Neither instance or array allocation";)
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici int length = alloc->in(AllocateNode::ALength)->find_int_con(-1);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici NOT_PRODUCT(fail_eliminate = "Array's size is not constant";)
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici for (DUIterator_Fast jmax, j = res->fast_outs(jmax);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici const TypePtr* addp_type = _igvn.type(use)->is_ptr();
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (offset == Type::OffsetTop || offset == Type::OffsetBot) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici NOT_PRODUCT(fail_eliminate = "Undefined field referrence";)
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici for (DUIterator_Fast kmax, k = use->fast_outs(kmax);
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici if (!n->is_Store() && n->Opcode() != Op_CastP2X) {
0be6372051459d02acfe49de71e8d6653f0b412eAlin Brici NOT_PRODUCT(fail_eliminate = "Not store field referrence";)
can_eliminate = false;
can_eliminate = false;
can_eliminate = false;
can_eliminate = false;
#ifndef PRODUCT
if (PrintEliminateAllocations) {
if (can_eliminate) {
#ifdef ASSERT
return can_eliminate;
bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray <SafePointNode *>& safepoints) {
int nfields = 0;
int array_base;
int element_size;
#ifdef ASSERT
for (int j = 0; j < nfields; j++) {
if (UseCompressedOops) {
for (int k = 0; k < nfields; k++) {
#ifndef PRODUCT
if (PrintEliminateAllocations) {
field_val = transform_later(new (C, 2) DecodeNNode(field_val, field_val->bottom_type()->make_ptr()));
if (n->is_Store()) {
#ifdef ASSERT
p < pmax; p++) {
#ifdef ASSERT
while (p != NULL) {
p = p->caller();
#ifndef PRODUCT
if (PrintEliminateAllocations) {
Node* PhaseMacroExpand::make_load(Node* ctl, Node* mem, Node* base, int offset, const Type* value_type, BasicType bt) {
return value;
Node* PhaseMacroExpand::make_store(Node* ctl, Node* mem, Node* base, int offset, Node* value, BasicType bt) {
return mem;
// %%% Here is an old comment from parseHelper.cpp; is it outdated?
// coalesce.cpp about how this works. It depends critically on the exact
bool always_slow = false;
if (tv >= 0) {
always_slow = true;
if (!always_slow) {
// See comment in memnode.hpp, around line 227 in class LoadPNode.
if( UseTLAB ) {
? new (C, 3) LoadPNode ( ctrl, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, TypeRawPtr::BOTTOM )
IfNode *needgc_iff = new (C, 2) IfNode(contended_region, needgc_bol, PROB_UNLIKELY_MAG(4), COUNT_UNKNOWN );
if( initial_slow_test ) {
if( UseTLAB ) {
store_eden_top = new (C, 4) StorePNode( needgc_false, contended_phi_rawmem, eden_top_adr, TypeRawPtr::BOTTOM, new_eden_top );
store_eden_top = new (C, 5) StorePConditionalNode( needgc_false, contended_phi_rawmem, eden_top_adr, new_eden_top, old_eden_top );
IfNode *contention_iff = new (C, 2) IfNode ( needgc_false, contention_check, PROB_MIN, COUNT_UNKNOWN );
if (!always_slow) {
// Replace uses of the control memory projection with result_phi_rawmem (unless we are only generating a slow call)
// Replace uses of the control i_o projection with result_phi_i_o (unless we are only generating a slow call)
} else if (!always_slow) {
if (always_slow)
Node*
mark_node = make_load(NULL, rawmem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeRawPtr::BOTTOM, T_ADDRESS);
rawmem = make_store(control, rawmem, object, oopDesc::mark_offset_in_bytes(), mark_node, T_ADDRESS);
rawmem = make_store(control, rawmem, object, oopDesc::klass_offset_in_bytes(), klass_node, T_OBJECT);
rawmem = make_store(control, rawmem, object, arrayOopDesc::length_offset_in_bytes(), length, T_INT);
if (!ZeroTLAB)
&_igvn);
return rawmem;
} else if( AllocatePrefetchStyle > 0 ) {
return i_o;
bool next_edge = true;
if (u == alock) {
if (u->is_Lock() &&
next_edge = false;
#ifdef ASSERT
next_edge = false;
if (next_edge) i++;
while (p != NULL) {
p = p->caller();
#ifndef PRODUCT
if (PrintEliminateLocks) {
if (UseOptoBiasInlining) {
Node* mark_node = make_load(ctrl, mem, obj, oopDesc::mark_offset_in_bytes(), TypeX_X, TypeX_X->basic_type());
klass_node = transform_later( LoadKlassNode::make(_igvn, mem, k_adr, _igvn.type(k_adr)->is_ptr()) );
#ifdef _LP64
Node *proto_node = make_load(ctrl, mem, klass_node, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), TypeX_X, TypeX_X->basic_type());
CallNode *call = make_slow_call( (CallNode *) lock, OptoRuntime::complete_monitor_enter_Type(), OptoRuntime::complete_monitor_locking_Java(), NULL, slow_path, obj, box );
if (UseOptoBiasInlining) {
Node* mark_node = make_load(ctrl, mem, obj, oopDesc::mark_offset_in_bytes(), TypeX_X, TypeX_X->basic_type());
CallNode *call = make_slow_call( (CallNode *) unlock, OptoRuntime::complete_monitor_exit_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::complete_monitor_unlocking_C), "complete_monitor_unlocking_C", slow_path, obj, box );
if (C->macro_count() == 0)
bool progress = true;
while (progress) {
progress = false;
for (int i = C->macro_count(); i > 0; i--) {
bool success = false;
if (n->is_AbstractLock()) {
success = true;
progress = true;
while (progress) {
progress = false;
for (int i = C->macro_count(); i > 0; i--) {
bool success = false;
switch (n->class_id()) {
while (C->macro_count() > 0) {
C->remove_macro_node(n);
switch (n->class_id()) {
if (C->failing()) return true;