Mercurial > hg > truffle
diff src/share/vm/opto/escape.cpp @ 10408:836a62f43af9
Merge with http://hg.openjdk.java.net/hsx/hsx25/hotspot/
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Wed, 19 Jun 2013 10:45:56 +0200 |
parents | f2110083203d |
children | b800986664f4 |
line wrap: on
line diff
--- a/src/share/vm/opto/escape.cpp Tue Jun 18 14:23:29 2013 -0700 +++ b/src/share/vm/opto/escape.cpp Wed Jun 19 10:45:56 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,15 +63,19 @@ // EA brings benefits only when the code has allocations and/or locks which // are represented by ideal Macro nodes. int cnt = C->macro_count(); - for( int i=0; i < cnt; i++ ) { + for (int i = 0; i < cnt; i++) { Node *n = C->macro_node(i); - if ( n->is_Allocate() ) + if (n->is_Allocate()) return true; - if( n->is_Lock() ) { + if (n->is_Lock()) { Node* obj = n->as_Lock()->obj_node()->uncast(); - if( !(obj->is_Parm() || obj->is_Con()) ) + if (!(obj->is_Parm() || obj->is_Con())) return true; } + if (n->is_CallStaticJava() && + n->as_CallStaticJava()->is_boxing_method()) { + return true; + } } return false; } @@ -115,7 +119,7 @@ { Compile::TracePhase t3("connectionGraph", &Phase::_t_connectionGraph, true); // 1. Populate Connection Graph (CG) with PointsTo nodes. - ideal_nodes.map(C->unique(), NULL); // preallocate space + ideal_nodes.map(C->live_nodes(), NULL); // preallocate space // Initialize worklist if (C->root() != NULL) { ideal_nodes.push(C->root()); @@ -152,8 +156,11 @@ // escape status of the associated Allocate node some of them // may be eliminated. storestore_worklist.append(n); + } else if (n->is_MemBar() && (n->Opcode() == Op_MemBarRelease) && + (n->req() > MemBarNode::Precedent)) { + record_for_optimizer(n); #ifdef ASSERT - } else if(n->is_AddP()) { + } else if (n->is_AddP()) { // Collect address nodes for graph verification. addp_worklist.append(n); #endif @@ -206,8 +213,15 @@ int non_escaped_length = non_escaped_worklist.length(); for (int next = 0; next < non_escaped_length; next++) { JavaObjectNode* ptn = non_escaped_worklist.at(next); - if (ptn->escape_state() == PointsToNode::NoEscape && - ptn->scalar_replaceable()) { + bool noescape = (ptn->escape_state() == PointsToNode::NoEscape); + Node* n = ptn->ideal_node(); + if (n->is_Allocate()) { + n->as_Allocate()->_is_non_escaping = noescape; + } + if (n->is_CallStaticJava()) { + n->as_CallStaticJava()->_is_non_escaping = noescape; + } + if (noescape && ptn->scalar_replaceable()) { adjust_scalar_replaceable_state(ptn); if (ptn->scalar_replaceable()) { alloc_worklist.append(ptn->ideal_node()); @@ -263,7 +277,7 @@ // scalar replaceable objects. split_unique_types(alloc_worklist); if (C->failing()) return false; - C->print_method("After Escape Analysis", 2); + C->print_method(PHASE_AFTER_EA, 2); #ifdef ASSERT } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) { @@ -330,8 +344,10 @@ // Don't mark as processed since call's arguments have to be processed. delayed_worklist->push(n); // Check if a call returns an object. - if (n->as_Call()->returns_pointer() && - n->as_Call()->proj_out(TypeFunc::Parms) != NULL) { + if ((n->as_Call()->returns_pointer() && + n->as_Call()->proj_out(TypeFunc::Parms) != NULL) || + (n->is_CallStaticJava() && + n->as_CallStaticJava()->is_boxing_method())) { add_call_node(n->as_Call()); } } @@ -387,8 +403,8 @@ case Op_ConNKlass: { // assume all oop constants globally escape except for null PointsToNode::EscapeState es; - if (igvn->type(n) == TypePtr::NULL_PTR || - igvn->type(n) == TypeNarrowOop::NULL_PTR) { + const Type* t = igvn->type(n); + if (t == TypePtr::NULL_PTR || t == TypeNarrowOop::NULL_PTR) { es = PointsToNode::NoEscape; } else { es = PointsToNode::GlobalEscape; @@ -468,6 +484,9 @@ Node* adr = n->in(MemNode::Address); const Type *adr_type = igvn->type(adr); adr_type = adr_type->make_ptr(); + if (adr_type == NULL) { + break; // skip dead nodes + } if (adr_type->isa_oopptr() || (opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) && (adr_type == TypeRawPtr::NOTNULL && @@ -660,14 +679,18 @@ case Op_GetAndSetP: case Op_GetAndSetN: { Node* adr = n->in(MemNode::Address); - if (opcode == Op_GetAndSetP || opcode == Op_GetAndSetN) { - const Type* t = _igvn->type(n); - if (t->make_ptr() != NULL) { - add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL); - } - } const Type *adr_type = _igvn->type(adr); adr_type = adr_type->make_ptr(); +#ifdef ASSERT + if (adr_type == NULL) { + n->dump(1); + assert(adr_type != NULL, "dead node should not be on list"); + break; + } +#endif + if (opcode == Op_GetAndSetP || opcode == Op_GetAndSetN) { + add_local_var_and_edge(n, PointsToNode::NoEscape, adr, NULL); + } if (adr_type->isa_oopptr() || (opcode == Op_StoreP || opcode == Op_StoreN || opcode == Op_StoreNKlass) && (adr_type == TypeRawPtr::NOTNULL && @@ -797,6 +820,18 @@ // Returns a newly allocated unescaped object. add_java_object(call, PointsToNode::NoEscape); ptnode_adr(call_idx)->set_scalar_replaceable(false); + } else if (meth->is_boxing_method()) { + // Returns boxing object + PointsToNode::EscapeState es; + vmIntrinsics::ID intr = meth->intrinsic_id(); + if (intr == vmIntrinsics::_floatValue || intr == vmIntrinsics::_doubleValue) { + // It does not escape if object is always allocated. + es = PointsToNode::NoEscape; + } else { + // It escapes globally if object could be loaded from cache. + es = PointsToNode::GlobalEscape; + } + add_java_object(call, es); } else { BCEscapeAnalyzer* call_analyzer = meth->get_bcea(); call_analyzer->copy_dependencies(_compile->dependencies()); @@ -943,6 +978,9 @@ assert((name == NULL || strcmp(name, "uncommon_trap") != 0), "normal calls only"); #endif ciMethod* meth = call->as_CallJava()->method(); + if ((meth != NULL) && meth->is_boxing_method()) { + break; // Boxing methods do not modify any oops. + } BCEscapeAnalyzer* call_analyzer = (meth !=NULL) ? meth->get_bcea() : NULL; // fall-through if not a Java method or no analyzer information if (call_analyzer != NULL) { @@ -1791,9 +1829,8 @@ jobj2->ideal_node()->is_Con()) { // Klass or String constants compare. Need to be careful with // compressed pointers - compare types of ConN and ConP instead of nodes. - const Type* t1 = jobj1->ideal_node()->bottom_type()->make_ptr(); - const Type* t2 = jobj2->ideal_node()->bottom_type()->make_ptr(); - assert(t1 != NULL && t2 != NULL, "sanity"); + const Type* t1 = jobj1->ideal_node()->get_ptr_type(); + const Type* t2 = jobj2->ideal_node()->get_ptr_type(); if (t1->make_ptr() == t2->make_ptr()) { return _pcmp_eq; } else { @@ -2165,7 +2202,7 @@ int opcode = uncast_base->Opcode(); assert(opcode == Op_ConP || opcode == Op_ThreadLocal || opcode == Op_CastX2P || uncast_base->is_DecodeNarrowPtr() || - (uncast_base->is_Mem() && uncast_base->bottom_type() == TypeRawPtr::NOTNULL) || + (uncast_base->is_Mem() && (uncast_base->bottom_type()->isa_rawptr() != NULL)) || (uncast_base->is_Proj() && uncast_base->in(0)->is_Allocate()), "sanity"); } return base; @@ -2744,6 +2781,11 @@ // so it could be eliminated if it has no uses. alloc->as_Allocate()->_is_scalar_replaceable = true; } + if (alloc->is_CallStaticJava()) { + // Set the scalar_replaceable flag for boxing method + // so it could be eliminated if it has no uses. + alloc->as_CallStaticJava()->_is_scalar_replaceable = true; + } continue; } if (!n->is_CheckCastPP()) { // not unique CheckCastPP. @@ -2782,6 +2824,11 @@ // so it could be eliminated. alloc->as_Allocate()->_is_scalar_replaceable = true; } + if (alloc->is_CallStaticJava()) { + // Set the scalar_replaceable flag for boxing method + // so it could be eliminated. + alloc->as_CallStaticJava()->_is_scalar_replaceable = true; + } set_escape_state(ptnode_adr(n->_idx), es); // CheckCastPP escape state // in order for an object to be scalar-replaceable, it must be: // - a direct allocation (not a call returning an object) @@ -2911,7 +2958,9 @@ // Load/store to instance's field memnode_worklist.append_if_missing(use); } else if (use->is_MemBar()) { - memnode_worklist.append_if_missing(use); + if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge + memnode_worklist.append_if_missing(use); + } } else if (use->is_AddP() && use->outcnt() > 0) { // No dead nodes Node* addp2 = find_second_addp(use, n); if (addp2 != NULL) { @@ -3028,7 +3077,9 @@ continue; memnode_worklist.append_if_missing(use); } else if (use->is_MemBar()) { - memnode_worklist.append_if_missing(use); + if (use->in(TypeFunc::Memory) == n) { // Ignore precedent edge + memnode_worklist.append_if_missing(use); + } #ifdef ASSERT } else if(use->is_Mem()) { assert(use->in(MemNode::Memory) != n, "EA: missing memory path"); @@ -3264,7 +3315,12 @@ if (ptn == NULL || !ptn->is_JavaObject()) continue; PointsToNode::EscapeState es = ptn->escape_state(); - if (ptn->ideal_node()->is_Allocate() && (es == PointsToNode::NoEscape || Verbose)) { + if ((es != PointsToNode::NoEscape) && !Verbose) { + continue; + } + Node* n = ptn->ideal_node(); + if (n->is_Allocate() || (n->is_CallStaticJava() && + n->as_CallStaticJava()->is_boxing_method())) { if (first) { tty->cr(); tty->print("======== Connection graph for ");