stubs.hpp 12.0 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27
#ifndef SHARE_VM_CODE_STUBS_HPP
#define SHARE_VM_CODE_STUBS_HPP

28
#include "asm/codeBuffer.hpp"
29 30 31 32 33 34 35 36 37 38
#include "memory/allocation.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
N
never 已提交
39 40 41
#ifdef TARGET_OS_FAMILY_bsd
# include "os_bsd.inline.hpp"
#endif
42

D
duke 已提交
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
// The classes in this file provide a simple framework for the
// management of little pieces of machine code - or stubs -
// created on the fly and frequently discarded. In this frame-
// work stubs are stored in a queue.


// Stub serves as abstract base class. A concrete stub
// implementation is a subclass of Stub, implementing
// all (non-virtual!) functions required sketched out
// in the Stub class.
//
// A concrete stub layout may look like this (both data
// and code sections could be empty as well):
//
//                ________
// stub       -->|        | <--+
//               |  data  |    |
//               |________|    |
// code_begin -->|        |    |
//               |        |    |
//               |  code  |    | size
//               |        |    |
//               |________|    |
// code_end   -->|        |    |
//               |  data  |    |
//               |________|    |
//                          <--+


class Stub VALUE_OBJ_CLASS_SPEC {
 public:
  // Initialization/finalization
75 76
  void    initialize(int size,
                     CodeComments& comments)     { ShouldNotCallThis(); }                // called to initialize/specify the stub's size
D
duke 已提交
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
  void    finalize()                             { ShouldNotCallThis(); }                // called before the stub is deallocated

  // General info/converters
  int     size() const                           { ShouldNotCallThis(); return 0; }      // must return the size provided by initialize
  static  int code_size_to_size(int code_size)   { ShouldNotCallThis(); return 0; }      // computes the size given the code size

  // Code info
  address code_begin() const                     { ShouldNotCallThis(); return NULL; }   // points to the first byte of    the code
  address code_end() const                       { ShouldNotCallThis(); return NULL; }   // points to the first byte after the code

  // Debugging
  void    verify()                               { ShouldNotCallThis(); }                // verifies the Stub
  void    print()                                { ShouldNotCallThis(); }                // prints some information about the stub
};


// A stub interface defines the interface between a stub queue
// and the stubs it queues. In order to avoid a vtable and
// (and thus the extra word) in each stub, a concrete stub
// interface object is created and associated with a stub
// buffer which in turn uses the stub interface to interact
// with its stubs.
//
// StubInterface serves as an abstract base class. A concrete
// stub interface implementation is a subclass of StubInterface,
// forwarding its virtual function calls to non-virtual calls
// of the concrete stub (see also macro below). There's exactly
// one stub interface instance required per stub queue.

Z
zgu 已提交
106
class StubInterface: public CHeapObj<mtCode> {
D
duke 已提交
107 108
 public:
  // Initialization/finalization
109 110
  virtual void    initialize(Stub* self, int size,
                             CodeComments& comments)       = 0; // called after creation (called twice if allocated via (request, commit))
D
duke 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
  virtual void    finalize(Stub* self)                     = 0; // called before deallocation

  // General info/converters
  virtual int     size(Stub* self) const                   = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment)
  virtual int     code_size_to_size(int code_size) const   = 0; // computes the total stub size in bytes given the code size in bytes

  // Code info
  virtual address code_begin(Stub* self) const             = 0; // points to the first code byte
  virtual address code_end(Stub* self) const               = 0; // points to the first byte after the code

  // Debugging
  virtual void    verify(Stub* self)                       = 0; // verifies the stub
  virtual void    print(Stub* self)                        = 0; // prints information about the stub
};


// DEF_STUB_INTERFACE is used to create a concrete stub interface
// class, forwarding stub interface calls to the corresponding
// stub calls.

#define DEF_STUB_INTERFACE(stub)                           \
  class stub##Interface: public StubInterface {            \
   private:                                                \
    static stub*    cast(Stub* self)                       { return (stub*)self; }                 \
                                                           \
   public:                                                 \
    /* Initialization/finalization */                      \
138 139
    virtual void    initialize(Stub* self, int size,       \
                               CodeComments& comments)     { cast(self)->initialize(size, comments); } \
D
duke 已提交
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
    virtual void    finalize(Stub* self)                   { cast(self)->finalize(); }             \
                                                           \
    /* General info */                                     \
    virtual int     size(Stub* self) const                 { return cast(self)->size(); }          \
    virtual int     code_size_to_size(int code_size) const { return stub::code_size_to_size(code_size); } \
                                                           \
    /* Code info */                                        \
    virtual address code_begin(Stub* self) const           { return cast(self)->code_begin(); }    \
    virtual address code_end(Stub* self) const             { return cast(self)->code_end(); }      \
                                                           \
    /* Debugging */                                        \
    virtual void    verify(Stub* self)                     { cast(self)->verify(); }               \
    virtual void    print(Stub* self)                      { cast(self)->print(); }                \
  };


// A StubQueue maintains a queue of stubs.
// Note: All sizes (spaces) are given in bytes.

Z
zgu 已提交
159
class StubQueue: public CHeapObj<mtCode> {
D
duke 已提交
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
  friend class VMStructs;
 private:
  StubInterface* _stub_interface;                // the interface prototype
  address        _stub_buffer;                   // where all stubs are stored
  int            _buffer_size;                   // the buffer size in bytes
  int            _buffer_limit;                  // the (byte) index of the actual buffer limit (_buffer_limit <= _buffer_size)
  int            _queue_begin;                   // the (byte) index of the first queue entry (word-aligned)
  int            _queue_end;                     // the (byte) index of the first entry after the queue (word-aligned)
  int            _number_of_stubs;               // the number of buffered stubs
  Mutex* const   _mutex;                         // the lock used for a (request, commit) transaction

  void  check_index(int i) const                 { assert(0 <= i && i < _buffer_limit && i % CodeEntryAlignment == 0, "illegal index"); }
  bool  is_contiguous() const                    { return _queue_begin <= _queue_end; }
  int   index_of(Stub* s) const                  { int i = (address)s - _stub_buffer; check_index(i); return i; }
  Stub* stub_at(int i) const                     { check_index(i); return (Stub*)(_stub_buffer + i); }
  Stub* current_stub() const                     { return stub_at(_queue_end); }

  // Stub functionality accessed via interface
178 179
  void  stub_initialize(Stub* s, int size,
                        CodeComments& comments)  { assert(size % CodeEntryAlignment == 0, "size not aligned"); _stub_interface->initialize(s, size, comments); }
D
duke 已提交
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
  void  stub_finalize(Stub* s)                   { _stub_interface->finalize(s); }
  int   stub_size(Stub* s) const                 { return _stub_interface->size(s); }
  bool  stub_contains(Stub* s, address pc) const { return _stub_interface->code_begin(s) <= pc && pc < _stub_interface->code_end(s); }
  int   stub_code_size_to_size(int code_size) const { return _stub_interface->code_size_to_size(code_size); }
  void  stub_verify(Stub* s)                     { _stub_interface->verify(s); }
  void  stub_print(Stub* s)                      { _stub_interface->print(s); }

  static void register_queue(StubQueue*);

 public:
  StubQueue(StubInterface* stub_interface, int buffer_size, Mutex* lock,
            const char* name);
  ~StubQueue();

  // General queue info
  bool  is_empty() const                         { return _queue_begin == _queue_end; }
  int   total_space() const                      { return _buffer_size - 1; }
  int   available_space() const                  { int d = _queue_begin - _queue_end - 1; return d < 0 ? d + _buffer_size : d; }
  int   used_space() const                       { return total_space() - available_space(); }
  int   number_of_stubs() const                  { return _number_of_stubs; }
  bool  contains(address pc) const               { return _stub_buffer <= pc && pc < _stub_buffer + _buffer_limit; }
  Stub* stub_containing(address pc) const;
  address code_start() const                     { return _stub_buffer; }
  address code_end() const                       { return _stub_buffer + _buffer_limit; }

  // Stub allocation (atomic transactions)
  Stub* request_committed(int code_size);        // request a stub that provides exactly code_size space for code
  Stub* request(int requested_code_size);        // request a stub with a (maximum) code space - locks the queue
208 209
  void  commit (int committed_code_size,
                CodeComments& comments);         // commit the previously requested stub - unlocks the queue
D
duke 已提交
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231

  // Stub deallocation
  void  remove_first();                          // remove the first stub in the queue
  void  remove_first(int n);                     // remove the first n stubs in the queue
  void  remove_all();                            // remove all stubs in the queue

  // Iteration
  static void queues_do(void f(StubQueue* s));   // call f with each StubQueue
  void  stubs_do(void f(Stub* s));               // call f with all stubs
  Stub* first() const                            { return number_of_stubs() > 0 ? stub_at(_queue_begin) : NULL; }
  Stub* next(Stub* s) const                      { int i = index_of(s) + stub_size(s);
                                                   if (i == _buffer_limit) i = 0;
                                                   return (i == _queue_end) ? NULL : stub_at(i);
                                                 }

  address stub_code_begin(Stub* s) const         { return _stub_interface->code_begin(s); }
  address stub_code_end(Stub* s) const           { return _stub_interface->code_end(s);   }

  // Debugging/printing
  void  verify();                                // verifies the stub queue
  void  print();                                 // prints information about the stub queue
};
232 233

#endif // SHARE_VM_CODE_STUBS_HPP