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