hotspot/src/share/vm/code/codeBlob.hpp
changeset 38133 78b95467b9f1
parent 35542 9dccb7f9f656
child 42040 70ec5a09a0d5
--- a/hotspot/src/share/vm/code/codeBlob.hpp	Mon Apr 25 21:25:22 2016 +0300
+++ b/hotspot/src/share/vm/code/codeBlob.hpp	Tue Apr 26 10:28:51 2016 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -45,12 +45,14 @@
 
 // CodeBlob - superclass for all entries in the CodeCache.
 //
-// Suptypes are:
-//   nmethod            : Compiled Java methods (include method that calls to native code)
-//   RuntimeStub        : Call to VM runtime methods
-//   DeoptimizationBlob : Used for deoptimizatation
-//   ExceptionBlob      : Used for stack unrolling
-//   SafepointBlob      : Used to handle illegal instruction exceptions
+// Subtypes are:
+//   CompiledMethod       : Compiled Java methods (include method that calls to native code)
+//     nmethod            : JIT Compiled Java methods
+//   RuntimeBlob          : Non-compiled method code; generated glue code
+//     RuntimeStub        : Call to VM runtime methods
+//     DeoptimizationBlob : Used for deoptimization
+//     ExceptionBlob      : Used for stack unrolling
+//     SafepointBlob      : Used to handle illegal instruction exceptions
 //
 //
 // Layout:
@@ -59,90 +61,79 @@
 //   - content space
 //     - instruction space
 //   - data space
-class DeoptimizationBlob;
+
+
+class CodeBlobLayout;
 
 class CodeBlob VALUE_OBJ_CLASS_SPEC {
-
   friend class VMStructs;
   friend class JVMCIVMStructs;
   friend class CodeCacheDumper;
 
- private:
+protected:
   const char* _name;
   int        _size;                              // total size of CodeBlob in bytes
   int        _header_size;                       // size of header (depends on subclass)
-  int        _relocation_size;                   // size of relocation
-  int        _content_offset;                    // offset to where content region begins (this includes consts, insts, stubs)
-  int        _code_offset;                       // offset to where instructions region begins (this includes insts, stubs)
   int        _frame_complete_offset;             // instruction offsets in [0.._frame_complete_offset) have
                                                  // not finished setting up their frame. Beware of pc's in
                                                  // that range. There is a similar range(s) on returns
                                                  // which we don't detect.
   int        _data_offset;                       // offset to where data region begins
   int        _frame_size;                        // size of stack frame
+
+  address    _code_begin;
+  address    _code_end;
+  address    _content_begin;                     // address to where content region begins (this includes consts, insts, stubs)
+                                                 // address    _content_end - not required, for all CodeBlobs _code_end == _content_end for now
+  address    _data_end;
+  address    _relocation_begin;
+  address    _relocation_end;
+
   ImmutableOopMapSet* _oop_maps;                 // OopMap for this CodeBlob
-  CodeStrings _strings;
+  bool                _caller_must_gc_arguments;
+  CodeStrings         _strings;
 
- public:
+  CodeBlob(const char* name, const CodeBlobLayout& layout, int frame_complete_offset, int frame_size, ImmutableOopMapSet* oop_maps, bool caller_must_gc_arguments);
+  CodeBlob(const char* name, const CodeBlobLayout& layout, CodeBuffer* cb, int frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments);
+public:
   // Returns the space needed for CodeBlob
   static unsigned int allocation_size(CodeBuffer* cb, int header_size);
   static unsigned int align_code_offset(int offset);
 
-  // Creation
-  // a) simple CodeBlob
-  // frame_complete is the offset from the beginning of the instructions
-  // to where the frame setup (from stackwalk viewpoint) is complete.
-  CodeBlob(const char* name, int header_size, int size, int frame_complete, int locs_size);
-
-  // b) full CodeBlob
-  CodeBlob(
-    const char* name,
-    CodeBuffer* cb,
-    int         header_size,
-    int         size,
-    int         frame_complete,
-    int         frame_size,
-    OopMapSet*  oop_maps
-  );
-
   // Deletion
-  void flush();
+  virtual void flush();
 
   // Typing
-  virtual bool is_buffer_blob() const            { return false; }
-  virtual bool is_nmethod() const                { return false; }
-  virtual bool is_runtime_stub() const           { return false; }
-  virtual bool is_deoptimization_stub() const    { return false; }
-  virtual bool is_uncommon_trap_stub() const     { return false; }
-  virtual bool is_exception_stub() const         { return false; }
+  virtual bool is_buffer_blob() const                 { return false; }
+  virtual bool is_nmethod() const                     { return false; }
+  virtual bool is_runtime_stub() const                { return false; }
+  virtual bool is_deoptimization_stub() const         { return false; }
+  virtual bool is_uncommon_trap_stub() const          { return false; }
+  virtual bool is_exception_stub() const              { return false; }
   virtual bool is_safepoint_stub() const              { return false; }
   virtual bool is_adapter_blob() const                { return false; }
   virtual bool is_method_handles_adapter_blob() const { return false; }
+  virtual bool is_compiled() const                    { return false; }
 
   virtual bool is_compiled_by_c2() const         { return false; }
   virtual bool is_compiled_by_c1() const         { return false; }
   virtual bool is_compiled_by_jvmci() const      { return false; }
 
   // Casting
-  nmethod* as_nmethod_or_null()                  { return is_nmethod() ? (nmethod*) this : NULL; }
+  nmethod* as_nmethod_or_null()                { return is_nmethod() ? (nmethod*) this : NULL; }
+  nmethod* as_nmethod()                        { assert(is_nmethod(), "must be nmethod"); return (nmethod*) this; }
+  CompiledMethod* as_compiled_method_or_null() { return is_compiled() ? (CompiledMethod*) this : NULL; }
+  CompiledMethod* as_compiled_method()         { assert(is_compiled(), "must be compiled"); return (CompiledMethod*) this; }
 
   // Boundaries
-  address    header_begin() const                { return (address)    this; }
-  address    header_end() const                  { return ((address)   this) + _header_size; };
-  relocInfo* relocation_begin() const            { return (relocInfo*) header_end(); };
-  relocInfo* relocation_end() const              { return (relocInfo*)(header_end()   + _relocation_size); }
-  address    content_begin() const               { return (address)    header_begin() + _content_offset; }
-  address    content_end() const                 { return (address)    header_begin() + _data_offset; }
-  address    code_begin() const                  { return (address)    header_begin() + _code_offset; }
-  address    code_end() const                    { return (address)    header_begin() + _data_offset; }
-  address    data_begin() const                  { return (address)    header_begin() + _data_offset; }
-  address    data_end() const                    { return (address)    header_begin() + _size; }
-
-  // Offsets
-  int relocation_offset() const                  { return _header_size; }
-  int content_offset() const                     { return _content_offset; }
-  int code_offset() const                        { return _code_offset; }
-  int data_offset() const                        { return _data_offset; }
+  address header_begin() const        { return (address) this; }
+  relocInfo* relocation_begin() const { return (relocInfo*) _relocation_begin; };
+  relocInfo* relocation_end() const   { return (relocInfo*) _relocation_end; }
+  address content_begin() const       { return _content_begin; }
+  address content_end() const         { return _code_end; } // _code_end == _content_end is true for all types of blobs for now, it is also checked in the constructor
+  address code_begin() const          { return _code_begin;    }
+  address code_end() const            { return _code_end; }
+  address data_end() const            { return _data_end;      }
 
   // Sizes
   int size() const                               { return _size; }
@@ -150,17 +141,12 @@
   int relocation_size() const                    { return (address) relocation_end() - (address) relocation_begin(); }
   int content_size() const                       { return           content_end()    -           content_begin();    }
   int code_size() const                          { return           code_end()       -           code_begin();       }
-  int data_size() const                          { return           data_end()       -           data_begin();       }
 
   // Containment
   bool blob_contains(address addr) const         { return header_begin()       <= addr && addr < data_end();       }
-  bool relocation_contains(relocInfo* addr) const{ return relocation_begin()   <= addr && addr < relocation_end(); }
-  bool content_contains(address addr) const      { return content_begin()      <= addr && addr < content_end();    }
   bool code_contains(address addr) const         { return code_begin()         <= addr && addr < code_end();       }
-  bool data_contains(address addr) const         { return data_begin()         <= addr && addr < data_end();       }
-  bool contains(address addr) const              { return content_contains(addr); }
-  bool is_frame_complete_at(address addr) const  { return code_contains(addr) &&
-                                                          addr >= code_begin() + _frame_complete_offset; }
+  bool contains(address addr) const              { return content_begin()      <= addr && addr < content_end();    }
+  bool is_frame_complete_at(address addr) const  { return code_contains(addr) && addr >= code_begin() + _frame_complete_offset; }
 
   // CodeCache support: really only used by the nmethods, but in order to get
   // asserts and certain bookkeeping to work in the CodeCache they are defined
@@ -178,29 +164,26 @@
   ImmutableOopMapSet* oop_maps() const           { return _oop_maps; }
   void set_oop_maps(OopMapSet* p);
   const ImmutableOopMap* oop_map_for_return_address(address return_address);
-  virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f)  { ShouldNotReachHere(); }
+  virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) = 0;
 
   // Frame support
   int  frame_size() const                        { return _frame_size; }
   void set_frame_size(int size)                  { _frame_size = size; }
 
   // Returns true, if the next frame is responsible for GC'ing oops passed as arguments
-  virtual bool caller_must_gc_arguments(JavaThread* thread) const { return false; }
+  bool caller_must_gc_arguments(JavaThread* thread) const { return _caller_must_gc_arguments; }
 
   // Naming
   const char* name() const                       { return _name; }
   void set_name(const char* name)                { _name = name; }
 
   // Debugging
-  virtual void verify();
-  void print() const                             { print_on(tty); }
+  virtual void verify() = 0;
+  virtual void print() const                     { print_on(tty); };
   virtual void print_on(outputStream* st) const;
   virtual void print_value_on(outputStream* st) const;
   void print_code();
 
-  // Deal with Disassembler, VTune, Forte, JvmtiExport, MemoryService.
-  static void trace_new_stub(CodeBlob* blob, const char* name1, const char* name2 = "");
-
   // Print the comment associated with offset on stream, if there is one
   virtual void print_block_comment(outputStream* stream, address block_begin) const {
     intptr_t offset = (intptr_t)(block_begin - code_begin());
@@ -221,11 +204,142 @@
   }
 };
 
+class CodeBlobLayout : public StackObj {
+private:
+  int _size;
+  int _header_size;
+  int _relocation_size;
+  int _content_offset;
+  int _code_offset;
+  int _data_offset;
+  address _code_begin;
+  address _code_end;
+  address _content_begin;
+  address _content_end;
+  address _data_end;
+  address _relocation_begin;
+  address _relocation_end;
+
+public:
+  CodeBlobLayout(address code_begin, address code_end, address content_begin, address content_end, address data_end, address relocation_begin, address relocation_end) :
+    _size(0),
+    _header_size(0),
+    _relocation_size(0),
+    _content_offset(0),
+    _code_offset(0),
+    _data_offset(0),
+    _content_begin(content_begin),
+    _content_end(content_end),
+    _code_begin(code_begin),
+    _code_end(code_end),
+    _data_end(data_end),
+    _relocation_begin(relocation_begin),
+    _relocation_end(relocation_end)
+  {
+  }
+
+  CodeBlobLayout(const address start, int size, int header_size, int relocation_size, int data_offset) :
+    _size(size),
+    _header_size(header_size),
+    _relocation_size(relocation_size),
+    _content_offset(CodeBlob::align_code_offset(_header_size + _relocation_size)),
+    _code_offset(_content_offset),
+    _data_offset(data_offset)
+  {
+    assert(_relocation_size == round_to(_relocation_size, oopSize), "unaligned size");
+
+    _code_begin = (address) start + _code_offset;
+    _code_end = (address) start + _data_offset;
+
+    _content_begin = (address) start + _content_offset;
+    _content_end = (address) start + _data_offset;
+
+    _data_end = (address) start + _size;
+    _relocation_begin = (address) start + _header_size;
+    _relocation_end = _relocation_begin + _relocation_size;
+  }
+
+  CodeBlobLayout(const address start, int size, int header_size, const CodeBuffer* cb) :
+    _size(size),
+    _header_size(header_size),
+    _relocation_size(round_to(cb->total_relocation_size(), oopSize)),
+    _content_offset(CodeBlob::align_code_offset(_header_size + _relocation_size)),
+    _code_offset(_content_offset + cb->total_offset_of(cb->insts())),
+    _data_offset(_content_offset + round_to(cb->total_content_size(), oopSize))
+  {
+    assert(_relocation_size == round_to(_relocation_size, oopSize), "unaligned size");
+
+    _code_begin = (address) start + _code_offset;
+    _code_end = (address) start + _data_offset;
+
+    _content_begin = (address) start + _content_offset;
+    _content_end = (address) start + _data_offset;
+
+    _data_end = (address) start + _size;
+    _relocation_begin = (address) start + _header_size;
+    _relocation_end = _relocation_begin + _relocation_size;
+  }
+
+  int size() const { return _size; }
+  int header_size() const { return _header_size; }
+  int relocation_size() const { return _relocation_size; }
+  int content_offset() const { return _content_offset; }
+  int code_offset() const { return _code_offset; }
+  int data_offset() const { return _data_offset; }
+  address code_begin() const { return _code_begin; }
+  address code_end() const { return _code_end; }
+  address data_end() const { return _data_end; }
+  address relocation_begin() const { return _relocation_begin; }
+  address relocation_end() const { return _relocation_end; }
+  address content_begin() const { return _content_begin; }
+  address content_end() const { return _content_end; }
+};
+
+
+class RuntimeBlob : public CodeBlob {
+  friend class VMStructs;
+ public:
+
+  // Creation
+  // a) simple CodeBlob
+  // frame_complete is the offset from the beginning of the instructions
+  // to where the frame setup (from stackwalk viewpoint) is complete.
+  RuntimeBlob(const char* name, int header_size, int size, int frame_complete, int locs_size);
+
+  // b) full CodeBlob
+  RuntimeBlob(
+    const char* name,
+    CodeBuffer* cb,
+    int         header_size,
+    int         size,
+    int         frame_complete,
+    int         frame_size,
+    OopMapSet*  oop_maps,
+    bool        caller_must_gc_arguments = false
+  );
+
+  // GC support
+  virtual bool is_alive() const                  = 0;
+
+  void verify();
+
+  // OopMap for frame
+  virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f)  { ShouldNotReachHere(); }
+
+  // Debugging
+  void print() const                             { print_on(tty); }
+  virtual void print_on(outputStream* st) const { CodeBlob::print_on(st); }
+  virtual void print_value_on(outputStream* st) const { CodeBlob::print_value_on(st); }
+
+  // Deal with Disassembler, VTune, Forte, JvmtiExport, MemoryService.
+  static void trace_new_stub(RuntimeBlob* blob, const char* name1, const char* name2 = "");
+};
+
 class WhiteBox;
 //----------------------------------------------------------------------------------------------------
 // BufferBlob: used to hold non-relocatable machine code such as the interpreter, stubroutines, etc.
 
-class BufferBlob: public CodeBlob {
+class BufferBlob: public RuntimeBlob {
   friend class VMStructs;
   friend class AdapterBlob;
   friend class MethodHandlesAdapterBlob;
@@ -293,11 +407,9 @@
 //----------------------------------------------------------------------------------------------------
 // RuntimeStub: describes stubs used by compiled code to call a (static) C++ runtime routine
 
-class RuntimeStub: public CodeBlob {
+class RuntimeStub: public RuntimeBlob {
   friend class VMStructs;
  private:
-  bool        _caller_must_gc_arguments;
-
   // Creation support
   RuntimeStub(
     const char* name,
@@ -325,10 +437,7 @@
   // Typing
   bool is_runtime_stub() const                   { return true; }
 
-  // GC support
-  bool caller_must_gc_arguments(JavaThread* thread) const { return _caller_must_gc_arguments; }
-
-  address entry_point()                          { return code_begin(); }
+  address entry_point() const                    { return code_begin(); }
 
   // GC/Verification support
   void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f)  { /* nothing to do */ }
@@ -343,7 +452,7 @@
 //----------------------------------------------------------------------------------------------------
 // Super-class for all blobs that exist in only one instance. Implements default behaviour.
 
-class SingletonBlob: public CodeBlob {
+class SingletonBlob: public RuntimeBlob {
   friend class VMStructs;
 
  protected:
@@ -358,13 +467,15 @@
      int         frame_size,
      OopMapSet*  oop_maps
    )
-   : CodeBlob(name, cb, header_size, size, CodeOffsets::frame_never_safe, frame_size, oop_maps)
+   : RuntimeBlob(name, cb, header_size, size, CodeOffsets::frame_never_safe, frame_size, oop_maps)
   {};
 
   address entry_point()                          { return code_begin(); }
 
   bool is_alive() const                          { return true; }
 
+  // GC/Verification support
+  void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f)  { /* nothing to do */ }
   void verify(); // does nothing
   void print_on(outputStream* st) const;
   void print_value_on(outputStream* st) const;