src/share/vm/opto/callnode.hpp

Print this page
rev 3361 : 7173584: Implement arraycopy as a macro node
Summary: delay the conversion of arraycopy to stub calls to macro expansion
Reviewed-by:

@@ -968,6 +968,87 @@
   virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
   // unlock is never a safepoint
   virtual bool        guaranteed_safepoint()  { return false; }
 };
 
+class ArrayCopyNode : public CallNode {
+private:
+
+  // What kind of arraycopy variant is this?
+  enum {
+    ArrayCopy,       // System.arraycopy()
+    ArrayCopyNoTest, // System.arraycopy(), all arguments validated
+    CloneBasic,      // A clone that can be copied by 64 bit chunks
+    CloneOop,        // An oop array clone
+    CopyOf           // Arrays.copyOf()
+  } _kind;
+
+  // Is the alloc obtained with
+  // AllocateArrayNode::Ideal_array_allocation() tighly coupled
+  // (arraycopy follows immediately the allocation)?
+  // We cache the result of LibraryCallKit::tightly_coupled_allocation
+  // here because it's much easier to find whether there's a tightly
+  // couple allocation at parse time than at macro expansion time. At
+  // macro expansion time, for every use of the allocation node we
+  // would need to figure out whether it happens after the arraycopy (and
+  // can be ignored) or between the allocation and the arraycopy. At
+  // parse time, it's straightforward because whatever happens after
+  // the arraycopy is not parsed yet so doesn't exist when
+  // LibraryCallKit::tightly_coupled_allocation() is called.
+  bool _alloc_tightly_coupled;
+
+  static const TypeFunc* arraycopy_type() {
+    const Type** fields = TypeTuple::fields(ParmLimit - TypeFunc::Parms);
+    fields[Src]     = TypeInstPtr::BOTTOM;
+    fields[SrcPos]  = TypeInt::INT;
+    fields[Dest]    = TypeInstPtr::BOTTOM;
+    fields[DestPos] = TypeInt::INT;
+    fields[Length]  = TypeInt::INT;
+    const TypeTuple *domain = TypeTuple::make(ParmLimit, fields);
+
+    // create result type (range)
+    fields = TypeTuple::fields(0);
+
+    const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields);
+
+    return TypeFunc::make(domain, range);
+  }
+
+  ArrayCopyNode(Compile* C, bool alloc_tightly_coupled);
+
+public:
+
+  enum {
+    Src   = TypeFunc::Parms,
+    SrcPos,
+    Dest,
+    DestPos,
+    Length,
+    ParmLimit
+  };
+
+  static ArrayCopyNode* make(GraphKit* kit, bool may_throw,
+                             Node* src, Node* src_offset, Node* dest, Node* dest_offset, Node* length,
+                             bool alloc_tightly_coupled);
+
+  void connect_outputs(GraphKit* kit);
+
+  bool is_arraycopy()         const { return _kind == ArrayCopy; }
+  bool is_arraycopy_notest()  const { return _kind == ArrayCopyNoTest; }
+  bool is_clonebasic()        const { return _kind == CloneBasic; }
+  bool is_cloneoop()          const { return _kind == CloneOop; }
+  bool is_copyof()            const { return _kind == CopyOf; }
+
+  void set_arraycopy()         { _kind = ArrayCopy; }
+  void set_arraycopy_notest()  { _kind = ArrayCopyNoTest; }
+  void set_clonebasic()        { _kind = CloneBasic; }
+  void set_cloneoop()          { _kind = CloneOop; }
+  void set_copyof()            { _kind = CopyOf; }
+
+  virtual int Opcode() const;
+  virtual uint size_of() const; // Size is bigger
+  virtual bool guaranteed_safepoint()  { return false; }
+
+  bool is_alloc_tightly_coupled() const { return _alloc_tightly_coupled; }
+
+};
 #endif // SHARE_VM_OPTO_CALLNODE_HPP