提交 7dc0d7c0 编写于 作者: C coleenp

8006040: NPG: on_stack processing wastes space in ConstantPool

Summary: Added on_stack bit to flags.  Also MetadataMarkOnStack is used for more than JVMTI so had to be moved.
Reviewed-by: dholmes, stefank
上级 a1c505a5
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013, 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
......@@ -50,11 +50,12 @@
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceShared.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "memory/oopFactory.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutex.hpp"
#include "runtime/safepoint.hpp"
......
/*
* Copyright (c) 2013, 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 "classfile/metadataOnStackMark.hpp"
#include "code/codeCache.hpp"
#include "compiler/compileBroker.hpp"
#include "oops/metadata.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.hpp"
#include "utilities/growableArray.hpp"
// Keep track of marked on-stack metadata so it can be cleared.
GrowableArray<Metadata*>* _marked_objects = NULL;
NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
// Walk metadata on the stack and mark it so that redefinition doesn't delete
// it. Class unloading also walks the previous versions and might try to
// delete it, so this class is used by class unloading also.
MetadataOnStackMark::MetadataOnStackMark() {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
NOT_PRODUCT(_is_active = true;)
if (_marked_objects == NULL) {
_marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(1000, true);
}
Threads::metadata_do(Metadata::mark_on_stack);
CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
CompileBroker::mark_on_stack();
}
MetadataOnStackMark::~MetadataOnStackMark() {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
// Unmark everything that was marked. Can't do the same walk because
// redefine classes messes up the code cache so the set of methods
// might not be the same.
for (int i = 0; i< _marked_objects->length(); i++) {
_marked_objects->at(i)->set_on_stack(false);
}
_marked_objects->clear(); // reuse growable array for next time.
NOT_PRODUCT(_is_active = false;)
}
// Record which objects are marked so we can unmark the same objects.
void MetadataOnStackMark::record(Metadata* m) {
assert(_is_active, "metadata on stack marking is active");
_marked_objects->push(m);
}
/*
* Copyright (c) 2013, 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.
*
*/
#ifndef SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP
#define SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP
#include "memory/allocation.hpp"
class Metadata;
// Helper class to mark and unmark metadata used on the stack as either handles
// or executing methods, so that it can't be deleted during class redefinition
// and class unloading.
// This is also used for other things that can be deallocated, like class
// metadata during parsing, relocated methods, and methods in backtraces.
class MetadataOnStackMark : public StackObj {
NOT_PRODUCT(static bool _is_active;)
public:
MetadataOnStackMark();
~MetadataOnStackMark();
static void record(Metadata* m);
};
#endif // SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, 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
......@@ -1241,7 +1241,7 @@ void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_kl
void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
assert(EnableInvokeDynamic, "");
pool->set_invokedynamic(); // mark header to flag active call sites
pool->set_has_invokedynamic(); // mark header to flag active call sites
//resolve_pool(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK);
Symbol* method_name = pool->name_ref_at(index);
......
......@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
......@@ -34,7 +35,6 @@
#include "oops/constantPool.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/objArrayKlass.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "runtime/fieldType.hpp"
#include "runtime/init.hpp"
#include "runtime/javaCalls.hpp"
......@@ -65,11 +65,10 @@ ConstantPool::ConstantPool(Array<u1>* tags) {
set_operands(NULL);
set_pool_holder(NULL);
set_flags(0);
// only set to non-zero if constant pool is merged by RedefineClasses
set_version(0);
set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock"));
// all fields are initialized; needed for GC
set_on_stack(false);
// initialize tag array
int length = tags->length();
......@@ -100,18 +99,6 @@ void ConstantPool::release_C_heap_structures() {
set_lock(NULL);
}
void ConstantPool::set_flag_at(FlagBit fb) {
const int MAX_STATE_CHANGES = 2;
for (int i = MAX_STATE_CHANGES + 10; i > 0; i--) {
int oflags = _flags;
int nflags = oflags | (1 << (int)fb);
if (Atomic::cmpxchg(nflags, &_flags, oflags) == oflags)
return;
}
assert(false, "failed to cmpxchg flags");
_flags |= (1 << (int)fb); // better than nothing
}
objArrayOop ConstantPool::resolved_references() const {
return (objArrayOop)JNIHandles::resolve(_resolved_references);
}
......@@ -1755,7 +1742,11 @@ int ConstantPool::copy_cpool_bytes(int cpool_size,
void ConstantPool::set_on_stack(const bool value) {
_on_stack = value;
if (value) {
_flags |= _on_stack;
} else {
_flags &= ~_on_stack;
}
if (value) MetadataOnStackMark::record(this);
}
......@@ -1827,6 +1818,7 @@ void ConstantPool::print_on(outputStream* st) const {
if (has_pseudo_string()) st->print(" has_pseudo_string");
if (has_invokedynamic()) st->print(" has_invokedynamic");
if (has_preresolution()) st->print(" has_preresolution");
if (on_stack()) st->print(" on_stack");
st->cr();
}
if (pool_holder() != NULL) {
......
......@@ -95,10 +95,15 @@ class ConstantPool : public Metadata {
jobject _resolved_references;
Array<u2>* _reference_map;
int _flags; // a few header bits to describe contents for GC
int _length; // number of elements in the array
enum {
_has_invokedynamic = 1, // Flags
_has_pseudo_string = 2,
_has_preresolution = 4,
_on_stack = 8
};
bool _on_stack; // Redefined method still executing refers to this constant pool.
int _flags; // old fashioned bit twiddling
int _length; // number of elements in the array
union {
// set for CDS to restore resolved references
......@@ -115,17 +120,8 @@ class ConstantPool : public Metadata {
void set_operands(Array<u2>* operands) { _operands = operands; }
enum FlagBit {
FB_has_invokedynamic = 1,
FB_has_pseudo_string = 2,
FB_has_preresolution = 3
};
int flags() const { return _flags; }
void set_flags(int f) { _flags = f; }
bool flag_at(FlagBit fb) const { return (_flags & (1 << (int)fb)) != 0; }
void set_flag_at(FlagBit fb);
// no clear_flag_at function; they only increase
int flags() const { return _flags; }
void set_flags(int f) { _flags = f; }
private:
intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); }
......@@ -178,18 +174,20 @@ class ConstantPool : public Metadata {
Array<u1>* tags() const { return _tags; }
Array<u2>* operands() const { return _operands; }
bool has_pseudo_string() const { return flag_at(FB_has_pseudo_string); }
bool has_invokedynamic() const { return flag_at(FB_has_invokedynamic); }
bool has_preresolution() const { return flag_at(FB_has_preresolution); }
void set_pseudo_string() { set_flag_at(FB_has_pseudo_string); }
void set_invokedynamic() { set_flag_at(FB_has_invokedynamic); }
void set_preresolution() { set_flag_at(FB_has_preresolution); }
bool has_invokedynamic() const { return (_flags & _has_invokedynamic) != 0; }
void set_has_invokedynamic() { _flags |= _has_invokedynamic; }
bool has_pseudo_string() const { return (_flags & _has_pseudo_string) != 0; }
void set_has_pseudo_string() { _flags |= _has_pseudo_string; }
bool has_preresolution() const { return (_flags & _has_preresolution) != 0; }
void set_has_preresolution() { _flags |= _has_preresolution; }
// Redefine classes support. If a method refering to this constant pool
// is on the executing stack, or as a handle in vm code, this constant pool
// can't be removed from the set of previous versions saved in the instance
// class.
bool on_stack() const { return _on_stack; }
bool on_stack() const { return (_flags &_on_stack) != 0; }
void set_on_stack(const bool value);
// Klass holding pool
......@@ -457,7 +455,7 @@ class ConstantPool : public Metadata {
void pseudo_string_at_put(int which, int obj_index, oop x) {
assert(EnableInvokeDynamic, "");
set_pseudo_string(); // mark header
set_has_pseudo_string(); // mark header
assert(tag_at(which).is_string(), "Corrupted constant pool");
string_at_put(which, obj_index, x); // this works just fine
}
......
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, 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
......@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/debugInfoRec.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
......@@ -41,7 +42,6 @@
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "prims/methodHandles.hpp"
#include "prims/nativeLookup.hpp"
#include "runtime/arguments.hpp"
......@@ -1027,7 +1027,7 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid,
cp->set_pool_holder(InstanceKlass::cast(holder()));
cp->symbol_at_put(_imcp_invoke_name, name);
cp->symbol_at_put(_imcp_invoke_signature, signature);
cp->set_preresolution();
cp->set_has_preresolution();
// decide on access bits: public or not?
int flags_bits = (JVM_ACC_NATIVE | JVM_ACC_SYNTHETIC | JVM_ACC_FINAL);
......
......@@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/verifier.hpp"
#include "code/codeCache.hpp"
......@@ -115,43 +116,6 @@ bool VM_RedefineClasses::doit_prologue() {
return true;
}
// Keep track of marked on-stack metadata so it can be cleared.
GrowableArray<Metadata*>* _marked_objects = NULL;
NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
// Walk metadata on the stack and mark it so that redefinition doesn't delete
// it. Class unloading also walks the previous versions and might try to
// delete it, so this class is used by class unloading also.
MetadataOnStackMark::MetadataOnStackMark() {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
NOT_PRODUCT(_is_active = true;)
if (_marked_objects == NULL) {
_marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(1000, true);
}
Threads::metadata_do(Metadata::mark_on_stack);
CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
CompileBroker::mark_on_stack();
}
MetadataOnStackMark::~MetadataOnStackMark() {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
// Unmark everything that was marked. Can't do the same walk because
// redefine classes messes up the code cache so the set of methods
// might not be the same.
for (int i = 0; i< _marked_objects->length(); i++) {
_marked_objects->at(i)->set_on_stack(false);
}
_marked_objects->clear(); // reuse growable array for next time.
NOT_PRODUCT(_is_active = false;)
}
// Record which objects are marked so we can unmark the same objects.
void MetadataOnStackMark::record(Metadata* m) {
assert(_is_active, "metadata on stack marking is active");
_marked_objects->push(m);
}
void VM_RedefineClasses::doit() {
Thread *thread = Thread::current();
......
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
......@@ -487,17 +487,4 @@ class VM_RedefineClasses: public VM_Operation {
// and redefine implementation
static bool is_modifiable_class(oop klass_mirror);
};
// Helper class to mark and unmark metadata used on the stack as either handles
// or executing methods, so that it can't be deleted during class redefinition
// and class unloading.
class MetadataOnStackMark : public StackObj {
NOT_PRODUCT(static bool _is_active;)
public:
MetadataOnStackMark() NOT_JVMTI_RETURN;
~MetadataOnStackMark() NOT_JVMTI_RETURN;
static void record(Metadata* m) NOT_JVMTI_RETURN;
};
#endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES_HPP
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册