1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/code/stubs.hpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,236 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#ifndef SHARE_VM_CODE_STUBS_HPP 1.29 +#define SHARE_VM_CODE_STUBS_HPP 1.30 + 1.31 +#include "asm/codeBuffer.hpp" 1.32 +#include "memory/allocation.hpp" 1.33 +#ifdef TARGET_OS_FAMILY_linux 1.34 +# include "os_linux.inline.hpp" 1.35 +#endif 1.36 +#ifdef TARGET_OS_FAMILY_solaris 1.37 +# include "os_solaris.inline.hpp" 1.38 +#endif 1.39 +#ifdef TARGET_OS_FAMILY_windows 1.40 +# include "os_windows.inline.hpp" 1.41 +#endif 1.42 +#ifdef TARGET_OS_FAMILY_aix 1.43 +# include "os_aix.inline.hpp" 1.44 +#endif 1.45 +#ifdef TARGET_OS_FAMILY_bsd 1.46 +# include "os_bsd.inline.hpp" 1.47 +#endif 1.48 + 1.49 +// The classes in this file provide a simple framework for the 1.50 +// management of little pieces of machine code - or stubs - 1.51 +// created on the fly and frequently discarded. In this frame- 1.52 +// work stubs are stored in a queue. 1.53 + 1.54 + 1.55 +// Stub serves as abstract base class. A concrete stub 1.56 +// implementation is a subclass of Stub, implementing 1.57 +// all (non-virtual!) functions required sketched out 1.58 +// in the Stub class. 1.59 +// 1.60 +// A concrete stub layout may look like this (both data 1.61 +// and code sections could be empty as well): 1.62 +// 1.63 +// ________ 1.64 +// stub -->| | <--+ 1.65 +// | data | | 1.66 +// |________| | 1.67 +// code_begin -->| | | 1.68 +// | | | 1.69 +// | code | | size 1.70 +// | | | 1.71 +// |________| | 1.72 +// code_end -->| | | 1.73 +// | data | | 1.74 +// |________| | 1.75 +// <--+ 1.76 + 1.77 + 1.78 +class Stub VALUE_OBJ_CLASS_SPEC { 1.79 + public: 1.80 + // Initialization/finalization 1.81 + void initialize(int size, 1.82 + CodeStrings& strings) { ShouldNotCallThis(); } // called to initialize/specify the stub's size 1.83 + void finalize() { ShouldNotCallThis(); } // called before the stub is deallocated 1.84 + 1.85 + // General info/converters 1.86 + int size() const { ShouldNotCallThis(); return 0; } // must return the size provided by initialize 1.87 + static int code_size_to_size(int code_size) { ShouldNotCallThis(); return 0; } // computes the size given the code size 1.88 + 1.89 + // Code info 1.90 + address code_begin() const { ShouldNotCallThis(); return NULL; } // points to the first byte of the code 1.91 + address code_end() const { ShouldNotCallThis(); return NULL; } // points to the first byte after the code 1.92 + 1.93 + // Debugging 1.94 + void verify() { ShouldNotCallThis(); } // verifies the Stub 1.95 + void print() { ShouldNotCallThis(); } // prints some information about the stub 1.96 +}; 1.97 + 1.98 + 1.99 +// A stub interface defines the interface between a stub queue 1.100 +// and the stubs it queues. In order to avoid a vtable and 1.101 +// (and thus the extra word) in each stub, a concrete stub 1.102 +// interface object is created and associated with a stub 1.103 +// buffer which in turn uses the stub interface to interact 1.104 +// with its stubs. 1.105 +// 1.106 +// StubInterface serves as an abstract base class. A concrete 1.107 +// stub interface implementation is a subclass of StubInterface, 1.108 +// forwarding its virtual function calls to non-virtual calls 1.109 +// of the concrete stub (see also macro below). There's exactly 1.110 +// one stub interface instance required per stub queue. 1.111 + 1.112 +class StubInterface: public CHeapObj<mtCode> { 1.113 + public: 1.114 + // Initialization/finalization 1.115 + virtual void initialize(Stub* self, int size, 1.116 + CodeStrings& strings) = 0; // called after creation (called twice if allocated via (request, commit)) 1.117 + virtual void finalize(Stub* self) = 0; // called before deallocation 1.118 + 1.119 + // General info/converters 1.120 + virtual int size(Stub* self) const = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment) 1.121 + virtual int code_size_to_size(int code_size) const = 0; // computes the total stub size in bytes given the code size in bytes 1.122 + 1.123 + // Code info 1.124 + virtual address code_begin(Stub* self) const = 0; // points to the first code byte 1.125 + virtual address code_end(Stub* self) const = 0; // points to the first byte after the code 1.126 + 1.127 + // Debugging 1.128 + virtual void verify(Stub* self) = 0; // verifies the stub 1.129 + virtual void print(Stub* self) = 0; // prints information about the stub 1.130 +}; 1.131 + 1.132 + 1.133 +// DEF_STUB_INTERFACE is used to create a concrete stub interface 1.134 +// class, forwarding stub interface calls to the corresponding 1.135 +// stub calls. 1.136 + 1.137 +#define DEF_STUB_INTERFACE(stub) \ 1.138 + class stub##Interface: public StubInterface { \ 1.139 + private: \ 1.140 + static stub* cast(Stub* self) { return (stub*)self; } \ 1.141 + \ 1.142 + public: \ 1.143 + /* Initialization/finalization */ \ 1.144 + virtual void initialize(Stub* self, int size, \ 1.145 + CodeStrings& strings) { cast(self)->initialize(size, strings); } \ 1.146 + virtual void finalize(Stub* self) { cast(self)->finalize(); } \ 1.147 + \ 1.148 + /* General info */ \ 1.149 + virtual int size(Stub* self) const { return cast(self)->size(); } \ 1.150 + virtual int code_size_to_size(int code_size) const { return stub::code_size_to_size(code_size); } \ 1.151 + \ 1.152 + /* Code info */ \ 1.153 + virtual address code_begin(Stub* self) const { return cast(self)->code_begin(); } \ 1.154 + virtual address code_end(Stub* self) const { return cast(self)->code_end(); } \ 1.155 + \ 1.156 + /* Debugging */ \ 1.157 + virtual void verify(Stub* self) { cast(self)->verify(); } \ 1.158 + virtual void print(Stub* self) { cast(self)->print(); } \ 1.159 + }; 1.160 + 1.161 + 1.162 +// A StubQueue maintains a queue of stubs. 1.163 +// Note: All sizes (spaces) are given in bytes. 1.164 + 1.165 +class StubQueue: public CHeapObj<mtCode> { 1.166 + friend class VMStructs; 1.167 + private: 1.168 + StubInterface* _stub_interface; // the interface prototype 1.169 + address _stub_buffer; // where all stubs are stored 1.170 + int _buffer_size; // the buffer size in bytes 1.171 + int _buffer_limit; // the (byte) index of the actual buffer limit (_buffer_limit <= _buffer_size) 1.172 + int _queue_begin; // the (byte) index of the first queue entry (word-aligned) 1.173 + int _queue_end; // the (byte) index of the first entry after the queue (word-aligned) 1.174 + int _number_of_stubs; // the number of buffered stubs 1.175 + Mutex* const _mutex; // the lock used for a (request, commit) transaction 1.176 + 1.177 + void check_index(int i) const { assert(0 <= i && i < _buffer_limit && i % CodeEntryAlignment == 0, "illegal index"); } 1.178 + bool is_contiguous() const { return _queue_begin <= _queue_end; } 1.179 + int index_of(Stub* s) const { int i = (address)s - _stub_buffer; check_index(i); return i; } 1.180 + Stub* stub_at(int i) const { check_index(i); return (Stub*)(_stub_buffer + i); } 1.181 + Stub* current_stub() const { return stub_at(_queue_end); } 1.182 + 1.183 + // Stub functionality accessed via interface 1.184 + void stub_initialize(Stub* s, int size, 1.185 + CodeStrings& strings) { assert(size % CodeEntryAlignment == 0, "size not aligned"); _stub_interface->initialize(s, size, strings); } 1.186 + void stub_finalize(Stub* s) { _stub_interface->finalize(s); } 1.187 + int stub_size(Stub* s) const { return _stub_interface->size(s); } 1.188 + bool stub_contains(Stub* s, address pc) const { return _stub_interface->code_begin(s) <= pc && pc < _stub_interface->code_end(s); } 1.189 + int stub_code_size_to_size(int code_size) const { return _stub_interface->code_size_to_size(code_size); } 1.190 + void stub_verify(Stub* s) { _stub_interface->verify(s); } 1.191 + void stub_print(Stub* s) { _stub_interface->print(s); } 1.192 + 1.193 + static void register_queue(StubQueue*); 1.194 + 1.195 + public: 1.196 + StubQueue(StubInterface* stub_interface, int buffer_size, Mutex* lock, 1.197 + const char* name); 1.198 + ~StubQueue(); 1.199 + 1.200 + // General queue info 1.201 + bool is_empty() const { return _queue_begin == _queue_end; } 1.202 + int total_space() const { return _buffer_size - 1; } 1.203 + int available_space() const { int d = _queue_begin - _queue_end - 1; return d < 0 ? d + _buffer_size : d; } 1.204 + int used_space() const { return total_space() - available_space(); } 1.205 + int number_of_stubs() const { return _number_of_stubs; } 1.206 + bool contains(address pc) const { return _stub_buffer <= pc && pc < _stub_buffer + _buffer_limit; } 1.207 + Stub* stub_containing(address pc) const; 1.208 + address code_start() const { return _stub_buffer; } 1.209 + address code_end() const { return _stub_buffer + _buffer_limit; } 1.210 + 1.211 + // Stub allocation (atomic transactions) 1.212 + Stub* request_committed(int code_size); // request a stub that provides exactly code_size space for code 1.213 + Stub* request(int requested_code_size); // request a stub with a (maximum) code space - locks the queue 1.214 + void commit (int committed_code_size, 1.215 + CodeStrings& strings); // commit the previously requested stub - unlocks the queue 1.216 + 1.217 + // Stub deallocation 1.218 + void remove_first(); // remove the first stub in the queue 1.219 + void remove_first(int n); // remove the first n stubs in the queue 1.220 + void remove_all(); // remove all stubs in the queue 1.221 + 1.222 + // Iteration 1.223 + static void queues_do(void f(StubQueue* s)); // call f with each StubQueue 1.224 + void stubs_do(void f(Stub* s)); // call f with all stubs 1.225 + Stub* first() const { return number_of_stubs() > 0 ? stub_at(_queue_begin) : NULL; } 1.226 + Stub* next(Stub* s) const { int i = index_of(s) + stub_size(s); 1.227 + if (i == _buffer_limit) i = 0; 1.228 + return (i == _queue_end) ? NULL : stub_at(i); 1.229 + } 1.230 + 1.231 + address stub_code_begin(Stub* s) const { return _stub_interface->code_begin(s); } 1.232 + address stub_code_end(Stub* s) const { return _stub_interface->code_end(s); } 1.233 + 1.234 + // Debugging/printing 1.235 + void verify(); // verifies the stub queue 1.236 + void print(); // prints information about the stub queue 1.237 +}; 1.238 + 1.239 +#endif // SHARE_VM_CODE_STUBS_HPP