Mercurial > hg > truffle
diff src/share/vm/code/icBuffer.cpp @ 6725:da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
Summary: Remove PermGen, allocate meta-data in metaspace linked to class loaders, rewrite GC walking, rewrite and rename metadata to be C++ classes
Reviewed-by: jmasa, stefank, never, coleenp, kvn, brutisso, mgerdin, dholmes, jrose, twisti, roland
Contributed-by: jmasa <jon.masamitsu@oracle.com>, stefank <stefan.karlsson@oracle.com>, mgerdin <mikael.gerdin@oracle.com>, never <tom.rodriguez@oracle.com>
author | coleenp |
---|---|
date | Sat, 01 Sep 2012 13:25:18 -0400 |
parents | 1d1603768966 |
children | 7d815d842ee0 cd3d6a6b95d9 |
line wrap: on
line diff
--- a/src/share/vm/code/icBuffer.cpp Fri Aug 31 16:39:35 2012 -0700 +++ b/src/share/vm/code/icBuffer.cpp Sat Sep 01 13:25:18 2012 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2012, 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 @@ -32,7 +32,7 @@ #include "interpreter/linkResolver.hpp" #include "memory/resourceArea.hpp" #include "memory/universe.inline.hpp" -#include "oops/methodOop.hpp" +#include "oops/method.hpp" #include "oops/oop.inline.hpp" #include "oops/oop.inline2.hpp" #include "runtime/mutexLocker.hpp" @@ -59,16 +59,17 @@ StubQueue* InlineCacheBuffer::_buffer = NULL; ICStub* InlineCacheBuffer::_next_stub = NULL; +CompiledICHolder* InlineCacheBuffer::_pending_released = NULL; +int InlineCacheBuffer::_pending_count = 0; void ICStub::finalize() { if (!is_empty()) { ResourceMark rm; - CompiledIC *ic = CompiledIC_at(ic_site()); + CompiledIC *ic = CompiledIC_at(CodeCache::find_nmethod(ic_site()), ic_site()); assert(CodeCache::find_nmethod(ic->instruction_address()) != NULL, "inline cache in non-nmethod?"); assert(this == ICStub_from_destination_address(ic->stub_address()), "wrong owner of ic buffer"); - ic->set_cached_oop(cached_oop()); - ic->set_ic_destination(destination()); + ic->set_ic_destination_and_value(destination(), cached_value()); } } @@ -77,25 +78,28 @@ return InlineCacheBuffer::ic_buffer_entry_point(code_begin()); } -oop ICStub::cached_oop() const { - return InlineCacheBuffer::ic_buffer_cached_oop(code_begin()); +void* ICStub::cached_value() const { + return InlineCacheBuffer::ic_buffer_cached_value(code_begin()); } -void ICStub::set_stub(CompiledIC *ic, oop cached_value, address dest_addr) { +void ICStub::set_stub(CompiledIC *ic, void* cached_val, address dest_addr) { // We cannot store a pointer to the 'ic' object, since it is resource allocated. Instead we // store the location of the inline cache. Then we have enough information recreate the CompiledIC // object when we need to remove the stub. _ic_site = ic->instruction_address(); // Assemble new stub - InlineCacheBuffer::assemble_ic_buffer_code(code_begin(), cached_value, dest_addr); + InlineCacheBuffer::assemble_ic_buffer_code(code_begin(), cached_val, dest_addr); assert(destination() == dest_addr, "can recover destination"); - assert(cached_oop() == cached_value, "can recover destination"); + assert(cached_value() == cached_val, "can recover destination"); } void ICStub::clear() { + if (CompiledIC::is_icholder_entry(destination())) { + InlineCacheBuffer::queue_for_release((CompiledICHolder*)cached_value()); + } _ic_site = NULL; } @@ -161,6 +165,7 @@ buffer()->remove_all(); init_next_stub(); } + release_pending_icholders(); } @@ -179,11 +184,13 @@ } -void InlineCacheBuffer::create_transition_stub(CompiledIC *ic, oop cached_oop, address entry) { +void InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_value, address entry) { assert(!SafepointSynchronize::is_at_safepoint(), "should not be called during a safepoint"); assert (CompiledIC_lock->is_locked(), ""); - assert(cached_oop == NULL || cached_oop->is_perm(), "must belong to perm. space"); - if (TraceICBuffer) { tty->print_cr(" create transition stub for " INTPTR_FORMAT, ic->instruction_address()); } + if (TraceICBuffer) { + tty->print_cr(" create transition stub for " INTPTR_FORMAT " destination " INTPTR_FORMAT " cached value " INTPTR_FORMAT, + ic->instruction_address(), entry, cached_value); + } // If an transition stub is already associate with the inline cache, then we remove the association. if (ic->is_in_transition_state()) { @@ -193,10 +200,10 @@ // allocate and initialize new "out-of-line" inline-cache ICStub* ic_stub = get_next_stub(); - ic_stub->set_stub(ic, cached_oop, entry); + ic_stub->set_stub(ic, cached_value, entry); // Update inline cache in nmethod to point to new "out-of-line" allocated inline cache - ic->set_ic_destination(ic_stub->code_begin()); + ic->set_ic_destination(ic_stub); set_next_stub(new_ic_stub()); // can cause safepoint synchronization } @@ -208,7 +215,35 @@ } -oop InlineCacheBuffer::cached_oop_for(CompiledIC *ic) { +void* InlineCacheBuffer::cached_value_for(CompiledIC *ic) { ICStub* stub = ICStub_from_destination_address(ic->stub_address()); - return stub->cached_oop(); + return stub->cached_value(); } + + +// Free CompiledICHolder*s that are no longer in use +void InlineCacheBuffer::release_pending_icholders() { + assert(SafepointSynchronize::is_at_safepoint(), "should only be called during a safepoint"); + CompiledICHolder* holder = _pending_released; + _pending_released = NULL; + while (holder != NULL) { + CompiledICHolder* next = holder->next(); + delete holder; + holder = next; + _pending_count--; + } + assert(_pending_count == 0, "wrong count"); +} + +// Enqueue this icholder for release during the next safepoint. It's +// not safe to free them until them since they might be visible to +// another thread. +void InlineCacheBuffer::queue_for_release(CompiledICHolder* icholder) { + MutexLockerEx mex(InlineCacheBuffer_lock); + icholder->set_next(_pending_released); + _pending_released = icholder; + _pending_count++; + if (TraceICBuffer) { + tty->print_cr("enqueueing icholder " INTPTR_FORMAT " to be freed", icholder); + } +}