Path: blob/master/src/hotspot/share/code/stubs.cpp
40931 views
/*1* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "code/codeBlob.hpp"26#include "code/codeCache.hpp"27#include "code/stubs.hpp"28#include "memory/allocation.inline.hpp"29#include "oops/oop.inline.hpp"30#include "runtime/mutexLocker.hpp"31#include "utilities/align.hpp"323334// Implementation of StubQueue35//36// Standard wrap-around queue implementation; the queue dimensions37// are specified by the _queue_begin & _queue_end indices. The queue38// can be in two states (transparent to the outside):39//40// a) contiguous state: all queue entries in one block (or empty)41//42// Queue: |...|XXXXXXX|...............|43// ^0 ^begin ^end ^size = limit44// |_______|45// one block46//47// b) non-contiguous state: queue entries in two blocks48//49// Queue: |XXX|.......|XXXXXXX|.......|50// ^0 ^end ^begin ^limit ^size51// |___| |_______|52// 1st block 2nd block53//54// In the non-contiguous state, the wrap-around point is55// indicated via the _buffer_limit index since the last56// queue entry may not fill up the queue completely in57// which case we need to know where the 2nd block's end58// is to do the proper wrap-around. When removing the59// last entry of the 2nd block, _buffer_limit is reset60// to _buffer_size.61//62// CAUTION: DO NOT MESS WITH THIS CODE IF YOU CANNOT PROVE63// ITS CORRECTNESS! THIS CODE IS MORE SUBTLE THAN IT LOOKS!646566StubQueue::StubQueue(StubInterface* stub_interface, int buffer_size,67Mutex* lock, const char* name) : _mutex(lock) {68intptr_t size = align_up(buffer_size, 2*BytesPerWord);69BufferBlob* blob = BufferBlob::create(name, size);70if( blob == NULL) {71vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "CodeCache: no room for %s", name);72}73_stub_interface = stub_interface;74_buffer_size = blob->content_size();75_buffer_limit = blob->content_size();76_stub_buffer = blob->content_begin();77_queue_begin = 0;78_queue_end = 0;79_number_of_stubs = 0;80}818283StubQueue::~StubQueue() {84// Note: Currently StubQueues are never destroyed so nothing needs to be done here.85// If we want to implement the destructor, we need to release the BufferBlob86// allocated in the constructor (i.e., we need to keep it around or look it87// up via CodeCache::find_blob(...).88Unimplemented();89}9091void StubQueue::deallocate_unused_tail() {92CodeBlob* blob = CodeCache::find_blob((void*)_stub_buffer);93CodeCache::free_unused_tail(blob, used_space());94// Update the limits to the new, trimmed CodeBlob size95_buffer_size = blob->content_size();96_buffer_limit = blob->content_size();97}9899Stub* StubQueue::stub_containing(address pc) const {100if (contains(pc)) {101for (Stub* s = first(); s != NULL; s = next(s)) {102if (stub_contains(s, pc)) return s;103}104}105return NULL;106}107108109Stub* StubQueue::request_committed(int code_size) {110Stub* s = request(code_size);111CodeStrings strings;112if (s != NULL) commit(code_size, strings);113return s;114}115116117Stub* StubQueue::request(int requested_code_size) {118assert(requested_code_size > 0, "requested_code_size must be > 0");119if (_mutex != NULL) _mutex->lock_without_safepoint_check();120Stub* s = current_stub();121int requested_size = align_up(stub_code_size_to_size(requested_code_size), CodeEntryAlignment);122if (requested_size <= available_space()) {123if (is_contiguous()) {124// Queue: |...|XXXXXXX|.............|125// ^0 ^begin ^end ^size = limit126assert(_buffer_limit == _buffer_size, "buffer must be fully usable");127if (_queue_end + requested_size <= _buffer_size) {128// code fits in at the end => nothing to do129CodeStrings strings;130stub_initialize(s, requested_size, strings);131return s;132} else {133// stub doesn't fit in at the queue end134// => reduce buffer limit & wrap around135assert(!is_empty(), "just checkin'");136_buffer_limit = _queue_end;137_queue_end = 0;138}139}140}141if (requested_size <= available_space()) {142assert(!is_contiguous(), "just checkin'");143assert(_buffer_limit <= _buffer_size, "queue invariant broken");144// Queue: |XXX|.......|XXXXXXX|.......|145// ^0 ^end ^begin ^limit ^size146s = current_stub();147CodeStrings strings;148stub_initialize(s, requested_size, strings);149return s;150}151// Not enough space left152if (_mutex != NULL) _mutex->unlock();153return NULL;154}155156157void StubQueue::commit(int committed_code_size, CodeStrings& strings) {158assert(committed_code_size > 0, "committed_code_size must be > 0");159int committed_size = align_up(stub_code_size_to_size(committed_code_size), CodeEntryAlignment);160Stub* s = current_stub();161assert(committed_size <= stub_size(s), "committed size must not exceed requested size");162stub_initialize(s, committed_size, strings);163_queue_end += committed_size;164_number_of_stubs++;165if (_mutex != NULL) _mutex->unlock();166debug_only(stub_verify(s);)167}168169170void StubQueue::remove_first() {171if (number_of_stubs() == 0) return;172Stub* s = first();173debug_only(stub_verify(s);)174stub_finalize(s);175_queue_begin += stub_size(s);176assert(_queue_begin <= _buffer_limit, "sanity check");177if (_queue_begin == _queue_end) {178// buffer empty179// => reset queue indices180_queue_begin = 0;181_queue_end = 0;182_buffer_limit = _buffer_size;183} else if (_queue_begin == _buffer_limit) {184// buffer limit reached185// => reset buffer limit & wrap around186_buffer_limit = _buffer_size;187_queue_begin = 0;188}189_number_of_stubs--;190}191192193void StubQueue::remove_first(int n) {194int i = MIN2(n, number_of_stubs());195while (i-- > 0) remove_first();196}197198199void StubQueue::remove_all(){200debug_only(verify();)201remove_first(number_of_stubs());202assert(number_of_stubs() == 0, "sanity check");203}204205206void StubQueue::verify() {207// verify only if initialized208if (_stub_buffer == NULL) return;209MutexLocker lock(_mutex, Mutex::_no_safepoint_check_flag);210// verify index boundaries211guarantee(0 <= _buffer_size, "buffer size must be positive");212guarantee(0 <= _buffer_limit && _buffer_limit <= _buffer_size , "_buffer_limit out of bounds");213guarantee(0 <= _queue_begin && _queue_begin < _buffer_limit, "_queue_begin out of bounds");214guarantee(0 <= _queue_end && _queue_end <= _buffer_limit, "_queue_end out of bounds");215// verify alignment216guarantee(_buffer_size % CodeEntryAlignment == 0, "_buffer_size not aligned");217guarantee(_buffer_limit % CodeEntryAlignment == 0, "_buffer_limit not aligned");218guarantee(_queue_begin % CodeEntryAlignment == 0, "_queue_begin not aligned");219guarantee(_queue_end % CodeEntryAlignment == 0, "_queue_end not aligned");220// verify buffer limit/size relationship221if (is_contiguous()) {222guarantee(_buffer_limit == _buffer_size, "_buffer_limit must equal _buffer_size");223}224// verify contents225int n = 0;226for (Stub* s = first(); s != NULL; s = next(s)) {227stub_verify(s);228n++;229}230guarantee(n == number_of_stubs(), "number of stubs inconsistent");231guarantee(_queue_begin != _queue_end || n == 0, "buffer indices must be the same");232}233234235void StubQueue::print() {236MutexLocker lock(_mutex, Mutex::_no_safepoint_check_flag);237for (Stub* s = first(); s != NULL; s = next(s)) {238stub_print(s);239}240}241242243