提交 98acb3e8 编写于 作者: Z zgu

Merge

...@@ -155,6 +155,7 @@ SUNWprivate_1.1 { ...@@ -155,6 +155,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxNameUTF; JVM_GetMethodIxNameUTF;
JVM_GetMethodIxSignatureUTF; JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameterAnnotations; JVM_GetMethodParameterAnnotations;
JVM_GetMethodParameters;
JVM_GetPrimitiveArrayElement; JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain; JVM_GetProtectionDomain;
JVM_GetSockName; JVM_GetSockName;
......
...@@ -155,6 +155,7 @@ SUNWprivate_1.1 { ...@@ -155,6 +155,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxNameUTF; JVM_GetMethodIxNameUTF;
JVM_GetMethodIxSignatureUTF; JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameterAnnotations; JVM_GetMethodParameterAnnotations;
JVM_GetMethodParameters;
JVM_GetPrimitiveArrayElement; JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain; JVM_GetProtectionDomain;
JVM_GetSockName; JVM_GetSockName;
......
...@@ -151,6 +151,7 @@ SUNWprivate_1.1 { ...@@ -151,6 +151,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxNameUTF; JVM_GetMethodIxNameUTF;
JVM_GetMethodIxSignatureUTF; JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameterAnnotations; JVM_GetMethodParameterAnnotations;
JVM_GetMethodParameters;
JVM_GetPrimitiveArrayElement; JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain; JVM_GetProtectionDomain;
JVM_GetSockName; JVM_GetSockName;
......
...@@ -151,6 +151,7 @@ SUNWprivate_1.1 { ...@@ -151,6 +151,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxNameUTF; JVM_GetMethodIxNameUTF;
JVM_GetMethodIxSignatureUTF; JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameterAnnotations; JVM_GetMethodParameterAnnotations;
JVM_GetMethodParameters;
JVM_GetPrimitiveArrayElement; JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain; JVM_GetProtectionDomain;
JVM_GetSockName; JVM_GetSockName;
......
...@@ -151,6 +151,7 @@ SUNWprivate_1.1 { ...@@ -151,6 +151,7 @@ SUNWprivate_1.1 {
JVM_GetMethodIxNameUTF; JVM_GetMethodIxNameUTF;
JVM_GetMethodIxSignatureUTF; JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameterAnnotations; JVM_GetMethodParameterAnnotations;
JVM_GetMethodParameters;
JVM_GetPrimitiveArrayElement; JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain; JVM_GetProtectionDomain;
JVM_GetSockName; JVM_GetSockName;
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -1935,6 +1935,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -1935,6 +1935,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
u2** localvariable_table_start; u2** localvariable_table_start;
u2* localvariable_type_table_length; u2* localvariable_type_table_length;
u2** localvariable_type_table_start; u2** localvariable_type_table_start;
u2 method_parameters_length = 0;
u1* method_parameters_data = NULL;
bool parsed_code_attribute = false; bool parsed_code_attribute = false;
bool parsed_checked_exceptions_attribute = false; bool parsed_checked_exceptions_attribute = false;
bool parsed_stackmap_attribute = false; bool parsed_stackmap_attribute = false;
...@@ -2144,6 +2146,14 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2144,6 +2146,14 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
parse_checked_exceptions(&checked_exceptions_length, parse_checked_exceptions(&checked_exceptions_length,
method_attribute_length, method_attribute_length,
cp, CHECK_(nullHandle)); cp, CHECK_(nullHandle));
} else if (method_attribute_name == vmSymbols::tag_method_parameters()) {
method_parameters_length = cfs->get_u1_fast();
method_parameters_data = cfs->get_u1_buffer();
cfs->skip_u2_fast(method_parameters_length);
cfs->skip_u4_fast(method_parameters_length);
// ignore this attribute if it cannot be reflected
if (!SystemDictionary::Parameter_klass_loaded())
method_parameters_length = 0;
} else if (method_attribute_name == vmSymbols::tag_synthetic()) { } else if (method_attribute_name == vmSymbols::tag_synthetic()) {
if (method_attribute_length != 0) { if (method_attribute_length != 0) {
classfile_parse_error( classfile_parse_error(
...@@ -2231,7 +2241,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2231,7 +2241,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
Method* m = Method::allocate( Method* m = Method::allocate(
loader_data, code_length, access_flags, linenumber_table_length, loader_data, code_length, access_flags, linenumber_table_length,
total_lvt_length, exception_table_length, checked_exceptions_length, total_lvt_length, exception_table_length, checked_exceptions_length,
generic_signature_index, ConstMethod::NORMAL, CHECK_(nullHandle)); method_parameters_length, generic_signature_index,
ConstMethod::NORMAL, CHECK_(nullHandle));
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize); ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
...@@ -2279,6 +2290,18 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data, ...@@ -2279,6 +2290,18 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
exception_table_start, size); exception_table_start, size);
} }
// Copy method parameters
if (method_parameters_length > 0) {
MethodParametersElement* elem = m->constMethod()->method_parameters_start();
for(int i = 0; i < method_parameters_length; i++) {
elem[i].name_cp_index =
Bytes::get_Java_u2(method_parameters_data);
method_parameters_data += 2;
elem[i].flags = Bytes::get_Java_u4(method_parameters_data);
method_parameters_data += 4;
}
}
// Copy checked exceptions // Copy checked exceptions
if (checked_exceptions_length > 0) { if (checked_exceptions_length > 0) {
int size = checked_exceptions_length * sizeof(CheckedExceptionElement) / sizeof(u2); int size = checked_exceptions_length * sizeof(CheckedExceptionElement) / sizeof(u2);
...@@ -3042,6 +3065,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -3042,6 +3065,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
TempNewSymbol& parsed_name, TempNewSymbol& parsed_name,
bool verify, bool verify,
TRAPS) { TRAPS) {
// When a retransformable agent is attached, JVMTI caches the // When a retransformable agent is attached, JVMTI caches the
// class bytes that existed before the first retransformation. // class bytes that existed before the first retransformation.
// If RedefineClasses() was used before the retransformable // If RedefineClasses() was used before the retransformable
...@@ -3888,8 +3912,11 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ...@@ -3888,8 +3912,11 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
// check that if this class is an interface then it doesn't have static methods // check that if this class is an interface then it doesn't have static methods
if (this_klass->is_interface()) { if (this_klass->is_interface()) {
/* An interface in a JAVA 8 classfile can be static */
if (_major_version < JAVA_8_VERSION) {
check_illegal_static_method(this_klass, CHECK_(nullHandle)); check_illegal_static_method(this_klass, CHECK_(nullHandle));
} }
}
#ifdef ASSERT #ifdef ASSERT
...@@ -4442,6 +4469,7 @@ void ClassFileParser::verify_legal_method_modifiers( ...@@ -4442,6 +4469,7 @@ void ClassFileParser::verify_legal_method_modifiers(
const bool is_bridge = (flags & JVM_ACC_BRIDGE) != 0; const bool is_bridge = (flags & JVM_ACC_BRIDGE) != 0;
const bool is_strict = (flags & JVM_ACC_STRICT) != 0; const bool is_strict = (flags & JVM_ACC_STRICT) != 0;
const bool is_synchronized = (flags & JVM_ACC_SYNCHRONIZED) != 0; const bool is_synchronized = (flags & JVM_ACC_SYNCHRONIZED) != 0;
const bool is_protected = (flags & JVM_ACC_PROTECTED) != 0;
const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION; const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION;
const bool major_gte_8 = _major_version >= JAVA_8_VERSION; const bool major_gte_8 = _major_version >= JAVA_8_VERSION;
const bool is_initializer = (name == vmSymbols::object_initializer_name()); const bool is_initializer = (name == vmSymbols::object_initializer_name());
...@@ -4449,12 +4477,34 @@ void ClassFileParser::verify_legal_method_modifiers( ...@@ -4449,12 +4477,34 @@ void ClassFileParser::verify_legal_method_modifiers(
bool is_illegal = false; bool is_illegal = false;
if (is_interface) { if (is_interface) {
if (!is_public || is_static || is_final || is_native || if (major_gte_8) {
((is_synchronized || is_strict) && major_gte_15 && // Class file version is JAVA_8_VERSION or later Methods of
(!major_gte_8 || is_abstract)) || // interfaces may set any of the flags except ACC_PROTECTED,
(!major_gte_8 && !is_abstract)) { // ACC_FINAL, ACC_NATIVE, and ACC_SYNCHRONIZED; they must
// have exactly one of the ACC_PUBLIC or ACC_PRIVATE flags set.
if ((is_public == is_private) || /* Only one of private and public should be true - XNOR */
(is_native || is_protected || is_final || is_synchronized) ||
// If a specific method of a class or interface has its
// ACC_ABSTRACT flag set, it must not have any of its
// ACC_FINAL, ACC_NATIVE, ACC_PRIVATE, ACC_STATIC,
// ACC_STRICT, or ACC_SYNCHRONIZED flags set. No need to
// check for ACC_FINAL, ACC_NATIVE or ACC_SYNCHRONIZED as
// those flags are illegal irrespective of ACC_ABSTRACT being set or not.
(is_abstract && (is_private || is_static || is_strict))) {
is_illegal = true; is_illegal = true;
} }
} else if (major_gte_15) {
// Class file version in the interval [JAVA_1_5_VERSION, JAVA_8_VERSION)
if (!is_public || is_static || is_final || is_synchronized ||
is_native || !is_abstract || is_strict) {
is_illegal = true;
}
} else {
// Class file version is pre-JAVA_1_5_VERSION
if (!is_public || is_static || is_final || is_native || !is_abstract) {
is_illegal = true;
}
}
} else { // not interface } else { // not interface
if (is_initializer) { if (is_initializer) {
if (is_static || is_final || is_synchronized || is_native || if (is_static || is_final || is_synchronized || is_native ||
......
...@@ -93,3 +93,10 @@ void ClassFileStream::skip_u2(int length, TRAPS) { ...@@ -93,3 +93,10 @@ void ClassFileStream::skip_u2(int length, TRAPS) {
} }
_current += length * 2; _current += length * 2;
} }
void ClassFileStream::skip_u4(int length, TRAPS) {
if (_need_verify) {
guarantee_more(length * 4, CHECK);
}
_current += length * 4;
}
...@@ -133,6 +133,11 @@ class ClassFileStream: public ResourceObj { ...@@ -133,6 +133,11 @@ class ClassFileStream: public ResourceObj {
_current += 2 * length; _current += 2 * length;
} }
void skip_u4(int length, TRAPS);
void skip_u4_fast(int length) {
_current += 4 * length;
}
// Tells whether eos is reached // Tells whether eos is reached
bool at_eos() const { return _current == _buffer_end; } bool at_eos() const { return _current == _buffer_end; }
}; };
......
...@@ -1148,7 +1148,8 @@ static Method* new_method( ...@@ -1148,7 +1148,8 @@ static Method* new_method(
int code_length = bytecodes->length(); int code_length = bytecodes->length();
Method* m = Method::allocate(cp->pool_holder()->class_loader_data(), Method* m = Method::allocate(cp->pool_holder()->class_loader_data(),
code_length, flags, 0, 0, 0, 0, 0, mt, CHECK_NULL); code_length, flags, 0, 0, 0, 0, 0, 0,
mt, CHECK_NULL);
m->set_constants(NULL); // This will get filled in later m->set_constants(NULL); // This will get filled in later
m->set_name_index(cp->utf8(name)); m->set_name_index(cp->utf8(name));
......
...@@ -2255,6 +2255,66 @@ void sun_reflect_ConstantPool::compute_offsets() { ...@@ -2255,6 +2255,66 @@ void sun_reflect_ConstantPool::compute_offsets() {
} }
} }
void java_lang_reflect_Parameter::compute_offsets() {
Klass* k = SystemDictionary::reflect_Parameter_klass();
if(NULL != k) {
compute_offset(name_offset, k, vmSymbols::name_name(), vmSymbols::string_signature());
compute_offset(modifiers_offset, k, vmSymbols::modifiers_name(), vmSymbols::int_signature());
compute_offset(index_offset, k, vmSymbols::index_name(), vmSymbols::int_signature());
compute_offset(executable_offset, k, vmSymbols::executable_name(), vmSymbols::executable_signature());
}
}
Handle java_lang_reflect_Parameter::create(TRAPS) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
Symbol* name = vmSymbols::java_lang_reflect_Parameter();
Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH);
instanceKlassHandle klass (THREAD, k);
// Ensure it is initialized
klass->initialize(CHECK_NH);
return klass->allocate_instance_handle(CHECK_NH);
}
oop java_lang_reflect_Parameter::name(oop param) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
return param->obj_field(name_offset);
}
void java_lang_reflect_Parameter::set_name(oop param, oop value) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
param->obj_field_put(name_offset, value);
}
int java_lang_reflect_Parameter::modifiers(oop param) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
return param->int_field(modifiers_offset);
}
void java_lang_reflect_Parameter::set_modifiers(oop param, int value) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
param->int_field_put(modifiers_offset, value);
}
int java_lang_reflect_Parameter::index(oop param) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
return param->int_field(index_offset);
}
void java_lang_reflect_Parameter::set_index(oop param, int value) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
param->int_field_put(index_offset, value);
}
oop java_lang_reflect_Parameter::executable(oop param) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
return param->obj_field(executable_offset);
}
void java_lang_reflect_Parameter::set_executable(oop param, oop value) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
param->obj_field_put(executable_offset, value);
}
Handle sun_reflect_ConstantPool::create(TRAPS) { Handle sun_reflect_ConstantPool::create(TRAPS) {
assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem"); assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
...@@ -2928,6 +2988,10 @@ int java_lang_reflect_Field::modifiers_offset; ...@@ -2928,6 +2988,10 @@ int java_lang_reflect_Field::modifiers_offset;
int java_lang_reflect_Field::signature_offset; int java_lang_reflect_Field::signature_offset;
int java_lang_reflect_Field::annotations_offset; int java_lang_reflect_Field::annotations_offset;
int java_lang_reflect_Field::type_annotations_offset; int java_lang_reflect_Field::type_annotations_offset;
int java_lang_reflect_Parameter::name_offset;
int java_lang_reflect_Parameter::modifiers_offset;
int java_lang_reflect_Parameter::index_offset;
int java_lang_reflect_Parameter::executable_offset;
int java_lang_boxing_object::value_offset; int java_lang_boxing_object::value_offset;
int java_lang_boxing_object::long_value_offset; int java_lang_boxing_object::long_value_offset;
int java_lang_ref_Reference::referent_offset; int java_lang_ref_Reference::referent_offset;
...@@ -3112,6 +3176,8 @@ void JavaClasses::compute_offsets() { ...@@ -3112,6 +3176,8 @@ void JavaClasses::compute_offsets() {
sun_reflect_ConstantPool::compute_offsets(); sun_reflect_ConstantPool::compute_offsets();
sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets(); sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
} }
if (JDK_Version::is_jdk18x_version())
java_lang_reflect_Parameter::compute_offsets();
// generated interpreter code wants to know about the offsets we just computed: // generated interpreter code wants to know about the offsets we just computed:
AbstractAssembler::update_delayed_values(); AbstractAssembler::update_delayed_values();
......
...@@ -729,6 +729,37 @@ class java_lang_reflect_Field : public java_lang_reflect_AccessibleObject { ...@@ -729,6 +729,37 @@ class java_lang_reflect_Field : public java_lang_reflect_AccessibleObject {
friend class JavaClasses; friend class JavaClasses;
}; };
class java_lang_reflect_Parameter {
private:
// Note that to reduce dependencies on the JDK we compute these
// offsets at run-time.
static int name_offset;
static int modifiers_offset;
static int index_offset;
static int executable_offset;
static void compute_offsets();
public:
// Allocation
static Handle create(TRAPS);
// Accessors
static oop name(oop field);
static void set_name(oop field, oop value);
static int index(oop reflect);
static void set_index(oop reflect, int value);
static int modifiers(oop reflect);
static void set_modifiers(oop reflect, int value);
static oop executable(oop constructor);
static void set_executable(oop constructor, oop value);
friend class JavaClasses;
};
// Interface to sun.reflect.ConstantPool objects // Interface to sun.reflect.ConstantPool objects
class sun_reflect_ConstantPool { class sun_reflect_ConstantPool {
private: private:
......
...@@ -131,6 +131,7 @@ class SymbolPropertyTable; ...@@ -131,6 +131,7 @@ class SymbolPropertyTable;
do_klass(Properties_klass, java_util_Properties, Pre ) \ do_klass(Properties_klass, java_util_Properties, Pre ) \
do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre ) \ do_klass(reflect_AccessibleObject_klass, java_lang_reflect_AccessibleObject, Pre ) \
do_klass(reflect_Field_klass, java_lang_reflect_Field, Pre ) \ do_klass(reflect_Field_klass, java_lang_reflect_Field, Pre ) \
do_klass(reflect_Parameter_klass, java_lang_reflect_Parameter, Opt ) \
do_klass(reflect_Method_klass, java_lang_reflect_Method, Pre ) \ do_klass(reflect_Method_klass, java_lang_reflect_Method, Pre ) \
do_klass(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre ) \ do_klass(reflect_Constructor_klass, java_lang_reflect_Constructor, Pre ) \
\ \
...@@ -459,6 +460,7 @@ public: ...@@ -459,6 +460,7 @@ public:
// Tells whether ClassLoader.checkPackageAccess is present // Tells whether ClassLoader.checkPackageAccess is present
static bool has_checkPackageAccess() { return _has_checkPackageAccess; } static bool has_checkPackageAccess() { return _has_checkPackageAccess; }
static bool Parameter_klass_loaded() { return WK_KLASS(reflect_Parameter_klass) != NULL; }
static bool Class_klass_loaded() { return WK_KLASS(Class_klass) != NULL; } static bool Class_klass_loaded() { return WK_KLASS(Class_klass) != NULL; }
static bool Cloneable_klass_loaded() { return WK_KLASS(Cloneable_klass) != NULL; } static bool Cloneable_klass_loaded() { return WK_KLASS(Cloneable_klass) != NULL; }
static bool Object_klass_loaded() { return WK_KLASS(Object_klass) != NULL; } static bool Object_klass_loaded() { return WK_KLASS(Object_klass) != NULL; }
......
...@@ -86,6 +86,7 @@ ...@@ -86,6 +86,7 @@
template(java_lang_reflect_Method, "java/lang/reflect/Method") \ template(java_lang_reflect_Method, "java/lang/reflect/Method") \
template(java_lang_reflect_Constructor, "java/lang/reflect/Constructor") \ template(java_lang_reflect_Constructor, "java/lang/reflect/Constructor") \
template(java_lang_reflect_Field, "java/lang/reflect/Field") \ template(java_lang_reflect_Field, "java/lang/reflect/Field") \
template(java_lang_reflect_Parameter, "java/lang/reflect/Parameter") \
template(java_lang_reflect_Array, "java/lang/reflect/Array") \ template(java_lang_reflect_Array, "java/lang/reflect/Array") \
template(java_lang_StringBuffer, "java/lang/StringBuffer") \ template(java_lang_StringBuffer, "java/lang/StringBuffer") \
template(java_lang_StringBuilder, "java/lang/StringBuilder") \ template(java_lang_StringBuilder, "java/lang/StringBuilder") \
...@@ -126,6 +127,7 @@ ...@@ -126,6 +127,7 @@
template(tag_line_number_table, "LineNumberTable") \ template(tag_line_number_table, "LineNumberTable") \
template(tag_local_variable_table, "LocalVariableTable") \ template(tag_local_variable_table, "LocalVariableTable") \
template(tag_local_variable_type_table, "LocalVariableTypeTable") \ template(tag_local_variable_type_table, "LocalVariableTypeTable") \
template(tag_method_parameters, "MethodParameters") \
template(tag_stack_map_table, "StackMapTable") \ template(tag_stack_map_table, "StackMapTable") \
template(tag_synthetic, "Synthetic") \ template(tag_synthetic, "Synthetic") \
template(tag_deprecated, "Deprecated") \ template(tag_deprecated, "Deprecated") \
...@@ -235,6 +237,8 @@ ...@@ -235,6 +237,8 @@
/* Support for annotations (JDK 1.5 and above) */ \ /* Support for annotations (JDK 1.5 and above) */ \
\ \
template(annotations_name, "annotations") \ template(annotations_name, "annotations") \
template(index_name, "index") \
template(executable_name, "executable") \
template(parameter_annotations_name, "parameterAnnotations") \ template(parameter_annotations_name, "parameterAnnotations") \
template(annotation_default_name, "annotationDefault") \ template(annotation_default_name, "annotationDefault") \
template(sun_reflect_ConstantPool, "sun/reflect/ConstantPool") \ template(sun_reflect_ConstantPool, "sun/reflect/ConstantPool") \
...@@ -475,6 +479,7 @@ ...@@ -475,6 +479,7 @@
template(class_signature, "Ljava/lang/Class;") \ template(class_signature, "Ljava/lang/Class;") \
template(string_signature, "Ljava/lang/String;") \ template(string_signature, "Ljava/lang/String;") \
template(reference_signature, "Ljava/lang/ref/Reference;") \ template(reference_signature, "Ljava/lang/ref/Reference;") \
template(executable_signature, "Ljava/lang/reflect/Executable;") \
template(concurrenthashmap_signature, "Ljava/util/concurrent/ConcurrentHashMap;") \ template(concurrenthashmap_signature, "Ljava/util/concurrent/ConcurrentHashMap;") \
template(String_StringBuilder_signature, "(Ljava/lang/String;)Ljava/lang/StringBuilder;") \ template(String_StringBuilder_signature, "(Ljava/lang/String;)Ljava/lang/StringBuilder;") \
template(int_StringBuilder_signature, "(I)Ljava/lang/StringBuilder;") \ template(int_StringBuilder_signature, "(I)Ljava/lang/StringBuilder;") \
......
...@@ -119,6 +119,7 @@ void FileMapInfo::populate_header(size_t alignment) { ...@@ -119,6 +119,7 @@ void FileMapInfo::populate_header(size_t alignment) {
_header._magic = 0xf00baba2; _header._magic = 0xf00baba2;
_header._version = _current_version; _header._version = _current_version;
_header._alignment = alignment; _header._alignment = alignment;
_header._obj_alignment = ObjectAlignmentInBytes;
// The following fields are for sanity checks for whether this archive // The following fields are for sanity checks for whether this archive
// will function correctly with this JVM and the bootclasspath it's // will function correctly with this JVM and the bootclasspath it's
...@@ -473,6 +474,12 @@ bool FileMapInfo::validate() { ...@@ -473,6 +474,12 @@ bool FileMapInfo::validate() {
" version or build of HotSpot."); " version or build of HotSpot.");
return false; return false;
} }
if (_header._obj_alignment != ObjectAlignmentInBytes) {
fail_continue("The shared archive file's ObjectAlignmentInBytes of %d"
" does not equal the current ObjectAlignmentInBytes of %d.",
_header._obj_alignment, ObjectAlignmentInBytes);
return false;
}
// Cannot verify interpreter yet, as it can only be created after the GC // Cannot verify interpreter yet, as it can only be created after the GC
// heap has been initialized. // heap has been initialized.
......
...@@ -63,6 +63,7 @@ private: ...@@ -63,6 +63,7 @@ private:
int _magic; // identify file type. int _magic; // identify file type.
int _version; // (from enum, above.) int _version; // (from enum, above.)
size_t _alignment; // how shared archive should be aligned size_t _alignment; // how shared archive should be aligned
int _obj_alignment; // value of ObjectAlignmentInBytes
struct space_info { struct space_info {
int _file_offset; // sizeof(this) rounded to vm page size int _file_offset; // sizeof(this) rounded to vm page size
......
...@@ -39,6 +39,7 @@ ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data, ...@@ -39,6 +39,7 @@ ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
int localvariable_table_length, int localvariable_table_length,
int exception_table_length, int exception_table_length,
int checked_exceptions_length, int checked_exceptions_length,
int method_parameters_length,
u2 generic_signature_index, u2 generic_signature_index,
MethodType method_type, MethodType method_type,
TRAPS) { TRAPS) {
...@@ -47,10 +48,12 @@ ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data, ...@@ -47,10 +48,12 @@ ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data,
localvariable_table_length, localvariable_table_length,
exception_table_length, exception_table_length,
checked_exceptions_length, checked_exceptions_length,
method_parameters_length,
generic_signature_index); generic_signature_index);
return new (loader_data, size, true, THREAD) ConstMethod( return new (loader_data, size, true, THREAD) ConstMethod(
byte_code_size, compressed_line_number_size, localvariable_table_length, byte_code_size, compressed_line_number_size, localvariable_table_length,
exception_table_length, checked_exceptions_length, generic_signature_index, exception_table_length, checked_exceptions_length,
method_parameters_length, generic_signature_index,
method_type, size); method_type, size);
} }
...@@ -59,6 +62,7 @@ ConstMethod::ConstMethod(int byte_code_size, ...@@ -59,6 +62,7 @@ ConstMethod::ConstMethod(int byte_code_size,
int localvariable_table_length, int localvariable_table_length,
int exception_table_length, int exception_table_length,
int checked_exceptions_length, int checked_exceptions_length,
int method_parameters_length,
u2 generic_signature_index, u2 generic_signature_index,
MethodType method_type, MethodType method_type,
int size) { int size) {
...@@ -74,7 +78,8 @@ ConstMethod::ConstMethod(int byte_code_size, ...@@ -74,7 +78,8 @@ ConstMethod::ConstMethod(int byte_code_size,
checked_exceptions_length, checked_exceptions_length,
compressed_line_number_size, compressed_line_number_size,
localvariable_table_length, localvariable_table_length,
exception_table_length); exception_table_length,
method_parameters_length);
set_method_type(method_type); set_method_type(method_type);
assert(this->size() == size, "wrong size for object"); assert(this->size() == size, "wrong size for object");
} }
...@@ -96,6 +101,7 @@ int ConstMethod::size(int code_size, ...@@ -96,6 +101,7 @@ int ConstMethod::size(int code_size,
int local_variable_table_length, int local_variable_table_length,
int exception_table_length, int exception_table_length,
int checked_exceptions_length, int checked_exceptions_length,
int method_parameters_length,
u2 generic_signature_index) { u2 generic_signature_index) {
int extra_bytes = code_size; int extra_bytes = code_size;
if (compressed_line_number_size > 0) { if (compressed_line_number_size > 0) {
...@@ -117,6 +123,10 @@ int ConstMethod::size(int code_size, ...@@ -117,6 +123,10 @@ int ConstMethod::size(int code_size,
if (generic_signature_index != 0) { if (generic_signature_index != 0) {
extra_bytes += sizeof(u2); extra_bytes += sizeof(u2);
} }
if (method_parameters_length > 0) {
extra_bytes += sizeof(u2);
extra_bytes += method_parameters_length * sizeof(MethodParametersElement);
}
int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord; int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord;
return align_object_size(header_size() + extra_words); return align_object_size(header_size() + extra_words);
} }
...@@ -143,6 +153,18 @@ u2* ConstMethod::generic_signature_index_addr() const { ...@@ -143,6 +153,18 @@ u2* ConstMethod::generic_signature_index_addr() const {
u2* ConstMethod::checked_exceptions_length_addr() const { u2* ConstMethod::checked_exceptions_length_addr() const {
// Located immediately before the generic signature index. // Located immediately before the generic signature index.
assert(has_checked_exceptions(), "called only if table is present"); assert(has_checked_exceptions(), "called only if table is present");
if(has_method_parameters()) {
// If method parameters present, locate immediately before them.
return (u2*)method_parameters_start() - 1;
} else {
// Else, the exception table is at the end of the constMethod.
return has_generic_signature() ? (last_u2_element() - 1) :
last_u2_element();
}
}
u2* ConstMethod::method_parameters_length_addr() const {
assert(has_method_parameters(), "called only if table is present");
return has_generic_signature() ? (last_u2_element() - 1) : return has_generic_signature() ? (last_u2_element() - 1) :
last_u2_element(); last_u2_element();
} }
...@@ -153,11 +175,15 @@ u2* ConstMethod::exception_table_length_addr() const { ...@@ -153,11 +175,15 @@ u2* ConstMethod::exception_table_length_addr() const {
// If checked_exception present, locate immediately before them. // If checked_exception present, locate immediately before them.
return (u2*) checked_exceptions_start() - 1; return (u2*) checked_exceptions_start() - 1;
} else { } else {
// Else, the exception table is at the end of the constMethod or if(has_method_parameters()) {
// immediately before the generic signature index. // If method parameters present, locate immediately before them.
return (u2*)method_parameters_start() - 1;
} else {
// Else, the exception table is at the end of the constMethod.
return has_generic_signature() ? (last_u2_element() - 1) : return has_generic_signature() ? (last_u2_element() - 1) :
last_u2_element(); last_u2_element();
} }
}
} }
u2* ConstMethod::localvariable_table_length_addr() const { u2* ConstMethod::localvariable_table_length_addr() const {
...@@ -170,12 +196,16 @@ u2* ConstMethod::localvariable_table_length_addr() const { ...@@ -170,12 +196,16 @@ u2* ConstMethod::localvariable_table_length_addr() const {
// If checked_exception present, locate immediately before them. // If checked_exception present, locate immediately before them.
return (u2*) checked_exceptions_start() - 1; return (u2*) checked_exceptions_start() - 1;
} else { } else {
// Else, the linenumber table is at the end of the constMethod or if(has_method_parameters()) {
// immediately before the generic signature index. // If method parameters present, locate immediately before them.
return (u2*)method_parameters_start() - 1;
} else {
// Else, the exception table is at the end of the constMethod.
return has_generic_signature() ? (last_u2_element() - 1) : return has_generic_signature() ? (last_u2_element() - 1) :
last_u2_element(); last_u2_element();
} }
} }
}
} }
// Update the flags to indicate the presence of these optional fields. // Update the flags to indicate the presence of these optional fields.
...@@ -183,29 +213,57 @@ void ConstMethod::set_inlined_tables_length(u2 generic_signature_index, ...@@ -183,29 +213,57 @@ void ConstMethod::set_inlined_tables_length(u2 generic_signature_index,
int checked_exceptions_len, int checked_exceptions_len,
int compressed_line_number_size, int compressed_line_number_size,
int localvariable_table_len, int localvariable_table_len,
int exception_table_len) { int exception_table_len,
// Must be done in the order below, otherwise length_addr accessors int method_parameters_len) {
// will not work. Only set bit in header if length is positive.
assert(_flags == 0, "Error"); assert(_flags == 0, "Error");
if (compressed_line_number_size > 0) { if (compressed_line_number_size > 0)
_flags |= _has_linenumber_table; _flags |= _has_linenumber_table;
} if (generic_signature_index != 0)
if (generic_signature_index != 0) {
_flags |= _has_generic_signature; _flags |= _has_generic_signature;
*(generic_signature_index_addr()) = generic_signature_index; if (method_parameters_len > 0)
} _flags |= _has_method_parameters;
if (checked_exceptions_len > 0) { if (checked_exceptions_len > 0)
_flags |= _has_checked_exceptions; _flags |= _has_checked_exceptions;
*(checked_exceptions_length_addr()) = checked_exceptions_len; if (exception_table_len > 0)
}
if (exception_table_len > 0) {
_flags |= _has_exception_table; _flags |= _has_exception_table;
*(exception_table_length_addr()) = exception_table_len; if (localvariable_table_len > 0)
}
if (localvariable_table_len > 0) {
_flags |= _has_localvariable_table; _flags |= _has_localvariable_table;
// This code is extremely brittle and should possibly be revised.
// The *_length_addr functions walk backwards through the
// constMethod data, using each of the length indexes ahead of them,
// as well as the flags variable. Therefore, the indexes must be
// initialized in reverse order, or else they will compute the wrong
// offsets. Moving the initialization of _flags into a separate
// block solves *half* of the problem, but the following part will
// still break if the order is not exactly right.
//
// Also, the servicability agent needs to be informed anytime
// anything is added here. It might be advisable to have some sort
// of indication of this inline.
if (generic_signature_index != 0)
*(generic_signature_index_addr()) = generic_signature_index;
// New data should probably go here.
if (method_parameters_len > 0)
*(method_parameters_length_addr()) = method_parameters_len;
if (checked_exceptions_len > 0)
*(checked_exceptions_length_addr()) = checked_exceptions_len;
if (exception_table_len > 0)
*(exception_table_length_addr()) = exception_table_len;
if (localvariable_table_len > 0)
*(localvariable_table_length_addr()) = localvariable_table_len; *(localvariable_table_length_addr()) = localvariable_table_len;
} }
int ConstMethod::method_parameters_length() const {
return has_method_parameters() ? *(method_parameters_length_addr()) : 0;
}
MethodParametersElement* ConstMethod::method_parameters_start() const {
u2* addr = method_parameters_length_addr();
u2 length = *addr;
assert(length > 0, "should only be called if table is present");
addr -= length * sizeof(MethodParametersElement) / sizeof(u2);
return (MethodParametersElement*) addr;
} }
...@@ -298,6 +356,10 @@ void ConstMethod::verify_on(outputStream* st) { ...@@ -298,6 +356,10 @@ void ConstMethod::verify_on(outputStream* st) {
} }
guarantee(compressed_table_end <= m_end, "invalid method layout"); guarantee(compressed_table_end <= m_end, "invalid method layout");
// Verify checked exceptions, exception table and local variable tables // Verify checked exceptions, exception table and local variable tables
if (has_method_parameters()) {
u2* addr = method_parameters_length_addr();
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
}
if (has_checked_exceptions()) { if (has_checked_exceptions()) {
u2* addr = checked_exceptions_length_addr(); u2* addr = checked_exceptions_length_addr();
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout"); guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
...@@ -318,6 +380,8 @@ void ConstMethod::verify_on(outputStream* st) { ...@@ -318,6 +380,8 @@ void ConstMethod::verify_on(outputStream* st) {
uncompressed_table_start = (u2*) exception_table_start(); uncompressed_table_start = (u2*) exception_table_start();
} else if (has_checked_exceptions()) { } else if (has_checked_exceptions()) {
uncompressed_table_start = (u2*) checked_exceptions_start(); uncompressed_table_start = (u2*) checked_exceptions_start();
} else if (has_method_parameters()) {
uncompressed_table_start = (u2*) method_parameters_start();
} else { } else {
uncompressed_table_start = (u2*) m_end; uncompressed_table_start = (u2*) m_end;
} }
......
...@@ -77,9 +77,18 @@ ...@@ -77,9 +77,18 @@
// | (access flags bit tells whether table is present) | // | (access flags bit tells whether table is present) |
// | (indexed from end of ConstMethod*) | // | (indexed from end of ConstMethod*) |
// |------------------------------------------------------| // |------------------------------------------------------|
// | method parameters elements + length (length last) |
// | (length is u2, elements are u2, u4 structures) |
// | (see class MethodParametersElement) |
// | (access flags bit tells whether table is present) |
// | (indexed from end of ConstMethod*) |
// |------------------------------------------------------|
// | generic signature index (u2) | // | generic signature index (u2) |
// | (indexed from start of constMethodOop) | // | (indexed from start of constMethodOop) |
// |------------------------------------------------------| // |------------------------------------------------------|
//
// IMPORTANT: If anything gets added here, there need to be changes to
// ensure that ServicabilityAgent doesn't get broken as a result!
// Utitily class decribing elements in checked exceptions table inlined in Method*. // Utitily class decribing elements in checked exceptions table inlined in Method*.
...@@ -109,6 +118,13 @@ class ExceptionTableElement VALUE_OBJ_CLASS_SPEC { ...@@ -109,6 +118,13 @@ class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
u2 catch_type_index; u2 catch_type_index;
}; };
// Utility class describing elements in method parameters
class MethodParametersElement VALUE_OBJ_CLASS_SPEC {
public:
u2 name_cp_index;
u4 flags;
};
class ConstMethod : public MetaspaceObj { class ConstMethod : public MetaspaceObj {
friend class VMStructs; friend class VMStructs;
...@@ -123,7 +139,8 @@ private: ...@@ -123,7 +139,8 @@ private:
_has_localvariable_table = 4, _has_localvariable_table = 4,
_has_exception_table = 8, _has_exception_table = 8,
_has_generic_signature = 16, _has_generic_signature = 16,
_is_overpass = 32 _has_method_parameters = 32,
_is_overpass = 64
}; };
// Bit vector of signature // Bit vector of signature
...@@ -160,6 +177,7 @@ private: ...@@ -160,6 +177,7 @@ private:
int localvariable_table_length, int localvariable_table_length,
int exception_table_length, int exception_table_length,
int checked_exceptions_length, int checked_exceptions_length,
int method_parameters_length,
u2 generic_signature_index, u2 generic_signature_index,
MethodType is_overpass, MethodType is_overpass,
int size); int size);
...@@ -171,6 +189,7 @@ public: ...@@ -171,6 +189,7 @@ public:
int localvariable_table_length, int localvariable_table_length,
int exception_table_length, int exception_table_length,
int checked_exceptions_length, int checked_exceptions_length,
int method_parameters_length,
u2 generic_signature_index, u2 generic_signature_index,
MethodType mt, MethodType mt,
TRAPS); TRAPS);
...@@ -182,7 +201,8 @@ public: ...@@ -182,7 +201,8 @@ public:
int checked_exceptions_len, int checked_exceptions_len,
int compressed_line_number_size, int compressed_line_number_size,
int localvariable_table_len, int localvariable_table_len,
int exception_table_len); int exception_table_len,
int method_parameters_length);
bool has_generic_signature() const bool has_generic_signature() const
{ return (_flags & _has_generic_signature) != 0; } { return (_flags & _has_generic_signature) != 0; }
...@@ -199,6 +219,9 @@ public: ...@@ -199,6 +219,9 @@ public:
bool has_exception_handler() const bool has_exception_handler() const
{ return (_flags & _has_exception_table) != 0; } { return (_flags & _has_exception_table) != 0; }
bool has_method_parameters() const
{ return (_flags & _has_method_parameters) != 0; }
MethodType method_type() const { MethodType method_type() const {
return ((_flags & _is_overpass) == 0) ? NORMAL : OVERPASS; return ((_flags & _is_overpass) == 0) ? NORMAL : OVERPASS;
} }
...@@ -287,6 +310,7 @@ public: ...@@ -287,6 +310,7 @@ public:
int local_variable_table_length, int local_variable_table_length,
int exception_table_length, int exception_table_length,
int checked_exceptions_length, int checked_exceptions_length,
int method_parameters_length,
u2 generic_signature_index); u2 generic_signature_index);
int size() const { return _constMethod_size;} int size() const { return _constMethod_size;}
...@@ -308,6 +332,7 @@ public: ...@@ -308,6 +332,7 @@ public:
u2* checked_exceptions_length_addr() const; u2* checked_exceptions_length_addr() const;
u2* localvariable_table_length_addr() const; u2* localvariable_table_length_addr() const;
u2* exception_table_length_addr() const; u2* exception_table_length_addr() const;
u2* method_parameters_length_addr() const;
// checked exceptions // checked exceptions
int checked_exceptions_length() const; int checked_exceptions_length() const;
...@@ -321,6 +346,10 @@ public: ...@@ -321,6 +346,10 @@ public:
int exception_table_length() const; int exception_table_length() const;
ExceptionTableElement* exception_table_start() const; ExceptionTableElement* exception_table_start() const;
// method parameters table
int method_parameters_length() const;
MethodParametersElement* method_parameters_start() const;
// byte codes // byte codes
void set_code(address code) { void set_code(address code) {
if (code_size() > 0) { if (code_size() > 0) {
......
...@@ -161,6 +161,8 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end, ...@@ -161,6 +161,8 @@ HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end,
#endif // ndef DTRACE_ENABLED #endif // ndef DTRACE_ENABLED
volatile int InstanceKlass::_total_instanceKlass_count = 0;
Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data, Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
int vtable_len, int vtable_len,
int itable_len, int itable_len,
...@@ -204,6 +206,7 @@ Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data, ...@@ -204,6 +206,7 @@ Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data,
access_flags, !host_klass.is_null()); access_flags, !host_klass.is_null());
} }
Atomic::inc(&_total_instanceKlass_count);
return ik; return ik;
} }
...@@ -2331,6 +2334,9 @@ void InstanceKlass::release_C_heap_structures() { ...@@ -2331,6 +2334,9 @@ void InstanceKlass::release_C_heap_structures() {
if (_array_name != NULL) _array_name->decrement_refcount(); if (_array_name != NULL) _array_name->decrement_refcount();
if (_source_file_name != NULL) _source_file_name->decrement_refcount(); if (_source_file_name != NULL) _source_file_name->decrement_refcount();
if (_source_debug_extension != NULL) FREE_C_HEAP_ARRAY(char, _source_debug_extension, mtClass); if (_source_debug_extension != NULL) FREE_C_HEAP_ARRAY(char, _source_debug_extension, mtClass);
assert(_total_instanceKlass_count >= 1, "Sanity check");
Atomic::dec(&_total_instanceKlass_count);
} }
void InstanceKlass::set_source_file_name(Symbol* n) { void InstanceKlass::set_source_file_name(Symbol* n) {
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "oops/fieldInfo.hpp" #include "oops/fieldInfo.hpp"
#include "oops/instanceOop.hpp" #include "oops/instanceOop.hpp"
#include "oops/klassVtable.hpp" #include "oops/klassVtable.hpp"
#include "runtime/atomic.hpp"
#include "runtime/handles.hpp" #include "runtime/handles.hpp"
#include "runtime/os.hpp" #include "runtime/os.hpp"
#include "utilities/accessFlags.hpp" #include "utilities/accessFlags.hpp"
...@@ -170,6 +171,11 @@ class InstanceKlass: public Klass { ...@@ -170,6 +171,11 @@ class InstanceKlass: public Klass {
initialization_error // error happened during initialization initialization_error // error happened during initialization
}; };
static int number_of_instance_classes() { return _total_instanceKlass_count; }
private:
static volatile int _total_instanceKlass_count;
protected: protected:
// Protection domain. // Protection domain.
oop _protection_domain; oop _protection_domain;
......
...@@ -64,6 +64,7 @@ Method* Method::allocate(ClassLoaderData* loader_data, ...@@ -64,6 +64,7 @@ Method* Method::allocate(ClassLoaderData* loader_data,
int localvariable_table_length, int localvariable_table_length,
int exception_table_length, int exception_table_length,
int checked_exceptions_length, int checked_exceptions_length,
int method_parameters_length,
u2 generic_signature_index, u2 generic_signature_index,
ConstMethod::MethodType method_type, ConstMethod::MethodType method_type,
TRAPS) { TRAPS) {
...@@ -75,6 +76,7 @@ Method* Method::allocate(ClassLoaderData* loader_data, ...@@ -75,6 +76,7 @@ Method* Method::allocate(ClassLoaderData* loader_data,
localvariable_table_length, localvariable_table_length,
exception_table_length, exception_table_length,
checked_exceptions_length, checked_exceptions_length,
method_parameters_length,
generic_signature_index, generic_signature_index,
method_type, method_type,
CHECK_NULL); CHECK_NULL);
...@@ -1035,8 +1037,10 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid, ...@@ -1035,8 +1037,10 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid,
methodHandle m; methodHandle m;
{ {
Method* m_oop = Method::allocate(loader_data, 0, accessFlags_from(flags_bits), Method* m_oop = Method::allocate(loader_data, 0,
0, 0, 0, 0, 0, ConstMethod::NORMAL, CHECK_(empty)); accessFlags_from(flags_bits),
0, 0, 0, 0, 0, 0,
ConstMethod::NORMAL, CHECK_(empty));
m = methodHandle(THREAD, m_oop); m = methodHandle(THREAD, m_oop);
} }
m->set_constants(cp()); m->set_constants(cp());
...@@ -1088,6 +1092,7 @@ methodHandle Method::clone_with_new_data(methodHandle m, u_char* new_code, int n ...@@ -1088,6 +1092,7 @@ methodHandle Method::clone_with_new_data(methodHandle m, u_char* new_code, int n
int checked_exceptions_len = m->checked_exceptions_length(); int checked_exceptions_len = m->checked_exceptions_length();
int localvariable_len = m->localvariable_table_length(); int localvariable_len = m->localvariable_table_length();
int exception_table_len = m->exception_table_length(); int exception_table_len = m->exception_table_length();
int method_parameters_len = m->method_parameters_length();
ClassLoaderData* loader_data = m->method_holder()->class_loader_data(); ClassLoaderData* loader_data = m->method_holder()->class_loader_data();
Method* newm_oop = Method::allocate(loader_data, Method* newm_oop = Method::allocate(loader_data,
...@@ -1097,6 +1102,7 @@ methodHandle Method::clone_with_new_data(methodHandle m, u_char* new_code, int n ...@@ -1097,6 +1102,7 @@ methodHandle Method::clone_with_new_data(methodHandle m, u_char* new_code, int n
localvariable_len, localvariable_len,
exception_table_len, exception_table_len,
checked_exceptions_len, checked_exceptions_len,
method_parameters_len,
generic_signature_index, generic_signature_index,
m->method_type(), m->method_type(),
CHECK_(methodHandle())); CHECK_(methodHandle()));
......
...@@ -160,6 +160,7 @@ class Method : public Metadata { ...@@ -160,6 +160,7 @@ class Method : public Metadata {
int localvariable_table_length, int localvariable_table_length,
int exception_table_length, int exception_table_length,
int checked_exceptions_length, int checked_exceptions_length,
int method_parameters_length,
u2 generic_signature_index, u2 generic_signature_index,
ConstMethod::MethodType method_type, ConstMethod::MethodType method_type,
TRAPS); TRAPS);
...@@ -480,6 +481,12 @@ class Method : public Metadata { ...@@ -480,6 +481,12 @@ class Method : public Metadata {
void print_codes_on(outputStream* st) const PRODUCT_RETURN; void print_codes_on(outputStream* st) const PRODUCT_RETURN;
void print_codes_on(int from, int to, outputStream* st) const PRODUCT_RETURN; void print_codes_on(int from, int to, outputStream* st) const PRODUCT_RETURN;
// method parameters
int method_parameters_length() const
{ return constMethod()->method_parameters_length(); }
MethodParametersElement* method_parameters_start() const
{ return constMethod()->method_parameters_start(); }
// checked exceptions // checked exceptions
int checked_exceptions_length() const int checked_exceptions_length() const
{ return constMethod()->checked_exceptions_length(); } { return constMethod()->checked_exceptions_length(); }
......
...@@ -1515,7 +1515,7 @@ JVM_ENTRY(jbyteArray, JVM_GetFieldAnnotations(JNIEnv *env, jobject field)) ...@@ -1515,7 +1515,7 @@ JVM_ENTRY(jbyteArray, JVM_GetFieldAnnotations(JNIEnv *env, jobject field))
JVM_END JVM_END
static Method* jvm_get_method_common(jobject method, TRAPS) { static Method* jvm_get_method_common(jobject method) {
// some of this code was adapted from from jni_FromReflectedMethod // some of this code was adapted from from jni_FromReflectedMethod
oop reflected = JNIHandles::resolve_non_null(method); oop reflected = JNIHandles::resolve_non_null(method);
...@@ -1533,8 +1533,7 @@ static Method* jvm_get_method_common(jobject method, TRAPS) { ...@@ -1533,8 +1533,7 @@ static Method* jvm_get_method_common(jobject method, TRAPS) {
} }
Klass* k = java_lang_Class::as_Klass(mirror); Klass* k = java_lang_Class::as_Klass(mirror);
KlassHandle kh(THREAD, k); Method* m = InstanceKlass::cast(k)->method_with_idnum(slot);
Method* m = InstanceKlass::cast(kh())->method_with_idnum(slot);
if (m == NULL) { if (m == NULL) {
assert(false, "cannot find method"); assert(false, "cannot find method");
return NULL; // robustness return NULL; // robustness
...@@ -1548,7 +1547,7 @@ JVM_ENTRY(jbyteArray, JVM_GetMethodAnnotations(JNIEnv *env, jobject method)) ...@@ -1548,7 +1547,7 @@ JVM_ENTRY(jbyteArray, JVM_GetMethodAnnotations(JNIEnv *env, jobject method))
JVMWrapper("JVM_GetMethodAnnotations"); JVMWrapper("JVM_GetMethodAnnotations");
// method is a handle to a java.lang.reflect.Method object // method is a handle to a java.lang.reflect.Method object
Method* m = jvm_get_method_common(method, CHECK_NULL); Method* m = jvm_get_method_common(method);
return (jbyteArray) JNIHandles::make_local(env, return (jbyteArray) JNIHandles::make_local(env,
Annotations::make_java_array(m->annotations(), THREAD)); Annotations::make_java_array(m->annotations(), THREAD));
JVM_END JVM_END
...@@ -1558,7 +1557,7 @@ JVM_ENTRY(jbyteArray, JVM_GetMethodDefaultAnnotationValue(JNIEnv *env, jobject m ...@@ -1558,7 +1557,7 @@ JVM_ENTRY(jbyteArray, JVM_GetMethodDefaultAnnotationValue(JNIEnv *env, jobject m
JVMWrapper("JVM_GetMethodDefaultAnnotationValue"); JVMWrapper("JVM_GetMethodDefaultAnnotationValue");
// method is a handle to a java.lang.reflect.Method object // method is a handle to a java.lang.reflect.Method object
Method* m = jvm_get_method_common(method, CHECK_NULL); Method* m = jvm_get_method_common(method);
return (jbyteArray) JNIHandles::make_local(env, return (jbyteArray) JNIHandles::make_local(env,
Annotations::make_java_array(m->annotation_default(), THREAD)); Annotations::make_java_array(m->annotation_default(), THREAD));
JVM_END JVM_END
...@@ -1568,7 +1567,7 @@ JVM_ENTRY(jbyteArray, JVM_GetMethodParameterAnnotations(JNIEnv *env, jobject met ...@@ -1568,7 +1567,7 @@ JVM_ENTRY(jbyteArray, JVM_GetMethodParameterAnnotations(JNIEnv *env, jobject met
JVMWrapper("JVM_GetMethodParameterAnnotations"); JVMWrapper("JVM_GetMethodParameterAnnotations");
// method is a handle to a java.lang.reflect.Method object // method is a handle to a java.lang.reflect.Method object
Method* m = jvm_get_method_common(method, CHECK_NULL); Method* m = jvm_get_method_common(method);
return (jbyteArray) JNIHandles::make_local(env, return (jbyteArray) JNIHandles::make_local(env,
Annotations::make_java_array(m->parameter_annotations(), THREAD)); Annotations::make_java_array(m->parameter_annotations(), THREAD));
JVM_END JVM_END
...@@ -1590,6 +1589,32 @@ JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls)) ...@@ -1590,6 +1589,32 @@ JVM_ENTRY(jbyteArray, JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls))
return NULL; return NULL;
JVM_END JVM_END
JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method))
{
JVMWrapper("JVM_GetMethodParameters");
// method is a handle to a java.lang.reflect.Method object
Method* method_ptr = jvm_get_method_common(method);
methodHandle mh (THREAD, method_ptr);
Handle reflected_method (THREAD, JNIHandles::resolve_non_null(method));
const int num_params = mh->method_parameters_length();
if(0 != num_params) {
objArrayOop result_oop = oopFactory::new_objArray(SystemDictionary::reflect_Parameter_klass(), num_params, CHECK_NULL);
objArrayHandle result (THREAD, result_oop);
for(int i = 0; i < num_params; i++) {
MethodParametersElement* params = mh->method_parameters_start();
Symbol* const sym = mh->constants()->symbol_at(params[i].name_cp_index);
oop param = Reflection::new_parameter(reflected_method, i, sym,
params[i].flags, CHECK_NULL);
result->obj_at_put(i, param);
}
return (jobjectArray)JNIHandles::make_local(env, result());
} else {
return (jobjectArray)NULL;
}
}
JVM_END
// New (JDK 1.4) reflection implementation ///////////////////////////////////// // New (JDK 1.4) reflection implementation /////////////////////////////////////
......
...@@ -86,6 +86,8 @@ extern "C" { ...@@ -86,6 +86,8 @@ extern "C" {
#define JVM_INTERFACE_VERSION 4 #define JVM_INTERFACE_VERSION 4
JNIEXPORT jobjectArray JNICALL
JVM_GetMethodParameters(JNIEnv *env, jobject method);
JNIEXPORT jint JNICALL JNIEXPORT jint JNICALL
JVM_GetInterfaceVersion(void); JVM_GetInterfaceVersion(void);
......
...@@ -1331,14 +1331,14 @@ bool verify_object_alignment() { ...@@ -1331,14 +1331,14 @@ bool verify_object_alignment() {
// then a saved space from compressed oops. // then a saved space from compressed oops.
if ((int)ObjectAlignmentInBytes > 256) { if ((int)ObjectAlignmentInBytes > 256) {
jio_fprintf(defaultStream::error_stream(), jio_fprintf(defaultStream::error_stream(),
"error: ObjectAlignmentInBytes=%d must not be greater then 256\n", "error: ObjectAlignmentInBytes=%d must not be greater than 256\n",
(int)ObjectAlignmentInBytes); (int)ObjectAlignmentInBytes);
return false; return false;
} }
// In case page size is very small. // In case page size is very small.
if ((int)ObjectAlignmentInBytes >= os::vm_page_size()) { if ((int)ObjectAlignmentInBytes >= os::vm_page_size()) {
jio_fprintf(defaultStream::error_stream(), jio_fprintf(defaultStream::error_stream(),
"error: ObjectAlignmentInBytes=%d must be less then page size %d\n", "error: ObjectAlignmentInBytes=%d must be less than page size %d\n",
(int)ObjectAlignmentInBytes, os::vm_page_size()); (int)ObjectAlignmentInBytes, os::vm_page_size());
return false; return false;
} }
...@@ -2997,11 +2997,6 @@ void Arguments::set_shared_spaces_flags() { ...@@ -2997,11 +2997,6 @@ void Arguments::set_shared_spaces_flags() {
FLAG_SET_DEFAULT(UseLargePages, false); FLAG_SET_DEFAULT(UseLargePages, false);
} }
// Add 2M to any size for SharedReadOnlySize to get around the JPRT setting
if (DumpSharedSpaces && !FLAG_IS_DEFAULT(SharedReadOnlySize)) {
SharedReadOnlySize = 14*M;
}
if (DumpSharedSpaces) { if (DumpSharedSpaces) {
if (RequireSharedSpaces) { if (RequireSharedSpaces) {
warning("cannot dump shared archive while using shared archive"); warning("cannot dump shared archive while using shared archive");
......
...@@ -1830,7 +1830,7 @@ class CommandLineFlags { ...@@ -1830,7 +1830,7 @@ class CommandLineFlags {
\ \
product(intx, CMSIsTooFullPercentage, 98, \ product(intx, CMSIsTooFullPercentage, 98, \
"An absolute ceiling above which CMS will always consider the " \ "An absolute ceiling above which CMS will always consider the " \
"perm gen ripe for collection") \ "unloading of classes when class unloading is enabled") \
\ \
develop(bool, CMSTestInFreeList, false, \ develop(bool, CMSTestInFreeList, false, \
"Check if the coalesced range is already in the " \ "Check if the coalesced range is already in the " \
...@@ -1899,13 +1899,13 @@ class CommandLineFlags { ...@@ -1899,13 +1899,13 @@ class CommandLineFlags {
"Metadata deallocation alot interval") \ "Metadata deallocation alot interval") \
\ \
develop(bool, TraceMetadataChunkAllocation, false, \ develop(bool, TraceMetadataChunkAllocation, false, \
"Trace humongous metadata allocations") \ "Trace chunk metadata allocations") \
\ \
product(bool, TraceMetadataHumongousAllocation, false, \ product(bool, TraceMetadataHumongousAllocation, false, \
"Trace humongous metadata allocations") \ "Trace humongous metadata allocations") \
\ \
develop(bool, TraceMetavirtualspaceAllocation, false, \ develop(bool, TraceMetavirtualspaceAllocation, false, \
"Trace humongous metadata allocations") \ "Trace virtual space metadata allocations") \
\ \
notproduct(bool, ExecuteInternalVMTests, false, \ notproduct(bool, ExecuteInternalVMTests, false, \
"Enable execution of internal VM tests.") \ "Enable execution of internal VM tests.") \
...@@ -3537,10 +3537,10 @@ class CommandLineFlags { ...@@ -3537,10 +3537,10 @@ class CommandLineFlags {
/* Shared spaces */ \ /* Shared spaces */ \
\ \
product(bool, UseSharedSpaces, true, \ product(bool, UseSharedSpaces, true, \
"Use shared spaces in the permanent generation") \ "Use shared spaces for metadata") \
\ \
product(bool, RequireSharedSpaces, false, \ product(bool, RequireSharedSpaces, false, \
"Require shared spaces in the permanent generation") \ "Require shared spaces for metadata") \
\ \
product(bool, DumpSharedSpaces, false, \ product(bool, DumpSharedSpaces, false, \
"Special mode: JVM reads a class list, loads classes, builds " \ "Special mode: JVM reads a class list, loads classes, builds " \
...@@ -3551,16 +3551,16 @@ class CommandLineFlags { ...@@ -3551,16 +3551,16 @@ class CommandLineFlags {
"Print usage of shared spaces") \ "Print usage of shared spaces") \
\ \
product(uintx, SharedReadWriteSize, NOT_LP64(12*M) LP64_ONLY(16*M), \ product(uintx, SharedReadWriteSize, NOT_LP64(12*M) LP64_ONLY(16*M), \
"Size of read-write space in permanent generation (in bytes)") \ "Size of read-write space for metadata (in bytes)") \
\ \
product(uintx, SharedReadOnlySize, NOT_LP64(12*M) LP64_ONLY(16*M), \ product(uintx, SharedReadOnlySize, NOT_LP64(12*M) LP64_ONLY(16*M), \
"Size of read-only space in permanent generation (in bytes)") \ "Size of read-only space for metadata (in bytes)") \
\ \
product(uintx, SharedMiscDataSize, NOT_LP64(2*M) LP64_ONLY(4*M), \ product(uintx, SharedMiscDataSize, NOT_LP64(2*M) LP64_ONLY(4*M), \
"Size of the shared data area adjacent to the heap (in bytes)") \ "Size of the shared miscellaneous data area (in bytes)") \
\ \
product(uintx, SharedMiscCodeSize, 120*K, \ product(uintx, SharedMiscCodeSize, 120*K, \
"Size of the shared code area adjacent to the heap (in bytes)") \ "Size of the shared miscellaneous code area (in bytes)") \
\ \
product(uintx, SharedDummyBlockSize, 0, \ product(uintx, SharedDummyBlockSize, 0, \
"Size of dummy block used to shift heap addresses (in bytes)") \ "Size of dummy block used to shift heap addresses (in bytes)") \
......
...@@ -860,6 +860,17 @@ oop Reflection::new_field(fieldDescriptor* fd, bool intern_name, TRAPS) { ...@@ -860,6 +860,17 @@ oop Reflection::new_field(fieldDescriptor* fd, bool intern_name, TRAPS) {
return rh(); return rh();
} }
oop Reflection::new_parameter(Handle method, int index, Symbol* sym,
int flags, TRAPS) {
Handle name = java_lang_String::create_from_symbol(sym, CHECK_NULL);
Handle rh = java_lang_reflect_Parameter::create(CHECK_NULL);
java_lang_reflect_Parameter::set_name(rh(), name());
java_lang_reflect_Parameter::set_modifiers(rh(), flags);
java_lang_reflect_Parameter::set_executable(rh(), method());
java_lang_reflect_Parameter::set_index(rh(), index);
return rh();
}
methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, methodHandle method, methodHandle Reflection::resolve_interface_call(instanceKlassHandle klass, methodHandle method,
KlassHandle recv_klass, Handle receiver, TRAPS) { KlassHandle recv_klass, Handle receiver, TRAPS) {
......
...@@ -118,6 +118,10 @@ class Reflection: public AllStatic { ...@@ -118,6 +118,10 @@ class Reflection: public AllStatic {
static oop new_constructor(methodHandle method, TRAPS); static oop new_constructor(methodHandle method, TRAPS);
// Create a java.lang.reflect.Field object based on a field descriptor // Create a java.lang.reflect.Field object based on a field descriptor
static oop new_field(fieldDescriptor* fd, bool intern_name, TRAPS); static oop new_field(fieldDescriptor* fd, bool intern_name, TRAPS);
// Create a java.lang.reflect.Parameter object based on a
// MethodParameterElement
static oop new_parameter(Handle method, int index, Symbol* sym,
int flags, TRAPS);
private: private:
// method resolution for invoke // method resolution for invoke
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
* *
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "services/memBaseline.hpp" #include "services/memBaseline.hpp"
#include "services/memTracker.hpp" #include "services/memTracker.hpp"
...@@ -349,7 +348,7 @@ bool MemBaseline::baseline(MemSnapshot& snapshot, bool summary_only) { ...@@ -349,7 +348,7 @@ bool MemBaseline::baseline(MemSnapshot& snapshot, bool summary_only) {
reset(); reset();
_baselined = baseline_malloc_summary(snapshot._alloc_ptrs) && _baselined = baseline_malloc_summary(snapshot._alloc_ptrs) &&
baseline_vm_summary(snapshot._vm_ptrs); baseline_vm_summary(snapshot._vm_ptrs);
_number_of_classes = SystemDictionary::number_of_classes(); _number_of_classes = snapshot.number_of_classes();
if (!summary_only && MemTracker::track_callsite() && _baselined) { if (!summary_only && MemTracker::track_callsite() && _baselined) {
_baselined = baseline_malloc_details(snapshot._alloc_ptrs) && _baselined = baseline_malloc_details(snapshot._alloc_ptrs) &&
......
...@@ -84,10 +84,13 @@ MemRecorder::~MemRecorder() { ...@@ -84,10 +84,13 @@ MemRecorder::~MemRecorder() {
} }
delete _pointer_records; delete _pointer_records;
} }
if (_next != NULL) { // delete all linked recorders
delete _next; while (_next != NULL) {
MemRecorder* tmp = _next;
_next = _next->next();
tmp->set_next(NULL);
delete tmp;
} }
Atomic::dec(&_instance_count); Atomic::dec(&_instance_count);
} }
......
...@@ -203,6 +203,7 @@ class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> { ...@@ -203,6 +203,7 @@ class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> {
friend class MemSnapshot; friend class MemSnapshot;
friend class MemTracker; friend class MemTracker;
friend class MemTrackWorker; friend class MemTrackWorker;
friend class GenerationData;
protected: protected:
// the array that holds memory records // the array that holds memory records
......
...@@ -384,6 +384,7 @@ MemSnapshot::MemSnapshot() { ...@@ -384,6 +384,7 @@ MemSnapshot::MemSnapshot() {
_staging_area.init(); _staging_area.init();
_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf - 1, "memSnapshotLock"); _lock = new (std::nothrow) Mutex(Monitor::max_nonleaf - 1, "memSnapshotLock");
NOT_PRODUCT(_untracked_count = 0;) NOT_PRODUCT(_untracked_count = 0;)
_number_of_classes = 0;
} }
MemSnapshot::~MemSnapshot() { MemSnapshot::~MemSnapshot() {
...@@ -479,7 +480,7 @@ bool MemSnapshot::merge(MemRecorder* rec) { ...@@ -479,7 +480,7 @@ bool MemSnapshot::merge(MemRecorder* rec) {
// promote data to next generation // promote data to next generation
bool MemSnapshot::promote() { bool MemSnapshot::promote(int number_of_classes) {
assert(_alloc_ptrs != NULL && _vm_ptrs != NULL, "Just check"); assert(_alloc_ptrs != NULL && _vm_ptrs != NULL, "Just check");
assert(_staging_area.malloc_data() != NULL && _staging_area.vm_data() != NULL, assert(_staging_area.malloc_data() != NULL && _staging_area.vm_data() != NULL,
"Just check"); "Just check");
...@@ -496,6 +497,7 @@ bool MemSnapshot::promote() { ...@@ -496,6 +497,7 @@ bool MemSnapshot::promote() {
NOT_PRODUCT(check_malloc_pointers();) NOT_PRODUCT(check_malloc_pointers();)
_staging_area.clear(); _staging_area.clear();
_number_of_classes = number_of_classes;
return promoted; return promoted;
} }
......
...@@ -355,6 +355,9 @@ class MemSnapshot : public CHeapObj<mtNMT> { ...@@ -355,6 +355,9 @@ class MemSnapshot : public CHeapObj<mtNMT> {
// the lock to protect this snapshot // the lock to protect this snapshot
Monitor* _lock; Monitor* _lock;
// the number of instance classes
int _number_of_classes;
NOT_PRODUCT(size_t _untracked_count;) NOT_PRODUCT(size_t _untracked_count;)
friend class MemBaseline; friend class MemBaseline;
...@@ -375,8 +378,9 @@ class MemSnapshot : public CHeapObj<mtNMT> { ...@@ -375,8 +378,9 @@ class MemSnapshot : public CHeapObj<mtNMT> {
// merge a per-thread memory recorder into staging area // merge a per-thread memory recorder into staging area
bool merge(MemRecorder* rec); bool merge(MemRecorder* rec);
// promote staged data to snapshot // promote staged data to snapshot
bool promote(); bool promote(int number_of_classes);
int number_of_classes() const { return _number_of_classes; }
void wait(long timeout) { void wait(long timeout) {
assert(_lock != NULL, "Just check"); assert(_lock != NULL, "Just check");
......
...@@ -29,6 +29,16 @@ ...@@ -29,6 +29,16 @@
#include "utilities/decoder.hpp" #include "utilities/decoder.hpp"
#include "utilities/vmError.hpp" #include "utilities/vmError.hpp"
void GenerationData::reset() {
_number_of_classes = 0;
while (_recorder_list != NULL) {
MemRecorder* tmp = _recorder_list;
_recorder_list = _recorder_list->next();
MemTracker::release_thread_recorder(tmp);
}
}
MemTrackWorker::MemTrackWorker() { MemTrackWorker::MemTrackWorker() {
// create thread uses cgc thread type for now. We should revisit // create thread uses cgc thread type for now. We should revisit
// the option, or create new thread type. // the option, or create new thread type.
...@@ -39,7 +49,7 @@ MemTrackWorker::MemTrackWorker() { ...@@ -39,7 +49,7 @@ MemTrackWorker::MemTrackWorker() {
if (!has_error()) { if (!has_error()) {
_head = _tail = 0; _head = _tail = 0;
for(int index = 0; index < MAX_GENERATIONS; index ++) { for(int index = 0; index < MAX_GENERATIONS; index ++) {
_gen[index] = NULL; ::new ((void*)&_gen[index]) GenerationData();
} }
} }
NOT_PRODUCT(_sync_point_count = 0;) NOT_PRODUCT(_sync_point_count = 0;)
...@@ -49,10 +59,7 @@ MemTrackWorker::MemTrackWorker() { ...@@ -49,10 +59,7 @@ MemTrackWorker::MemTrackWorker() {
MemTrackWorker::~MemTrackWorker() { MemTrackWorker::~MemTrackWorker() {
for (int index = 0; index < MAX_GENERATIONS; index ++) { for (int index = 0; index < MAX_GENERATIONS; index ++) {
MemRecorder* rc = _gen[index]; _gen[index].reset();
if (rc != NULL) {
delete rc;
}
} }
} }
...@@ -90,12 +97,7 @@ void MemTrackWorker::run() { ...@@ -90,12 +97,7 @@ void MemTrackWorker::run() {
{ {
// take a recorder from earliest generation in buffer // take a recorder from earliest generation in buffer
ThreadCritical tc; ThreadCritical tc;
rec = _gen[_head]; rec = _gen[_head].next_recorder();
if (rec != NULL) {
_gen[_head] = rec->next();
}
assert(count_recorder(_gen[_head]) <= MemRecorder::_instance_count,
"infinite loop after dequeue");
} }
if (rec != NULL) { if (rec != NULL) {
// merge the recorder into staging area // merge the recorder into staging area
...@@ -109,16 +111,20 @@ void MemTrackWorker::run() { ...@@ -109,16 +111,20 @@ void MemTrackWorker::run() {
// no more recorder to merge, promote staging area // no more recorder to merge, promote staging area
// to snapshot // to snapshot
if (_head != _tail) { if (_head != _tail) {
long number_of_classes;
{ {
ThreadCritical tc; ThreadCritical tc;
if (_gen[_head] != NULL || _head == _tail) { if (_gen[_head].has_more_recorder() || _head == _tail) {
continue; continue;
} }
number_of_classes = _gen[_head].number_of_classes();
_gen[_head].reset();
// done with this generation, increment _head pointer // done with this generation, increment _head pointer
_head = (_head + 1) % MAX_GENERATIONS; _head = (_head + 1) % MAX_GENERATIONS;
} }
// promote this generation data to snapshot // promote this generation data to snapshot
if (!snapshot->promote()) { if (!snapshot->promote(number_of_classes)) {
// failed to promote, means out of memory // failed to promote, means out of memory
MemTracker::shutdown(MemTracker::NMT_out_of_memory); MemTracker::shutdown(MemTracker::NMT_out_of_memory);
} }
...@@ -126,8 +132,8 @@ void MemTrackWorker::run() { ...@@ -126,8 +132,8 @@ void MemTrackWorker::run() {
snapshot->wait(1000); snapshot->wait(1000);
ThreadCritical tc; ThreadCritical tc;
// check if more data arrived // check if more data arrived
if (_gen[_head] == NULL) { if (!_gen[_head].has_more_recorder()) {
_gen[_head] = MemTracker::get_pending_recorders(); _gen[_head].add_recorders(MemTracker::get_pending_recorders());
} }
} }
} }
...@@ -147,7 +153,7 @@ void MemTrackWorker::run() { ...@@ -147,7 +153,7 @@ void MemTrackWorker::run() {
// 1. add all recorders in pending queue to current generation // 1. add all recorders in pending queue to current generation
// 2. increase generation // 2. increase generation
void MemTrackWorker::at_sync_point(MemRecorder* rec) { void MemTrackWorker::at_sync_point(MemRecorder* rec, int number_of_classes) {
NOT_PRODUCT(_sync_point_count ++;) NOT_PRODUCT(_sync_point_count ++;)
assert(count_recorder(rec) <= MemRecorder::_instance_count, assert(count_recorder(rec) <= MemRecorder::_instance_count,
"pending queue has infinite loop"); "pending queue has infinite loop");
...@@ -155,23 +161,15 @@ void MemTrackWorker::at_sync_point(MemRecorder* rec) { ...@@ -155,23 +161,15 @@ void MemTrackWorker::at_sync_point(MemRecorder* rec) {
bool out_of_generation_buffer = false; bool out_of_generation_buffer = false;
// check shutdown state inside ThreadCritical // check shutdown state inside ThreadCritical
if (MemTracker::shutdown_in_progress()) return; if (MemTracker::shutdown_in_progress()) return;
_gen[_tail].set_number_of_classes(number_of_classes);
// append the recorders to the end of the generation // append the recorders to the end of the generation
if( rec != NULL) { _gen[_tail].add_recorders(rec);
MemRecorder* cur_head = _gen[_tail]; assert(count_recorder(_gen[_tail].peek()) <= MemRecorder::_instance_count,
if (cur_head == NULL) {
_gen[_tail] = rec;
} else {
while (cur_head->next() != NULL) {
cur_head = cur_head->next();
}
cur_head->set_next(rec);
}
}
assert(count_recorder(rec) <= MemRecorder::_instance_count,
"after add to current generation has infinite loop"); "after add to current generation has infinite loop");
// we have collected all recorders for this generation. If there is data, // we have collected all recorders for this generation. If there is data,
// we need to increment _tail to start a new generation. // we need to increment _tail to start a new generation.
if (_gen[_tail] != NULL || _head == _tail) { if (_gen[_tail].has_more_recorder() || _head == _tail) {
_tail = (_tail + 1) % MAX_GENERATIONS; _tail = (_tail + 1) % MAX_GENERATIONS;
out_of_generation_buffer = (_tail == _head); out_of_generation_buffer = (_tail == _head);
} }
...@@ -194,7 +192,7 @@ int MemTrackWorker::count_recorder(const MemRecorder* head) { ...@@ -194,7 +192,7 @@ int MemTrackWorker::count_recorder(const MemRecorder* head) {
int MemTrackWorker::count_pending_recorders() const { int MemTrackWorker::count_pending_recorders() const {
int count = 0; int count = 0;
for (int index = 0; index < MAX_GENERATIONS; index ++) { for (int index = 0; index < MAX_GENERATIONS; index ++) {
MemRecorder* head = _gen[index]; MemRecorder* head = _gen[index].peek();
if (head != NULL) { if (head != NULL) {
count += count_recorder(head); count += count_recorder(head);
} }
......
...@@ -32,14 +32,55 @@ ...@@ -32,14 +32,55 @@
// Maximum MAX_GENERATIONS generation data can be tracked. // Maximum MAX_GENERATIONS generation data can be tracked.
#define MAX_GENERATIONS 512 #define MAX_GENERATIONS 512
class GenerationData : public _ValueObj {
private:
int _number_of_classes;
MemRecorder* _recorder_list;
public:
GenerationData(): _number_of_classes(0), _recorder_list(NULL) { }
inline int number_of_classes() const { return _number_of_classes; }
inline void set_number_of_classes(long num) { _number_of_classes = num; }
inline MemRecorder* next_recorder() {
if (_recorder_list == NULL) {
return NULL;
} else {
MemRecorder* tmp = _recorder_list;
_recorder_list = _recorder_list->next();
return tmp;
}
}
inline bool has_more_recorder() const {
return (_recorder_list != NULL);
}
// add recorders to this generation
void add_recorders(MemRecorder* head) {
if (head != NULL) {
if (_recorder_list == NULL) {
_recorder_list = head;
} else {
MemRecorder* tmp = _recorder_list;
for (; tmp->next() != NULL; tmp = tmp->next());
tmp->set_next(head);
}
}
}
void reset();
NOT_PRODUCT(MemRecorder* peek() const { return _recorder_list; })
};
class MemTrackWorker : public NamedThread { class MemTrackWorker : public NamedThread {
private: private:
// circular buffer. This buffer contains recorders to be merged into global // circular buffer. This buffer contains generation data to be merged into global
// snaphsot. // snaphsot.
// Each slot holds a linked list of memory recorders, that contains one // Each slot holds a generation
// generation of memory data. GenerationData _gen[MAX_GENERATIONS];
MemRecorder* _gen[MAX_GENERATIONS];
int _head, _tail; // head and tail pointers to above circular buffer int _head, _tail; // head and tail pointers to above circular buffer
bool _has_error; bool _has_error;
...@@ -56,7 +97,7 @@ class MemTrackWorker : public NamedThread { ...@@ -56,7 +97,7 @@ class MemTrackWorker : public NamedThread {
inline bool has_error() const { return _has_error; } inline bool has_error() const { return _has_error; }
// task at synchronization point // task at synchronization point
void at_sync_point(MemRecorder* pending_recorders); void at_sync_point(MemRecorder* pending_recorders, int number_of_classes);
// for debugging purpose, they are not thread safe. // for debugging purpose, they are not thread safe.
NOT_PRODUCT(static int count_recorder(const MemRecorder* head);) NOT_PRODUCT(static int count_recorder(const MemRecorder* head);)
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "oops/instanceKlass.hpp"
#include "runtime/atomic.hpp" #include "runtime/atomic.hpp"
#include "runtime/interfaceSupport.hpp" #include "runtime/interfaceSupport.hpp"
#include "runtime/mutexLocker.hpp" #include "runtime/mutexLocker.hpp"
...@@ -485,7 +486,7 @@ void MemTracker::sync() { ...@@ -485,7 +486,7 @@ void MemTracker::sync() {
} }
// check _worker_thread with lock to avoid racing condition // check _worker_thread with lock to avoid racing condition
if (_worker_thread != NULL) { if (_worker_thread != NULL) {
_worker_thread->at_sync_point(pending_recorders); _worker_thread->at_sync_point(pending_recorders, InstanceKlass::number_of_instance_classes());
} }
assert(SequenceGenerator::peek() == 1, "Should not have memory activities during sync-point"); assert(SequenceGenerator::peek() == 1, "Should not have memory activities during sync-point");
......
...@@ -142,6 +142,7 @@ class Thread; ...@@ -142,6 +142,7 @@ class Thread;
* MemTracker is the 'gate' class to native memory tracking runtime. * MemTracker is the 'gate' class to native memory tracking runtime.
*/ */
class MemTracker : AllStatic { class MemTracker : AllStatic {
friend class GenerationData;
friend class MemTrackWorker; friend class MemTrackWorker;
friend class MemSnapshot; friend class MemSnapshot;
friend class SyncThreadRecorderClosure; friend class SyncThreadRecorderClosure;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册