Mercurial > hg > graal-compiler
view src/share/vm/code/codeBlob.cpp @ 3992:d1bdeef3e3e2
7098282: G1: assert(interval >= 0) failed: Sanity check, referencePolicy.cpp: 76
Summary: There is a race between one thread successfully forwarding and copying the klass mirror for the SoftReference class (including the static master clock) and another thread attempting to use the master clock while attempting to discover a soft reference object. Maintain a shadow copy of the soft reference master clock and use the shadow during reference discovery and reference processing.
Reviewed-by: tonyp, brutisso, ysr
author | johnc |
---|---|
date | Wed, 12 Oct 2011 10:25:51 -0700 |
parents | 167b70ff3abc |
children | d2a62e0f25eb |
line wrap: on
line source
/* * Copyright (c) 1998, 2011, 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 * 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. * * 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. * */ #include "precompiled.hpp" #include "code/codeBlob.hpp" #include "code/codeCache.hpp" #include "code/relocInfo.hpp" #include "compiler/disassembler.hpp" #include "interpreter/bytecode.hpp" #include "memory/allocation.inline.hpp" #include "memory/heap.hpp" #include "oops/oop.inline.hpp" #include "prims/forte.hpp" #include "runtime/handles.inline.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/vframe.hpp" #include "services/memoryService.hpp" #ifdef TARGET_ARCH_x86 # include "nativeInst_x86.hpp" #endif #ifdef TARGET_ARCH_sparc # include "nativeInst_sparc.hpp" #endif #ifdef TARGET_ARCH_zero # include "nativeInst_zero.hpp" #endif #ifdef TARGET_ARCH_arm # include "nativeInst_arm.hpp" #endif #ifdef TARGET_ARCH_ppc # include "nativeInst_ppc.hpp" #endif #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #endif unsigned int align_code_offset(int offset) { // align the size to CodeEntryAlignment return ((offset + (int)CodeHeap::header_size() + (CodeEntryAlignment-1)) & ~(CodeEntryAlignment-1)) - (int)CodeHeap::header_size(); } // This must be consistent with the CodeBlob constructor's layout actions. unsigned int CodeBlob::allocation_size(CodeBuffer* cb, int header_size) { unsigned int size = header_size; size += round_to(cb->total_relocation_size(), oopSize); // align the size to CodeEntryAlignment size = align_code_offset(size); size += round_to(cb->total_content_size(), oopSize); size += round_to(cb->total_oop_size(), oopSize); return size; } // Creates a simple CodeBlob. Sets up the size of the different regions. CodeBlob::CodeBlob(const char* name, int header_size, int size, int frame_complete, int locs_size) { assert(size == round_to(size, oopSize), "unaligned size"); assert(locs_size == round_to(locs_size, oopSize), "unaligned size"); assert(header_size == round_to(header_size, oopSize), "unaligned size"); assert(!UseRelocIndex, "no space allocated for reloc index yet"); // Note: If UseRelocIndex is enabled, there needs to be (at least) one // extra word for the relocation information, containing the reloc // index table length. Unfortunately, the reloc index table imple- // mentation is not easily understandable and thus it is not clear // what exactly the format is supposed to be. For now, we just turn // off the use of this table (gri 7/6/2000). _name = name; _size = size; _frame_complete_offset = frame_complete; _header_size = header_size; _relocation_size = locs_size; _content_offset = align_code_offset(header_size + _relocation_size); _code_offset = _content_offset; _data_offset = size; _frame_size = 0; set_oop_maps(NULL); } // Creates a CodeBlob from a CodeBuffer. Sets up the size of the different regions, // and copy code and relocation info. CodeBlob::CodeBlob( const char* name, CodeBuffer* cb, int header_size, int size, int frame_complete, int frame_size, OopMapSet* oop_maps ) { assert(size == round_to(size, oopSize), "unaligned size"); assert(header_size == round_to(header_size, oopSize), "unaligned size"); _name = name; _size = size; _frame_complete_offset = frame_complete; _header_size = header_size; _relocation_size = round_to(cb->total_relocation_size(), oopSize); _content_offset = 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(_data_offset <= size, "codeBlob is too small"); cb->copy_code_and_locs_to(this); set_oop_maps(oop_maps); _frame_size = frame_size; #ifdef COMPILER1 // probably wrong for tiered assert(_frame_size >= -1, "must use frame size or -1 for runtime stubs"); #endif // COMPILER1 } void CodeBlob::set_oop_maps(OopMapSet* p) { // Danger Will Robinson! This method allocates a big // chunk of memory, its your job to free it. if (p != NULL) { // We need to allocate a chunk big enough to hold the OopMapSet and all of its OopMaps _oop_maps = (OopMapSet* )NEW_C_HEAP_ARRAY(unsigned char, p->heap_size()); p->copy_to((address)_oop_maps); } else { _oop_maps = NULL; } } void CodeBlob::trace_new_stub(CodeBlob* stub, const char* name1, const char* name2) { // Do not hold the CodeCache lock during name formatting. assert(!CodeCache_lock->owned_by_self(), "release CodeCache before registering the stub"); if (stub != NULL) { char stub_id[256]; assert(strlen(name1) + strlen(name2) < sizeof(stub_id), ""); jio_snprintf(stub_id, sizeof(stub_id), "%s%s", name1, name2); if (PrintStubCode) { tty->print_cr("Decoding %s " INTPTR_FORMAT, stub_id, (intptr_t) stub); Disassembler::decode(stub->code_begin(), stub->code_end()); } Forte::register_stub(stub_id, stub->code_begin(), stub->code_end()); if (JvmtiExport::should_post_dynamic_code_generated()) { const char* stub_name = name2; if (name2[0] == '\0') stub_name = name1; JvmtiExport::post_dynamic_code_generated(stub_name, stub->code_begin(), stub->code_end()); } } // Track memory usage statistic after releasing CodeCache_lock MemoryService::track_code_cache_memory_usage(); } void CodeBlob::flush() { if (_oop_maps) { FREE_C_HEAP_ARRAY(unsigned char, _oop_maps); _oop_maps = NULL; } _comments.free(); } OopMap* CodeBlob::oop_map_for_return_address(address return_address) { assert(oop_maps() != NULL, "nope"); return oop_maps()->find_map_at_offset((intptr_t) return_address - (intptr_t) code_begin()); } //---------------------------------------------------------------------------------------------------- // Implementation of BufferBlob BufferBlob::BufferBlob(const char* name, int size) : CodeBlob(name, sizeof(BufferBlob), size, CodeOffsets::frame_never_safe, /*locs_size:*/ 0) {} BufferBlob* BufferBlob::create(const char* name, int buffer_size) { ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock BufferBlob* blob = NULL; unsigned int size = sizeof(BufferBlob); // align the size to CodeEntryAlignment size = align_code_offset(size); size += round_to(buffer_size, oopSize); assert(name != NULL, "must provide a name"); { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = new (size) BufferBlob(name, size); } // Track memory usage statistic after releasing CodeCache_lock MemoryService::track_code_cache_memory_usage(); return blob; } BufferBlob::BufferBlob(const char* name, int size, CodeBuffer* cb) : CodeBlob(name, cb, sizeof(BufferBlob), size, CodeOffsets::frame_never_safe, 0, NULL) {} BufferBlob* BufferBlob::create(const char* name, CodeBuffer* cb) { ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock BufferBlob* blob = NULL; unsigned int size = allocation_size(cb, sizeof(BufferBlob)); assert(name != NULL, "must provide a name"); { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = new (size) BufferBlob(name, size, cb); } // Track memory usage statistic after releasing CodeCache_lock MemoryService::track_code_cache_memory_usage(); return blob; } void* BufferBlob::operator new(size_t s, unsigned size) { void* p = CodeCache::allocate(size); return p; } void BufferBlob::free( BufferBlob *blob ) { ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); CodeCache::free((CodeBlob*)blob); } // Track memory usage statistic after releasing CodeCache_lock MemoryService::track_code_cache_memory_usage(); } //---------------------------------------------------------------------------------------------------- // Implementation of AdapterBlob AdapterBlob::AdapterBlob(int size, CodeBuffer* cb) : BufferBlob("I2C/C2I adapters", size, cb) { CodeCache::commit(this); } AdapterBlob* AdapterBlob::create(CodeBuffer* cb) { ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock AdapterBlob* blob = NULL; unsigned int size = allocation_size(cb, sizeof(AdapterBlob)); { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = new (size) AdapterBlob(size, cb); } // Track memory usage statistic after releasing CodeCache_lock MemoryService::track_code_cache_memory_usage(); return blob; } //---------------------------------------------------------------------------------------------------- // Implementation of MethodHandlesAdapterBlob MethodHandlesAdapterBlob* MethodHandlesAdapterBlob::create(int buffer_size) { ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock MethodHandlesAdapterBlob* blob = NULL; unsigned int size = sizeof(MethodHandlesAdapterBlob); // align the size to CodeEntryAlignment size = align_code_offset(size); size += round_to(buffer_size, oopSize); { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); blob = new (size) MethodHandlesAdapterBlob(size); } // Track memory usage statistic after releasing CodeCache_lock MemoryService::track_code_cache_memory_usage(); return blob; } //---------------------------------------------------------------------------------------------------- // Implementation of RuntimeStub RuntimeStub::RuntimeStub( const char* name, CodeBuffer* cb, int size, int frame_complete, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments ) : CodeBlob(name, cb, sizeof(RuntimeStub), size, frame_complete, frame_size, oop_maps) { _caller_must_gc_arguments = caller_must_gc_arguments; } RuntimeStub* RuntimeStub::new_runtime_stub(const char* stub_name, CodeBuffer* cb, int frame_complete, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments) { RuntimeStub* stub = NULL; ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); unsigned int size = allocation_size(cb, sizeof(RuntimeStub)); stub = new (size) RuntimeStub(stub_name, cb, size, frame_complete, frame_size, oop_maps, caller_must_gc_arguments); } trace_new_stub(stub, "RuntimeStub - ", stub_name); return stub; } void* RuntimeStub::operator new(size_t s, unsigned size) { void* p = CodeCache::allocate(size); if (!p) fatal("Initial size of CodeCache is too small"); return p; } // operator new shared by all singletons: void* SingletonBlob::operator new(size_t s, unsigned size) { void* p = CodeCache::allocate(size); if (!p) fatal("Initial size of CodeCache is too small"); return p; } //---------------------------------------------------------------------------------------------------- // Implementation of RicochetBlob RicochetBlob::RicochetBlob( CodeBuffer* cb, int size, int bounce_offset, int exception_offset, int frame_size ) : SingletonBlob("RicochetBlob", cb, sizeof(RicochetBlob), size, frame_size, (OopMapSet*) NULL) { _bounce_offset = bounce_offset; _exception_offset = exception_offset; } RicochetBlob* RicochetBlob::create( CodeBuffer* cb, int bounce_offset, int exception_offset, int frame_size) { RicochetBlob* blob = NULL; ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); unsigned int size = allocation_size(cb, sizeof(RicochetBlob)); blob = new (size) RicochetBlob(cb, size, bounce_offset, exception_offset, frame_size); } trace_new_stub(blob, "RicochetBlob"); return blob; } //---------------------------------------------------------------------------------------------------- // Implementation of DeoptimizationBlob DeoptimizationBlob::DeoptimizationBlob( CodeBuffer* cb, int size, OopMapSet* oop_maps, int unpack_offset, int unpack_with_exception_offset, int unpack_with_reexecution_offset, int frame_size ) : SingletonBlob("DeoptimizationBlob", cb, sizeof(DeoptimizationBlob), size, frame_size, oop_maps) { _unpack_offset = unpack_offset; _unpack_with_exception = unpack_with_exception_offset; _unpack_with_reexecution = unpack_with_reexecution_offset; #ifdef COMPILER1 _unpack_with_exception_in_tls = -1; #endif } DeoptimizationBlob* DeoptimizationBlob::create( CodeBuffer* cb, OopMapSet* oop_maps, int unpack_offset, int unpack_with_exception_offset, int unpack_with_reexecution_offset, int frame_size) { DeoptimizationBlob* blob = NULL; ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); unsigned int size = allocation_size(cb, sizeof(DeoptimizationBlob)); blob = new (size) DeoptimizationBlob(cb, size, oop_maps, unpack_offset, unpack_with_exception_offset, unpack_with_reexecution_offset, frame_size); } trace_new_stub(blob, "DeoptimizationBlob"); return blob; } //---------------------------------------------------------------------------------------------------- // Implementation of UncommonTrapBlob #ifdef COMPILER2 UncommonTrapBlob::UncommonTrapBlob( CodeBuffer* cb, int size, OopMapSet* oop_maps, int frame_size ) : SingletonBlob("UncommonTrapBlob", cb, sizeof(UncommonTrapBlob), size, frame_size, oop_maps) {} UncommonTrapBlob* UncommonTrapBlob::create( CodeBuffer* cb, OopMapSet* oop_maps, int frame_size) { UncommonTrapBlob* blob = NULL; ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); unsigned int size = allocation_size(cb, sizeof(UncommonTrapBlob)); blob = new (size) UncommonTrapBlob(cb, size, oop_maps, frame_size); } trace_new_stub(blob, "UncommonTrapBlob"); return blob; } #endif // COMPILER2 //---------------------------------------------------------------------------------------------------- // Implementation of ExceptionBlob #ifdef COMPILER2 ExceptionBlob::ExceptionBlob( CodeBuffer* cb, int size, OopMapSet* oop_maps, int frame_size ) : SingletonBlob("ExceptionBlob", cb, sizeof(ExceptionBlob), size, frame_size, oop_maps) {} ExceptionBlob* ExceptionBlob::create( CodeBuffer* cb, OopMapSet* oop_maps, int frame_size) { ExceptionBlob* blob = NULL; ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); unsigned int size = allocation_size(cb, sizeof(ExceptionBlob)); blob = new (size) ExceptionBlob(cb, size, oop_maps, frame_size); } trace_new_stub(blob, "ExceptionBlob"); return blob; } #endif // COMPILER2 //---------------------------------------------------------------------------------------------------- // Implementation of SafepointBlob SafepointBlob::SafepointBlob( CodeBuffer* cb, int size, OopMapSet* oop_maps, int frame_size ) : SingletonBlob("SafepointBlob", cb, sizeof(SafepointBlob), size, frame_size, oop_maps) {} SafepointBlob* SafepointBlob::create( CodeBuffer* cb, OopMapSet* oop_maps, int frame_size) { SafepointBlob* blob = NULL; ThreadInVMfromUnknown __tiv; // get to VM state in case we block on CodeCache_lock { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); unsigned int size = allocation_size(cb, sizeof(SafepointBlob)); blob = new (size) SafepointBlob(cb, size, oop_maps, frame_size); } trace_new_stub(blob, "SafepointBlob"); return blob; } //---------------------------------------------------------------------------------------------------- // Verification and printing void CodeBlob::verify() { ShouldNotReachHere(); } void CodeBlob::print_on(outputStream* st) const { st->print_cr("[CodeBlob (" INTPTR_FORMAT ")]", this); st->print_cr("Framesize: %d", _frame_size); } void CodeBlob::print_value_on(outputStream* st) const { st->print_cr("[CodeBlob]"); } void BufferBlob::verify() { // unimplemented } void BufferBlob::print_on(outputStream* st) const { CodeBlob::print_on(st); print_value_on(st); } void BufferBlob::print_value_on(outputStream* st) const { st->print_cr("BufferBlob (" INTPTR_FORMAT ") used for %s", this, name()); } void RuntimeStub::verify() { // unimplemented } void RuntimeStub::print_on(outputStream* st) const { CodeBlob::print_on(st); st->print("Runtime Stub (" INTPTR_FORMAT "): ", this); st->print_cr(name()); Disassembler::decode((CodeBlob*)this, st); } void RuntimeStub::print_value_on(outputStream* st) const { st->print("RuntimeStub (" INTPTR_FORMAT "): ", this); st->print(name()); } void SingletonBlob::verify() { // unimplemented } void SingletonBlob::print_on(outputStream* st) const { CodeBlob::print_on(st); st->print_cr(name()); Disassembler::decode((CodeBlob*)this, st); } void SingletonBlob::print_value_on(outputStream* st) const { st->print_cr(name()); } void DeoptimizationBlob::print_value_on(outputStream* st) const { st->print_cr("Deoptimization (frame not available)"); }