mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
6711908: JVM needs direct access to some annotations
Add annotation extraction code to class file parser. Reviewed-by: twisti, jrose, kvn
This commit is contained in:
parent
e2fc7f742c
commit
e0cf9c652d
6 changed files with 316 additions and 43 deletions
|
@ -3505,8 +3505,10 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, BlockBeg
|
||||||
}
|
}
|
||||||
|
|
||||||
// now perform tests that are based on flag settings
|
// now perform tests that are based on flag settings
|
||||||
if (callee->should_inline()) {
|
if (callee->force_inline() || callee->should_inline()) {
|
||||||
// ignore heuristic controls on inlining
|
// ignore heuristic controls on inlining
|
||||||
|
if (callee->force_inline())
|
||||||
|
CompileTask::print_inlining(callee, scope()->level(), bci(), "force inline by annotation");
|
||||||
} else {
|
} else {
|
||||||
if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("too-deep inlining");
|
if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("too-deep inlining");
|
||||||
if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("too-deep recursive inlining");
|
if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("too-deep recursive inlining");
|
||||||
|
|
|
@ -160,6 +160,8 @@ class ciMethod : public ciObject {
|
||||||
// Code size for inlining decisions.
|
// Code size for inlining decisions.
|
||||||
int code_size_for_inlining();
|
int code_size_for_inlining();
|
||||||
|
|
||||||
|
bool force_inline() { return get_methodOop()->force_inline(); }
|
||||||
|
|
||||||
int comp_level();
|
int comp_level();
|
||||||
int highest_osr_comp_level();
|
int highest_osr_comp_level();
|
||||||
|
|
||||||
|
|
|
@ -318,6 +318,13 @@ class ConstantPoolCleaner : public StackObj {
|
||||||
|
|
||||||
bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
|
bool inline valid_cp_range(int index, int length) { return (index > 0 && index < length); }
|
||||||
|
|
||||||
|
inline Symbol* check_symbol_at(constantPoolHandle cp, int index) {
|
||||||
|
if (valid_cp_range(index, cp->length()) && cp->tag_at(index).is_utf8())
|
||||||
|
return cp->symbol_at(index);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
constantPoolHandle ClassFileParser::parse_constant_pool(Handle class_loader, TRAPS) {
|
constantPoolHandle ClassFileParser::parse_constant_pool(Handle class_loader, TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
constantPoolHandle nullHandle;
|
constantPoolHandle nullHandle;
|
||||||
|
@ -902,6 +909,7 @@ void ClassFileParser::parse_field_attributes(constantPoolHandle cp,
|
||||||
bool* is_synthetic_addr,
|
bool* is_synthetic_addr,
|
||||||
u2* generic_signature_index_addr,
|
u2* generic_signature_index_addr,
|
||||||
typeArrayHandle* field_annotations,
|
typeArrayHandle* field_annotations,
|
||||||
|
ClassFileParser::FieldAnnotationCollector* parsed_annotations,
|
||||||
TRAPS) {
|
TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
assert(attributes_count > 0, "length should be greater than 0");
|
assert(attributes_count > 0, "length should be greater than 0");
|
||||||
|
@ -1142,12 +1150,14 @@ typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name,
|
||||||
bool is_synthetic = false;
|
bool is_synthetic = false;
|
||||||
u2 generic_signature_index = 0;
|
u2 generic_signature_index = 0;
|
||||||
bool is_static = access_flags.is_static();
|
bool is_static = access_flags.is_static();
|
||||||
|
FieldAnnotationCollector parsed_annotations;
|
||||||
|
|
||||||
u2 attributes_count = cfs->get_u2_fast();
|
u2 attributes_count = cfs->get_u2_fast();
|
||||||
if (attributes_count > 0) {
|
if (attributes_count > 0) {
|
||||||
parse_field_attributes(cp, attributes_count, is_static, signature_index,
|
parse_field_attributes(cp, attributes_count, is_static, signature_index,
|
||||||
&constantvalue_index, &is_synthetic,
|
&constantvalue_index, &is_synthetic,
|
||||||
&generic_signature_index, &field_annotations,
|
&generic_signature_index, &field_annotations,
|
||||||
|
&parsed_annotations,
|
||||||
CHECK_(nullHandle));
|
CHECK_(nullHandle));
|
||||||
if (field_annotations.not_null()) {
|
if (field_annotations.not_null()) {
|
||||||
if (fields_annotations->is_null()) {
|
if (fields_annotations->is_null()) {
|
||||||
|
@ -1173,6 +1183,8 @@ typeArrayHandle ClassFileParser::parse_fields(Symbol* class_name,
|
||||||
signature_index,
|
signature_index,
|
||||||
constantvalue_index,
|
constantvalue_index,
|
||||||
0);
|
0);
|
||||||
|
if (parsed_annotations.has_any_annotations())
|
||||||
|
parsed_annotations.apply_to(field);
|
||||||
|
|
||||||
BasicType type = cp->basic_type_for_signature_at(signature_index);
|
BasicType type = cp->basic_type_for_signature_at(signature_index);
|
||||||
|
|
||||||
|
@ -1638,12 +1650,158 @@ void ClassFileParser::throwIllegalSignature(
|
||||||
name->as_C_string(), _class_name->as_C_string(), sig->as_C_string());
|
name->as_C_string(), _class_name->as_C_string(), sig->as_C_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skip an annotation. Return >=limit if there is any problem.
|
||||||
|
int ClassFileParser::skip_annotation(u1* buffer, int limit, int index) {
|
||||||
|
// annotation := atype:u2 do(nmem:u2) {member:u2 value}
|
||||||
|
// value := switch (tag:u1) { ... }
|
||||||
|
index += 2; // skip atype
|
||||||
|
if ((index += 2) >= limit) return limit; // read nmem
|
||||||
|
int nmem = Bytes::get_Java_u2(buffer+index-2);
|
||||||
|
while (--nmem >= 0 && index < limit) {
|
||||||
|
index += 2; // skip member
|
||||||
|
index = skip_annotation_value(buffer, limit, index);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip an annotation value. Return >=limit if there is any problem.
|
||||||
|
int ClassFileParser::skip_annotation_value(u1* buffer, int limit, int index) {
|
||||||
|
// value := switch (tag:u1) {
|
||||||
|
// case B, C, I, S, Z, D, F, J, c: con:u2;
|
||||||
|
// case e: e_class:u2 e_name:u2;
|
||||||
|
// case s: s_con:u2;
|
||||||
|
// case [: do(nval:u2) {value};
|
||||||
|
// case @: annotation;
|
||||||
|
// case s: s_con:u2;
|
||||||
|
// }
|
||||||
|
if ((index += 1) >= limit) return limit; // read tag
|
||||||
|
u1 tag = buffer[index-1];
|
||||||
|
switch (tag) {
|
||||||
|
case 'B': case 'C': case 'I': case 'S': case 'Z':
|
||||||
|
case 'D': case 'F': case 'J': case 'c': case 's':
|
||||||
|
index += 2; // skip con or s_con
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
index += 4; // skip e_class, e_name
|
||||||
|
break;
|
||||||
|
case '[':
|
||||||
|
{
|
||||||
|
if ((index += 2) >= limit) return limit; // read nval
|
||||||
|
int nval = Bytes::get_Java_u2(buffer+index-2);
|
||||||
|
while (--nval >= 0 && index < limit) {
|
||||||
|
index = skip_annotation_value(buffer, limit, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '@':
|
||||||
|
index = skip_annotation(buffer, limit, index);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false, "annotation tag");
|
||||||
|
return limit; // bad tag byte
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sift through annotations, looking for those significant to the VM:
|
||||||
|
void ClassFileParser::parse_annotations(u1* buffer, int limit,
|
||||||
|
constantPoolHandle cp,
|
||||||
|
ClassFileParser::AnnotationCollector* coll,
|
||||||
|
TRAPS) {
|
||||||
|
// annotations := do(nann:u2) {annotation}
|
||||||
|
int index = 0;
|
||||||
|
if ((index += 2) >= limit) return; // read nann
|
||||||
|
int nann = Bytes::get_Java_u2(buffer+index-2);
|
||||||
|
enum { // initial annotation layout
|
||||||
|
atype_off = 0, // utf8 such as 'Ljava/lang/annotation/Retention;'
|
||||||
|
count_off = 2, // u2 such as 1 (one value)
|
||||||
|
member_off = 4, // utf8 such as 'value'
|
||||||
|
tag_off = 6, // u1 such as 'c' (type) or 'e' (enum)
|
||||||
|
e_tag_val = 'e',
|
||||||
|
e_type_off = 7, // utf8 such as 'Ljava/lang/annotation/RetentionPolicy;'
|
||||||
|
e_con_off = 9, // utf8 payload, such as 'SOURCE', 'CLASS', 'RUNTIME'
|
||||||
|
e_size = 11, // end of 'e' annotation
|
||||||
|
c_tag_val = 'c',
|
||||||
|
c_con_off = 7, // utf8 payload, such as 'I' or 'Ljava/lang/String;'
|
||||||
|
c_size = 9, // end of 'c' annotation
|
||||||
|
min_size = 6 // smallest possible size (zero members)
|
||||||
|
};
|
||||||
|
while ((--nann) >= 0 && (index-2 + min_size <= limit)) {
|
||||||
|
int index0 = index;
|
||||||
|
index = skip_annotation(buffer, limit, index);
|
||||||
|
u1* abase = buffer + index0;
|
||||||
|
int atype = Bytes::get_Java_u2(abase + atype_off);
|
||||||
|
int count = Bytes::get_Java_u2(abase + count_off);
|
||||||
|
Symbol* aname = check_symbol_at(cp, atype);
|
||||||
|
if (aname == NULL) break; // invalid annotation name
|
||||||
|
Symbol* member = NULL;
|
||||||
|
if (count >= 1) {
|
||||||
|
int member_index = Bytes::get_Java_u2(abase + member_off);
|
||||||
|
member = check_symbol_at(cp, member_index);
|
||||||
|
if (member == NULL) break; // invalid member name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here is where parsing particular annotations will take place.
|
||||||
|
AnnotationCollector::ID id = coll->annotation_index(aname);
|
||||||
|
if (id == AnnotationCollector::_unknown) continue;
|
||||||
|
coll->set_annotation(id);
|
||||||
|
// If there are no values, just set the bit and move on:
|
||||||
|
if (count == 0) continue;
|
||||||
|
|
||||||
|
// For the record, here is how annotation payloads can be collected.
|
||||||
|
// Suppose we want to capture @Retention.value. Here is how:
|
||||||
|
//if (id == AnnotationCollector::_class_Retention) {
|
||||||
|
// Symbol* payload = NULL;
|
||||||
|
// if (count == 1
|
||||||
|
// && e_size == (index0 - index) // match size
|
||||||
|
// && e_tag_val == *(abase + tag_off)
|
||||||
|
// && (check_symbol_at(cp, Bytes::get_Java_u2(abase + e_type_off))
|
||||||
|
// == vmSymbols::RetentionPolicy_signature())
|
||||||
|
// && member == vmSymbols::value_name()) {
|
||||||
|
// payload = check_symbol_at(cp, Bytes::get_Java_u2(abase + e_con_off));
|
||||||
|
// }
|
||||||
|
// check_property(payload != NULL,
|
||||||
|
// "Invalid @Retention annotation at offset %u in class file %s",
|
||||||
|
// index0, CHECK);
|
||||||
|
// if (payload != NULL) {
|
||||||
|
// payload->increment_refcount();
|
||||||
|
// coll->_class_RetentionPolicy = payload;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFileParser::AnnotationCollector::ID ClassFileParser::AnnotationCollector::annotation_index(Symbol* name) {
|
||||||
|
vmSymbols::SID sid = vmSymbols::find_sid(name);
|
||||||
|
switch (sid) {
|
||||||
|
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_ForceInline_signature):
|
||||||
|
if (_location != _in_method) break; // only allow for methods
|
||||||
|
return _method_ForceInline;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return AnnotationCollector::_unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) {
|
||||||
|
fatal("no field annotations yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassFileParser::MethodAnnotationCollector::apply_to(methodHandle m) {
|
||||||
|
if (has_annotation(_method_ForceInline))
|
||||||
|
m->set_force_inline(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassFileParser::ClassAnnotationCollector::apply_to(instanceKlassHandle k) {
|
||||||
|
fatal("no class annotations yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define MAX_ARGS_SIZE 255
|
#define MAX_ARGS_SIZE 255
|
||||||
#define MAX_CODE_SIZE 65535
|
#define MAX_CODE_SIZE 65535
|
||||||
#define INITIAL_MAX_LVT_NUMBER 256
|
#define INITIAL_MAX_LVT_NUMBER 256
|
||||||
|
|
||||||
// Note: the parse_method below is big and clunky because all parsing of the code and exceptions
|
// Note: the parse_method below is big and clunky because all parsing of the code and exceptions
|
||||||
// attribute is inlined. This is curbersome to avoid since we inline most of the parts in the
|
// attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the
|
||||||
// methodOop to save footprint, so we only know the size of the resulting methodOop when the
|
// methodOop to save footprint, so we only know the size of the resulting methodOop when the
|
||||||
// entire method attribute is parsed.
|
// entire method attribute is parsed.
|
||||||
//
|
//
|
||||||
|
@ -1733,6 +1891,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
||||||
// stackmap attribute - JDK1.5
|
// stackmap attribute - JDK1.5
|
||||||
typeArrayHandle stackmap_data;
|
typeArrayHandle stackmap_data;
|
||||||
u2 generic_signature_index = 0;
|
u2 generic_signature_index = 0;
|
||||||
|
MethodAnnotationCollector parsed_annotations;
|
||||||
u1* runtime_visible_annotations = NULL;
|
u1* runtime_visible_annotations = NULL;
|
||||||
int runtime_visible_annotations_length = 0;
|
int runtime_visible_annotations_length = 0;
|
||||||
u1* runtime_invisible_annotations = NULL;
|
u1* runtime_invisible_annotations = NULL;
|
||||||
|
@ -1959,6 +2118,7 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
||||||
runtime_visible_annotations_length = method_attribute_length;
|
runtime_visible_annotations_length = method_attribute_length;
|
||||||
runtime_visible_annotations = cfs->get_u1_buffer();
|
runtime_visible_annotations = cfs->get_u1_buffer();
|
||||||
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
||||||
|
parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, cp, &parsed_annotations, CHECK_(nullHandle));
|
||||||
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
|
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
|
||||||
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
|
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
|
||||||
runtime_invisible_annotations_length = method_attribute_length;
|
runtime_invisible_annotations_length = method_attribute_length;
|
||||||
|
@ -2136,6 +2296,8 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
|
||||||
clear_hashtable(lvt_Hash);
|
clear_hashtable(lvt_Hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parsed_annotations.has_any_annotations())
|
||||||
|
parsed_annotations.apply_to(m);
|
||||||
*method_annotations = assemble_annotations(runtime_visible_annotations,
|
*method_annotations = assemble_annotations(runtime_visible_annotations,
|
||||||
runtime_visible_annotations_length,
|
runtime_visible_annotations_length,
|
||||||
runtime_invisible_annotations,
|
runtime_invisible_annotations,
|
||||||
|
@ -2314,7 +2476,7 @@ typeArrayHandle ClassFileParser::sort_methods(objArrayHandle methods,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ClassFileParser::parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
|
void ClassFileParser::parse_classfile_sourcefile_attribute(constantPoolHandle cp, TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
cfs->guarantee_more(2, CHECK); // sourcefile_index
|
cfs->guarantee_more(2, CHECK); // sourcefile_index
|
||||||
u2 sourcefile_index = cfs->get_u2_fast();
|
u2 sourcefile_index = cfs->get_u2_fast();
|
||||||
|
@ -2323,13 +2485,12 @@ void ClassFileParser::parse_classfile_sourcefile_attribute(constantPoolHandle cp
|
||||||
cp->tag_at(sourcefile_index).is_utf8(),
|
cp->tag_at(sourcefile_index).is_utf8(),
|
||||||
"Invalid SourceFile attribute at constant pool index %u in class file %s",
|
"Invalid SourceFile attribute at constant pool index %u in class file %s",
|
||||||
sourcefile_index, CHECK);
|
sourcefile_index, CHECK);
|
||||||
k->set_source_file_name(cp->symbol_at(sourcefile_index));
|
set_class_sourcefile(cp->symbol_at(sourcefile_index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
|
void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
|
||||||
instanceKlassHandle k,
|
|
||||||
int length, TRAPS) {
|
int length, TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
u1* sde_buffer = cfs->get_u1_buffer();
|
u1* sde_buffer = cfs->get_u1_buffer();
|
||||||
|
@ -2340,9 +2501,9 @@ void ClassFileParser::parse_classfile_source_debug_extension_attribute(constantP
|
||||||
// Optimistically assume that only 1 byte UTF format is used
|
// Optimistically assume that only 1 byte UTF format is used
|
||||||
// (common case)
|
// (common case)
|
||||||
TempNewSymbol sde_symbol = SymbolTable::new_symbol((const char*)sde_buffer, length, CHECK);
|
TempNewSymbol sde_symbol = SymbolTable::new_symbol((const char*)sde_buffer, length, CHECK);
|
||||||
k->set_source_debug_extension(sde_symbol);
|
|
||||||
// Note that set_source_debug_extension() increments the reference count
|
// Note that set_source_debug_extension() increments the reference count
|
||||||
// for its copy of the Symbol*, so use a TempNewSymbol here.
|
// for its copy of the Symbol*, so use a TempNewSymbol here.
|
||||||
|
set_class_sde_symbol(sde_symbol);
|
||||||
}
|
}
|
||||||
// Got utf8 string, set stream position forward
|
// Got utf8 string, set stream position forward
|
||||||
cfs->skip_u1(length, CHECK);
|
cfs->skip_u1(length, CHECK);
|
||||||
|
@ -2358,7 +2519,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_at
|
||||||
u2 enclosing_method_class_index,
|
u2 enclosing_method_class_index,
|
||||||
u2 enclosing_method_method_index,
|
u2 enclosing_method_method_index,
|
||||||
constantPoolHandle cp,
|
constantPoolHandle cp,
|
||||||
instanceKlassHandle k, TRAPS) {
|
TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
u1* current_mark = cfs->current();
|
u1* current_mark = cfs->current();
|
||||||
u2 length = 0;
|
u2 length = 0;
|
||||||
|
@ -2449,7 +2610,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_at
|
||||||
assert(index == size, "wrong size");
|
assert(index == size, "wrong size");
|
||||||
|
|
||||||
// Update instanceKlass with inner class info.
|
// Update instanceKlass with inner class info.
|
||||||
k->set_inner_classes(inner_classes());
|
set_class_inner_classes(inner_classes);
|
||||||
|
|
||||||
// Restore buffer's current position.
|
// Restore buffer's current position.
|
||||||
cfs->set_current(current_mark);
|
cfs->set_current(current_mark);
|
||||||
|
@ -2457,11 +2618,11 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_at
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassFileParser::parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
|
void ClassFileParser::parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS) {
|
||||||
k->set_is_synthetic();
|
set_class_synthetic_flag(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassFileParser::parse_classfile_signature_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
|
void ClassFileParser::parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
u2 signature_index = cfs->get_u2(CHECK);
|
u2 signature_index = cfs->get_u2(CHECK);
|
||||||
check_property(
|
check_property(
|
||||||
|
@ -2469,10 +2630,10 @@ void ClassFileParser::parse_classfile_signature_attribute(constantPoolHandle cp,
|
||||||
cp->tag_at(signature_index).is_utf8(),
|
cp->tag_at(signature_index).is_utf8(),
|
||||||
"Invalid constant pool index %u in Signature attribute in class file %s",
|
"Invalid constant pool index %u in Signature attribute in class file %s",
|
||||||
signature_index, CHECK);
|
signature_index, CHECK);
|
||||||
k->set_generic_signature(cp->symbol_at(signature_index));
|
set_class_generic_signature(cp->symbol_at(signature_index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, instanceKlassHandle k,
|
void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp,
|
||||||
u4 attribute_byte_length, TRAPS) {
|
u4 attribute_byte_length, TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
u1* current_start = cfs->current();
|
u1* current_start = cfs->current();
|
||||||
|
@ -2544,10 +2705,12 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(constantPoolHa
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS) {
|
void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp,
|
||||||
|
ClassFileParser::ClassAnnotationCollector* parsed_annotations,
|
||||||
|
TRAPS) {
|
||||||
ClassFileStream* cfs = stream();
|
ClassFileStream* cfs = stream();
|
||||||
// Set inner classes attribute to default sentinel
|
// Set inner classes attribute to default sentinel
|
||||||
k->set_inner_classes(Universe::the_empty_short_array());
|
set_class_inner_classes(typeArrayHandle(THREAD, Universe::the_empty_short_array()));
|
||||||
cfs->guarantee_more(2, CHECK); // attributes_count
|
cfs->guarantee_more(2, CHECK); // attributes_count
|
||||||
u2 attributes_count = cfs->get_u2_fast();
|
u2 attributes_count = cfs->get_u2_fast();
|
||||||
bool parsed_sourcefile_attribute = false;
|
bool parsed_sourcefile_attribute = false;
|
||||||
|
@ -2583,10 +2746,10 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
|
||||||
} else {
|
} else {
|
||||||
parsed_sourcefile_attribute = true;
|
parsed_sourcefile_attribute = true;
|
||||||
}
|
}
|
||||||
parse_classfile_sourcefile_attribute(cp, k, CHECK);
|
parse_classfile_sourcefile_attribute(cp, CHECK);
|
||||||
} else if (tag == vmSymbols::tag_source_debug_extension()) {
|
} else if (tag == vmSymbols::tag_source_debug_extension()) {
|
||||||
// Check for SourceDebugExtension tag
|
// Check for SourceDebugExtension tag
|
||||||
parse_classfile_source_debug_extension_attribute(cp, k, (int)attribute_length, CHECK);
|
parse_classfile_source_debug_extension_attribute(cp, (int)attribute_length, CHECK);
|
||||||
} else if (tag == vmSymbols::tag_inner_classes()) {
|
} else if (tag == vmSymbols::tag_inner_classes()) {
|
||||||
// Check for InnerClasses tag
|
// Check for InnerClasses tag
|
||||||
if (parsed_innerclasses_attribute) {
|
if (parsed_innerclasses_attribute) {
|
||||||
|
@ -2605,7 +2768,7 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
|
||||||
"Invalid Synthetic classfile attribute length %u in class file %s",
|
"Invalid Synthetic classfile attribute length %u in class file %s",
|
||||||
attribute_length, CHECK);
|
attribute_length, CHECK);
|
||||||
}
|
}
|
||||||
parse_classfile_synthetic_attribute(cp, k, CHECK);
|
parse_classfile_synthetic_attribute(cp, CHECK);
|
||||||
} else if (tag == vmSymbols::tag_deprecated()) {
|
} else if (tag == vmSymbols::tag_deprecated()) {
|
||||||
// Check for Deprecatd tag - 4276120
|
// Check for Deprecatd tag - 4276120
|
||||||
if (attribute_length != 0) {
|
if (attribute_length != 0) {
|
||||||
|
@ -2620,11 +2783,16 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
|
||||||
"Wrong Signature attribute length %u in class file %s",
|
"Wrong Signature attribute length %u in class file %s",
|
||||||
attribute_length, CHECK);
|
attribute_length, CHECK);
|
||||||
}
|
}
|
||||||
parse_classfile_signature_attribute(cp, k, CHECK);
|
parse_classfile_signature_attribute(cp, CHECK);
|
||||||
} else if (tag == vmSymbols::tag_runtime_visible_annotations()) {
|
} else if (tag == vmSymbols::tag_runtime_visible_annotations()) {
|
||||||
runtime_visible_annotations_length = attribute_length;
|
runtime_visible_annotations_length = attribute_length;
|
||||||
runtime_visible_annotations = cfs->get_u1_buffer();
|
runtime_visible_annotations = cfs->get_u1_buffer();
|
||||||
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
||||||
|
parse_annotations(runtime_visible_annotations,
|
||||||
|
runtime_visible_annotations_length,
|
||||||
|
cp,
|
||||||
|
parsed_annotations,
|
||||||
|
CHECK);
|
||||||
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
|
cfs->skip_u1(runtime_visible_annotations_length, CHECK);
|
||||||
} else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_annotations()) {
|
} else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_annotations()) {
|
||||||
runtime_invisible_annotations_length = attribute_length;
|
runtime_invisible_annotations_length = attribute_length;
|
||||||
|
@ -2658,7 +2826,7 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
|
||||||
if (parsed_bootstrap_methods_attribute)
|
if (parsed_bootstrap_methods_attribute)
|
||||||
classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK);
|
classfile_parse_error("Multiple BootstrapMethods attributes in class file %s", CHECK);
|
||||||
parsed_bootstrap_methods_attribute = true;
|
parsed_bootstrap_methods_attribute = true;
|
||||||
parse_classfile_bootstrap_methods_attribute(cp, k, attribute_length, CHECK);
|
parse_classfile_bootstrap_methods_attribute(cp, attribute_length, CHECK);
|
||||||
} else {
|
} else {
|
||||||
// Unknown attribute
|
// Unknown attribute
|
||||||
cfs->skip_u1(attribute_length, CHECK);
|
cfs->skip_u1(attribute_length, CHECK);
|
||||||
|
@ -2673,7 +2841,7 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
|
||||||
runtime_invisible_annotations,
|
runtime_invisible_annotations,
|
||||||
runtime_invisible_annotations_length,
|
runtime_invisible_annotations_length,
|
||||||
CHECK);
|
CHECK);
|
||||||
k->set_class_annotations(annotations());
|
set_class_annotations(annotations);
|
||||||
|
|
||||||
if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
|
if (parsed_innerclasses_attribute || parsed_enclosingmethod_attribute) {
|
||||||
u2 num_of_classes = parse_classfile_inner_classes_attribute(
|
u2 num_of_classes = parse_classfile_inner_classes_attribute(
|
||||||
|
@ -2681,7 +2849,7 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
|
||||||
parsed_innerclasses_attribute,
|
parsed_innerclasses_attribute,
|
||||||
enclosing_method_class_index,
|
enclosing_method_class_index,
|
||||||
enclosing_method_method_index,
|
enclosing_method_method_index,
|
||||||
cp, k, CHECK);
|
cp, CHECK);
|
||||||
if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) {
|
if (parsed_innerclasses_attribute &&_need_verify && _major_version >= JAVA_1_5_VERSION) {
|
||||||
guarantee_property(
|
guarantee_property(
|
||||||
inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
|
inner_classes_attribute_length == sizeof(num_of_classes) + 4 * sizeof(u2) * num_of_classes,
|
||||||
|
@ -2695,6 +2863,21 @@ void ClassFileParser::parse_classfile_attributes(constantPoolHandle cp, instance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClassFileParser::apply_parsed_class_attributes(instanceKlassHandle k) {
|
||||||
|
if (_synthetic_flag)
|
||||||
|
k->set_is_synthetic();
|
||||||
|
if (_sourcefile != NULL) {
|
||||||
|
_sourcefile->increment_refcount();
|
||||||
|
k->set_source_file_name(_sourcefile);
|
||||||
|
}
|
||||||
|
if (_generic_signature != NULL) {
|
||||||
|
_generic_signature->increment_refcount();
|
||||||
|
k->set_generic_signature(_generic_signature);
|
||||||
|
}
|
||||||
|
k->set_source_debug_extension(_sde_symbol); // increment_refcount inside
|
||||||
|
k->set_inner_classes(_inner_classes());
|
||||||
|
k->set_class_annotations(_annotations());
|
||||||
|
}
|
||||||
|
|
||||||
typeArrayHandle ClassFileParser::assemble_annotations(u1* runtime_visible_annotations,
|
typeArrayHandle ClassFileParser::assemble_annotations(u1* runtime_visible_annotations,
|
||||||
int runtime_visible_annotations_length,
|
int runtime_visible_annotations_length,
|
||||||
|
@ -2745,8 +2928,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
jt->get_thread_stat()->perf_timers_addr(),
|
jt->get_thread_stat()->perf_timers_addr(),
|
||||||
PerfClassTraceTime::PARSE_CLASS);
|
PerfClassTraceTime::PARSE_CLASS);
|
||||||
|
|
||||||
_has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false;
|
init_parsed_class_attributes();
|
||||||
_max_bootstrap_specifier_index = -1;
|
|
||||||
|
|
||||||
if (JvmtiExport::should_post_class_file_load_hook()) {
|
if (JvmtiExport::should_post_class_file_load_hook()) {
|
||||||
// Get the cached class file bytes (if any) from the class that
|
// Get the cached class file bytes (if any) from the class that
|
||||||
|
@ -2979,6 +3161,13 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
objArrayHandle methods_parameter_annotations(THREAD, methods_parameter_annotations_oop);
|
objArrayHandle methods_parameter_annotations(THREAD, methods_parameter_annotations_oop);
|
||||||
objArrayHandle methods_default_annotations(THREAD, methods_default_annotations_oop);
|
objArrayHandle methods_default_annotations(THREAD, methods_default_annotations_oop);
|
||||||
|
|
||||||
|
// Additional attributes
|
||||||
|
ClassAnnotationCollector parsed_annotations;
|
||||||
|
parse_classfile_attributes(cp, &parsed_annotations, CHECK_(nullHandle));
|
||||||
|
|
||||||
|
// Make sure this is the end of class file stream
|
||||||
|
guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle));
|
||||||
|
|
||||||
// We check super class after class file is parsed and format is checked
|
// We check super class after class file is parsed and format is checked
|
||||||
if (super_class_index > 0 && super_klass.is_null()) {
|
if (super_class_index > 0 && super_klass.is_null()) {
|
||||||
Symbol* sk = cp->klass_name_at(super_class_index);
|
Symbol* sk = cp->klass_name_at(super_class_index);
|
||||||
|
@ -3467,11 +3656,10 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
this_klass->set_has_miranda_methods(); // then set a flag
|
this_klass->set_has_miranda_methods(); // then set a flag
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional attributes
|
// Fill in field values obtained by parse_classfile_attributes
|
||||||
parse_classfile_attributes(cp, this_klass, CHECK_(nullHandle));
|
if (parsed_annotations.has_any_annotations())
|
||||||
|
parsed_annotations.apply_to(this_klass);
|
||||||
// Make sure this is the end of class file stream
|
apply_parsed_class_attributes(this_klass);
|
||||||
guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle));
|
|
||||||
|
|
||||||
// VerifyOops believes that once this has been set, the object is completely loaded.
|
// VerifyOops believes that once this has been set, the object is completely loaded.
|
||||||
// Compute transitive closure of interfaces this class implements
|
// Compute transitive closure of interfaces this class implements
|
||||||
|
@ -3486,6 +3674,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
// Do final class setup
|
// Do final class setup
|
||||||
fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts);
|
fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts);
|
||||||
|
|
||||||
|
// Fill in has_finalizer, has_vanilla_constructor, and layout_helper
|
||||||
set_precomputed_flags(this_klass);
|
set_precomputed_flags(this_klass);
|
||||||
|
|
||||||
// reinitialize modifiers, using the InnerClasses attribute
|
// reinitialize modifiers, using the InnerClasses attribute
|
||||||
|
|
|
@ -31,8 +31,8 @@
|
||||||
#include "oops/typeArrayOop.hpp"
|
#include "oops/typeArrayOop.hpp"
|
||||||
#include "runtime/handles.inline.hpp"
|
#include "runtime/handles.inline.hpp"
|
||||||
#include "utilities/accessFlags.hpp"
|
#include "utilities/accessFlags.hpp"
|
||||||
|
#include "classfile/symbolTable.hpp"
|
||||||
|
|
||||||
class TempNewSymbol;
|
|
||||||
class FieldAllocationCount;
|
class FieldAllocationCount;
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,11 +50,77 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||||
KlassHandle _host_klass;
|
KlassHandle _host_klass;
|
||||||
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
|
GrowableArray<Handle>* _cp_patches; // overrides for CP entries
|
||||||
|
|
||||||
|
// precomputed flags
|
||||||
bool _has_finalizer;
|
bool _has_finalizer;
|
||||||
bool _has_empty_finalizer;
|
bool _has_empty_finalizer;
|
||||||
bool _has_vanilla_constructor;
|
bool _has_vanilla_constructor;
|
||||||
|
int _max_bootstrap_specifier_index; // detects BSS values
|
||||||
|
|
||||||
int _max_bootstrap_specifier_index;
|
// class attributes parsed before the instance klass is created:
|
||||||
|
bool _synthetic_flag;
|
||||||
|
Symbol* _sourcefile;
|
||||||
|
Symbol* _generic_signature;
|
||||||
|
TempNewSymbol _sde_symbol;
|
||||||
|
typeArrayHandle _inner_classes;
|
||||||
|
typeArrayHandle _annotations;
|
||||||
|
|
||||||
|
void set_class_synthetic_flag(bool x) { _synthetic_flag = x; }
|
||||||
|
void set_class_sourcefile(Symbol* x) { _sourcefile = x; }
|
||||||
|
void set_class_generic_signature(Symbol* x) { _generic_signature = x; }
|
||||||
|
void set_class_sde_symbol(Symbol* x) { _sde_symbol = x; }
|
||||||
|
void set_class_inner_classes(typeArrayHandle x) { _inner_classes = x; }
|
||||||
|
void set_class_annotations(typeArrayHandle x) { _annotations = x; }
|
||||||
|
void init_parsed_class_attributes() {
|
||||||
|
_synthetic_flag = false;
|
||||||
|
_sourcefile = NULL;
|
||||||
|
_generic_signature = NULL;
|
||||||
|
// initialize the other flags too:
|
||||||
|
_has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false;
|
||||||
|
_max_bootstrap_specifier_index = -1;
|
||||||
|
}
|
||||||
|
void apply_parsed_class_attributes(instanceKlassHandle k); // update k
|
||||||
|
|
||||||
|
class AnnotationCollector {
|
||||||
|
public:
|
||||||
|
enum Location { _in_field, _in_method, _in_class };
|
||||||
|
enum ID {
|
||||||
|
_unknown = 0,
|
||||||
|
_method_ForceInline,
|
||||||
|
_annotation_LIMIT
|
||||||
|
};
|
||||||
|
const Location _location;
|
||||||
|
int _annotations_present;
|
||||||
|
AnnotationCollector(Location location)
|
||||||
|
: _location(location), _annotations_present(0)
|
||||||
|
{
|
||||||
|
assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, "");
|
||||||
|
}
|
||||||
|
// If this annotation name has an ID, report it (or _none).
|
||||||
|
ID annotation_index(Symbol* name);
|
||||||
|
// Set the annotation name:
|
||||||
|
void set_annotation(ID id) {
|
||||||
|
assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
|
||||||
|
_annotations_present |= nth_bit((int)id);
|
||||||
|
}
|
||||||
|
// Report if the annotation is present.
|
||||||
|
bool has_any_annotations() { return _annotations_present != 0; }
|
||||||
|
bool has_annotation(ID id) { return (nth_bit((int)id) & _annotations_present) != 0; }
|
||||||
|
};
|
||||||
|
class FieldAnnotationCollector: public AnnotationCollector {
|
||||||
|
public:
|
||||||
|
FieldAnnotationCollector() : AnnotationCollector(_in_field) { }
|
||||||
|
void apply_to(FieldInfo* f);
|
||||||
|
};
|
||||||
|
class MethodAnnotationCollector: public AnnotationCollector {
|
||||||
|
public:
|
||||||
|
MethodAnnotationCollector() : AnnotationCollector(_in_method) { }
|
||||||
|
void apply_to(methodHandle m);
|
||||||
|
};
|
||||||
|
class ClassAnnotationCollector: public AnnotationCollector {
|
||||||
|
public:
|
||||||
|
ClassAnnotationCollector() : AnnotationCollector(_in_class) { }
|
||||||
|
void apply_to(instanceKlassHandle k);
|
||||||
|
};
|
||||||
|
|
||||||
enum { fixed_buffer_size = 128 };
|
enum { fixed_buffer_size = 128 };
|
||||||
u_char linenumbertable_buffer[fixed_buffer_size];
|
u_char linenumbertable_buffer[fixed_buffer_size];
|
||||||
|
@ -87,7 +153,9 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||||
u2* constantvalue_index_addr,
|
u2* constantvalue_index_addr,
|
||||||
bool* is_synthetic_addr,
|
bool* is_synthetic_addr,
|
||||||
u2* generic_signature_index_addr,
|
u2* generic_signature_index_addr,
|
||||||
typeArrayHandle* field_annotations, TRAPS);
|
typeArrayHandle* field_annotations,
|
||||||
|
FieldAnnotationCollector* parsed_annotations,
|
||||||
|
TRAPS);
|
||||||
typeArrayHandle parse_fields(Symbol* class_name,
|
typeArrayHandle parse_fields(Symbol* class_name,
|
||||||
constantPoolHandle cp, bool is_interface,
|
constantPoolHandle cp, bool is_interface,
|
||||||
FieldAllocationCount *fac,
|
FieldAllocationCount *fac,
|
||||||
|
@ -128,25 +196,32 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||||
typeArrayOop parse_stackmap_table(u4 code_attribute_length, TRAPS);
|
typeArrayOop parse_stackmap_table(u4 code_attribute_length, TRAPS);
|
||||||
|
|
||||||
// Classfile attribute parsing
|
// Classfile attribute parsing
|
||||||
void parse_classfile_sourcefile_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
|
void parse_classfile_sourcefile_attribute(constantPoolHandle cp, TRAPS);
|
||||||
void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp,
|
void parse_classfile_source_debug_extension_attribute(constantPoolHandle cp, int length, TRAPS);
|
||||||
instanceKlassHandle k, int length, TRAPS);
|
|
||||||
u2 parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
|
u2 parse_classfile_inner_classes_attribute(u1* inner_classes_attribute_start,
|
||||||
bool parsed_enclosingmethod_attribute,
|
bool parsed_enclosingmethod_attribute,
|
||||||
u2 enclosing_method_class_index,
|
u2 enclosing_method_class_index,
|
||||||
u2 enclosing_method_method_index,
|
u2 enclosing_method_method_index,
|
||||||
constantPoolHandle cp,
|
constantPoolHandle cp,
|
||||||
instanceKlassHandle k, TRAPS);
|
TRAPS);
|
||||||
void parse_classfile_attributes(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
|
void parse_classfile_attributes(constantPoolHandle cp,
|
||||||
void parse_classfile_synthetic_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
|
ClassAnnotationCollector* parsed_annotations,
|
||||||
void parse_classfile_signature_attribute(constantPoolHandle cp, instanceKlassHandle k, TRAPS);
|
TRAPS);
|
||||||
void parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, instanceKlassHandle k, u4 attribute_length, TRAPS);
|
void parse_classfile_synthetic_attribute(constantPoolHandle cp, TRAPS);
|
||||||
|
void parse_classfile_signature_attribute(constantPoolHandle cp, TRAPS);
|
||||||
|
void parse_classfile_bootstrap_methods_attribute(constantPoolHandle cp, u4 attribute_length, TRAPS);
|
||||||
|
|
||||||
// Annotations handling
|
// Annotations handling
|
||||||
typeArrayHandle assemble_annotations(u1* runtime_visible_annotations,
|
typeArrayHandle assemble_annotations(u1* runtime_visible_annotations,
|
||||||
int runtime_visible_annotations_length,
|
int runtime_visible_annotations_length,
|
||||||
u1* runtime_invisible_annotations,
|
u1* runtime_invisible_annotations,
|
||||||
int runtime_invisible_annotations_length, TRAPS);
|
int runtime_invisible_annotations_length, TRAPS);
|
||||||
|
int skip_annotation(u1* buffer, int limit, int index);
|
||||||
|
int skip_annotation_value(u1* buffer, int limit, int index);
|
||||||
|
void parse_annotations(u1* buffer, int limit, constantPoolHandle cp,
|
||||||
|
/* Results (currently, only one result is supported): */
|
||||||
|
AnnotationCollector* result,
|
||||||
|
TRAPS);
|
||||||
|
|
||||||
// Final setup
|
// Final setup
|
||||||
unsigned int compute_oop_map_count(instanceKlassHandle super,
|
unsigned int compute_oop_map_count(instanceKlassHandle super,
|
||||||
|
|
|
@ -257,6 +257,7 @@
|
||||||
template(java_lang_invoke_BoundMethodHandle, "java/lang/invoke/BoundMethodHandle") \
|
template(java_lang_invoke_BoundMethodHandle, "java/lang/invoke/BoundMethodHandle") \
|
||||||
template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \
|
template(java_lang_invoke_DirectMethodHandle, "java/lang/invoke/DirectMethodHandle") \
|
||||||
template(java_lang_invoke_CountingMethodHandle, "java/lang/invoke/CountingMethodHandle") \
|
template(java_lang_invoke_CountingMethodHandle, "java/lang/invoke/CountingMethodHandle") \
|
||||||
|
template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \
|
||||||
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
|
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
|
||||||
template(findMethodHandleType_name, "findMethodHandleType") \
|
template(findMethodHandleType_name, "findMethodHandleType") \
|
||||||
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
|
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
|
||||||
|
|
|
@ -123,7 +123,8 @@ class methodOopDesc : public oopDesc {
|
||||||
u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words
|
u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words
|
||||||
u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none)
|
u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none)
|
||||||
u1 _jfr_towrite : 1, // Flags
|
u1 _jfr_towrite : 1, // Flags
|
||||||
: 7;
|
_force_inline : 1,
|
||||||
|
: 6;
|
||||||
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
|
u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting
|
||||||
u2 _number_of_breakpoints; // fullspeed debugging support
|
u2 _number_of_breakpoints; // fullspeed debugging support
|
||||||
InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations
|
InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations
|
||||||
|
@ -655,6 +656,9 @@ class methodOopDesc : public oopDesc {
|
||||||
bool jfr_towrite() { return _jfr_towrite; }
|
bool jfr_towrite() { return _jfr_towrite; }
|
||||||
void set_jfr_towrite(bool towrite) { _jfr_towrite = towrite; }
|
void set_jfr_towrite(bool towrite) { _jfr_towrite = towrite; }
|
||||||
|
|
||||||
|
bool force_inline() { return _force_inline; }
|
||||||
|
void set_force_inline(bool fi) { _force_inline = fi; }
|
||||||
|
|
||||||
// On-stack replacement support
|
// On-stack replacement support
|
||||||
bool has_osr_nmethod(int level, bool match_level) {
|
bool has_osr_nmethod(int level, bool match_level) {
|
||||||
return instanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL;
|
return instanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue