arraycopynode.hpp revision 12806:2ab74e5dbdc2
1193323Sed/* 2193323Sed * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3193323Sed * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4193323Sed * 5193323Sed * This code is free software; you can redistribute it and/or modify it 6193323Sed * under the terms of the GNU General Public License version 2 only, as 7193323Sed * published by the Free Software Foundation. 8193323Sed * 9193323Sed * This code is distributed in the hope that it will be useful, but WITHOUT 10193323Sed * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11193323Sed * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12193323Sed * version 2 for more details (a copy is included in the LICENSE file that 13193323Sed * accompanied this code). 14193323Sed * 15193323Sed * You should have received a copy of the GNU General Public License version 16193323Sed * 2 along with this work; if not, write to the Free Software Foundation, 17193323Sed * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18193323Sed * 19218893Sdim * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20193323Sed * or visit www.oracle.com if you need additional information or have any 21193323Sed * questions. 22193323Sed * 23193323Sed */ 24193323Sed 25193323Sed#ifndef SHARE_VM_OPTO_ARRAYCOPYNODE_HPP 26193323Sed#define SHARE_VM_OPTO_ARRAYCOPYNODE_HPP 27193323Sed 28218893Sdim#include "opto/callnode.hpp" 29193323Sed 30193323Sedclass GraphKit; 31193323Sed 32218893Sdimclass ArrayCopyNode : public CallNode { 33218893Sdimprivate: 34193323Sed 35194612Sed // What kind of arraycopy variant is this? 36194612Sed enum { 37194612Sed None, // not set yet 38194612Sed ArrayCopy, // System.arraycopy() 39194612Sed CloneBasic, // A clone that can be copied by 64 bit chunks 40194612Sed CloneOop, // An oop array clone 41194612Sed CopyOf, // Arrays.copyOf() 42218893Sdim CopyOfRange // Arrays.copyOfRange() 43193323Sed } _kind; 44193323Sed 45193323Sed#ifndef PRODUCT 46193323Sed static const char* _kind_names[CopyOfRange+1]; 47193323Sed#endif 48193323Sed // Is the alloc obtained with 49193323Sed // AllocateArrayNode::Ideal_array_allocation() tighly coupled 50193323Sed // (arraycopy follows immediately the allocation)? 51193323Sed // We cache the result of LibraryCallKit::tightly_coupled_allocation 52193323Sed // here because it's much easier to find whether there's a tightly 53193323Sed // couple allocation at parse time than at macro expansion time. At 54193323Sed // macro expansion time, for every use of the allocation node we 55193323Sed // would need to figure out whether it happens after the arraycopy (and 56193323Sed // can be ignored) or between the allocation and the arraycopy. At 57193323Sed // parse time, it's straightforward because whatever happens after 58193323Sed // the arraycopy is not parsed yet so doesn't exist when 59193323Sed // LibraryCallKit::tightly_coupled_allocation() is called. 60193323Sed bool _alloc_tightly_coupled; 61193323Sed bool _has_negative_length_guard; 62219077Sdim 63193323Sed bool _arguments_validated; 64193323Sed 65193323Sed static const TypeFunc* arraycopy_type() { 66193323Sed const Type** fields = TypeTuple::fields(ParmLimit - TypeFunc::Parms); 67193323Sed fields[Src] = TypeInstPtr::BOTTOM; 68193323Sed fields[SrcPos] = TypeInt::INT; 69193323Sed fields[Dest] = TypeInstPtr::BOTTOM; 70193323Sed fields[DestPos] = TypeInt::INT; 71193323Sed fields[Length] = TypeInt::INT; 72193323Sed fields[SrcLen] = TypeInt::INT; 73193323Sed fields[DestLen] = TypeInt::INT; 74193323Sed fields[SrcKlass] = TypeKlassPtr::BOTTOM; 75193323Sed fields[DestKlass] = TypeKlassPtr::BOTTOM; 76203954Srdivacky const TypeTuple *domain = TypeTuple::make(ParmLimit, fields); 77193323Sed 78193323Sed // create result type (range) 79193323Sed fields = TypeTuple::fields(0); 80193323Sed 81203954Srdivacky const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields); 82193323Sed 83193323Sed return TypeFunc::make(domain, range); 84193323Sed } 85193323Sed 86193323Sed ArrayCopyNode(Compile* C, bool alloc_tightly_coupled, bool has_negative_length_guard); 87193323Sed 88193323Sed intptr_t get_length_if_constant(PhaseGVN *phase) const; 89193323Sed int get_count(PhaseGVN *phase) const; 90193323Sed static const TypePtr* get_address_type(PhaseGVN *phase, Node* n); 91208599Srdivacky 92208599Srdivacky Node* try_clone_instance(PhaseGVN *phase, bool can_reshape, int count); 93208599Srdivacky bool prepare_array_copy(PhaseGVN *phase, bool can_reshape, 94208599Srdivacky Node*& adr_src, Node*& base_src, Node*& adr_dest, Node*& base_dest, 95208599Srdivacky BasicType& copy_type, const Type*& value_type, bool& disjoint_bases); 96208599Srdivacky void array_copy_test_overlap(PhaseGVN *phase, bool can_reshape, 97208599Srdivacky bool disjoint_bases, int count, 98208599Srdivacky Node*& forward_ctl, Node*& backward_ctl); 99208599Srdivacky Node* array_copy_forward(PhaseGVN *phase, bool can_reshape, Node* ctl, 100208599Srdivacky Node* start_mem_src, Node* start_mem_dest, 101208599Srdivacky const TypePtr* atp_src, const TypePtr* atp_dest, 102208599Srdivacky Node* adr_src, Node* base_src, Node* adr_dest, Node* base_dest, 103208599Srdivacky BasicType copy_type, const Type* value_type, int count); 104208599Srdivacky Node* array_copy_backward(PhaseGVN *phase, bool can_reshape, Node* ctl, 105193323Sed Node *start_mem_src, Node* start_mem_dest, 106203954Srdivacky const TypePtr* atp_src, const TypePtr* atp_dest, 107193323Sed Node* adr_src, Node* base_src, Node* adr_dest, Node* base_dest, 108193323Sed BasicType copy_type, const Type* value_type, int count); 109193323Sed bool finish_transform(PhaseGVN *phase, bool can_reshape, 110193323Sed Node* ctl, Node *mem); 111193323Sed static bool may_modify_helper(const TypeOopPtr *t_oop, Node* n, PhaseTransform *phase, CallNode*& call); 112193323Sed 113193323Sedpublic: 114193323Sed 115193323Sed enum { 116193323Sed Src = TypeFunc::Parms, 117203954Srdivacky SrcPos, 118193323Sed Dest, 119193323Sed DestPos, 120193323Sed Length, 121193323Sed SrcLen, 122193323Sed DestLen, 123193323Sed SrcKlass, 124193323Sed DestKlass, 125193323Sed ParmLimit 126193323Sed }; 127204792Srdivacky 128204792Srdivacky // Results from escape analysis for non escaping inputs 129204792Srdivacky const TypeOopPtr* _src_type; 130204792Srdivacky const TypeOopPtr* _dest_type; 131203954Srdivacky 132203954Srdivacky static ArrayCopyNode* make(GraphKit* kit, bool may_throw, 133203954Srdivacky Node* src, Node* src_offset, 134203954Srdivacky Node* dest, Node* dest_offset, 135203954Srdivacky Node* length, 136203954Srdivacky bool alloc_tightly_coupled, 137203954Srdivacky bool has_negative_length_guard, 138193323Sed Node* src_klass = NULL, Node* dest_klass = NULL, 139203954Srdivacky Node* src_length = NULL, Node* dest_length = NULL); 140203954Srdivacky 141203954Srdivacky void connect_outputs(GraphKit* kit); 142203954Srdivacky 143203954Srdivacky bool is_arraycopy() const { assert(_kind != None, "should bet set"); return _kind == ArrayCopy; } 144203954Srdivacky bool is_arraycopy_validated() const { assert(_kind != None, "should bet set"); return _kind == ArrayCopy && _arguments_validated; } 145204792Srdivacky bool is_clonebasic() const { assert(_kind != None, "should bet set"); return _kind == CloneBasic; } 146204792Srdivacky bool is_cloneoop() const { assert(_kind != None, "should bet set"); return _kind == CloneOop; } 147204792Srdivacky bool is_copyof() const { assert(_kind != None, "should bet set"); return _kind == CopyOf; } 148204792Srdivacky bool is_copyof_validated() const { assert(_kind != None, "should bet set"); return _kind == CopyOf && _arguments_validated; } 149193323Sed bool is_copyofrange() const { assert(_kind != None, "should bet set"); return _kind == CopyOfRange; } 150193323Sed bool is_copyofrange_validated() const { assert(_kind != None, "should bet set"); return _kind == CopyOfRange && _arguments_validated; } 151193323Sed 152193323Sed void set_arraycopy(bool validated) { assert(_kind == None, "shouldn't bet set yet"); _kind = ArrayCopy; _arguments_validated = validated; } 153193323Sed void set_clonebasic() { assert(_kind == None, "shouldn't bet set yet"); _kind = CloneBasic; } 154193323Sed void set_cloneoop() { assert(_kind == None, "shouldn't bet set yet"); _kind = CloneOop; } 155193323Sed void set_copyof(bool validated) { assert(_kind == None, "shouldn't bet set yet"); _kind = CopyOf; _arguments_validated = validated; } 156193323Sed void set_copyofrange(bool validated) { assert(_kind == None, "shouldn't bet set yet"); _kind = CopyOfRange; _arguments_validated = validated; } 157218893Sdim 158218893Sdim virtual int Opcode() const; 159218893Sdim virtual uint size_of() const; // Size is bigger 160193323Sed virtual bool guaranteed_safepoint() { return false; } 161193323Sed virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); 162193323Sed 163218893Sdim virtual bool may_modify(const TypeOopPtr *t_oop, PhaseTransform *phase); 164218893Sdim 165218893Sdim bool is_alloc_tightly_coupled() const { return _alloc_tightly_coupled; } 166193323Sed 167193323Sed bool has_negative_length_guard() const { return _has_negative_length_guard; } 168193323Sed 169193323Sed static bool may_modify(const TypeOopPtr *t_oop, MemBarNode* mb, PhaseTransform *phase, ArrayCopyNode*& ac); 170193323Sed bool modifies(intptr_t offset_lo, intptr_t offset_hi, PhaseTransform* phase, bool must_modify) const; 171193323Sed 172208599Srdivacky#ifndef PRODUCT 173208599Srdivacky virtual void dump_spec(outputStream *st) const; 174208599Srdivacky virtual void dump_compact_spec(outputStream* st) const; 175208599Srdivacky#endif 176208599Srdivacky}; 177208599Srdivacky#endif // SHARE_VM_OPTO_ARRAYCOPYNODE_HPP 178193323Sed