8306851: Move Method access flags

Reviewed-by: cjplummer, dholmes, dnsimon, matsaave, fparain
This commit is contained in:
Coleen Phillimore 2023-05-01 11:33:22 +00:00
parent a6b4f25bd5
commit 316d303c1d
27 changed files with 483 additions and 464 deletions

View File

@ -84,8 +84,8 @@ ciMethod::ciMethod(const methodHandle& h_m, ciInstanceKlass* holder) :
_code_size = h_m->code_size();
_handler_count = h_m->exception_table_length();
_size_of_parameters = h_m->size_of_parameters();
_uses_monitors = h_m->access_flags().has_monitor_bytecodes();
_balanced_monitors = !_uses_monitors || h_m->access_flags().is_monitor_matching();
_uses_monitors = h_m->has_monitor_bytecodes();
_balanced_monitors = !_uses_monitors || h_m->guaranteed_monitor_matching();
_is_c1_compilable = !h_m->is_not_c1_compilable();
_is_c2_compilable = !h_m->is_not_c2_compilable();
_can_be_parsed = true;

View File

@ -1978,27 +1978,27 @@ ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() {
void MethodAnnotationCollector::apply_to(const methodHandle& m) {
if (has_annotation(_method_CallerSensitive))
m->set_caller_sensitive(true);
m->set_caller_sensitive();
if (has_annotation(_method_ForceInline))
m->set_force_inline(true);
m->set_force_inline();
if (has_annotation(_method_DontInline))
m->set_dont_inline(true);
m->set_dont_inline();
if (has_annotation(_method_ChangesCurrentThread))
m->set_changes_current_thread(true);
m->set_changes_current_thread();
if (has_annotation(_method_JvmtiMountTransition))
m->set_jvmti_mount_transition(true);
m->set_jvmti_mount_transition();
if (has_annotation(_method_InjectedProfile))
m->set_has_injected_profile(true);
m->set_has_injected_profile();
if (has_annotation(_method_LambdaForm_Compiled) && m->intrinsic_id() == vmIntrinsics::_none)
m->set_intrinsic_id(vmIntrinsics::_compiledLambdaForm);
if (has_annotation(_method_Hidden))
m->set_hidden(true);
m->set_is_hidden();
if (has_annotation(_method_Scoped))
m->set_scoped(true);
m->set_scoped();
if (has_annotation(_method_IntrinsicCandidate) && !m->is_synthetic())
m->set_intrinsic_candidate(true);
m->set_intrinsic_candidate();
if (has_annotation(_jdk_internal_vm_annotation_ReservedStackAccess))
m->set_has_reserved_stack_access(true);
m->set_has_reserved_stack_access();
}
void ClassFileParser::ClassAnnotationCollector::apply_to(InstanceKlass* ik) {
@ -2739,7 +2739,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs,
parsed_annotations.apply_to(methodHandle(THREAD, m));
if (is_hidden()) { // Mark methods in hidden classes as 'hidden'.
m->set_hidden(true);
m->set_is_hidden();
}
// Copy annotations

View File

@ -476,7 +476,7 @@ ExceptionMessageBuilder::ExceptionMessageBuilder(Method* method, int bci) :
_stacks->at_put(0, new SimulatedOperandStack());
// And initialize the start of all exception handlers.
if (const_method->has_exception_handler()) {
if (const_method->has_exception_table()) {
ExceptionTableElement *et = const_method->exception_table_start();
for (int i = 0; i < const_method->exception_table_length(); ++i) {
u2 index = et[i].handler_pc;

View File

@ -473,7 +473,7 @@ void Rewriter::scan_method(Thread* thread, Method* method, bool reverse, bool* i
}
}
// Update access flags
// Update flags
if (has_monitor_bytecodes) {
method->set_has_monitor_bytecodes();
}
@ -482,8 +482,6 @@ void Rewriter::scan_method(Thread* thread, Method* method, bool reverse, bool* i
// have to be rewritten, so we run the oopMapGenerator on the method
if (nof_jsrs > 0) {
method->set_has_jsrs();
// Second pass will revisit this method.
assert(method->has_jsrs(), "didn't we just set this?");
}
}

View File

@ -926,8 +926,8 @@ C2V_END
C2V_VMENTRY(void, setNotInlinableOrCompilable,(JNIEnv* env, jobject, ARGUMENT_PAIR(method)))
methodHandle method(THREAD, UNPACK_PAIR(Method, method));
method->set_not_c1_compilable();
method->set_not_c2_compilable();
method->set_is_not_c1_compilable();
method->set_is_not_c2_compilable();
method->set_dont_inline(true);
C2V_END

View File

@ -129,7 +129,7 @@
nonstatic_field(ConstantPool, _source_file_name_index, u2) \
\
nonstatic_field(ConstMethod, _constants, ConstantPool*) \
nonstatic_field(ConstMethod, _flags, u2) \
nonstatic_field(ConstMethod, _flags._flags, u4) \
nonstatic_field(ConstMethod, _code_size, u2) \
nonstatic_field(ConstMethod, _name_index, u2) \
nonstatic_field(ConstMethod, _signature_index, u2) \
@ -228,7 +228,7 @@
nonstatic_field(Method, _access_flags, AccessFlags) \
nonstatic_field(Method, _vtable_index, int) \
nonstatic_field(Method, _intrinsic_id, u2) \
nonstatic_field(Method, _flags, u2) \
nonstatic_field(Method, _flags._status, u4) \
volatile_nonstatic_field(Method, _code, CompiledMethod*) \
volatile_nonstatic_field(Method, _from_compiled_entry, address) \
\
@ -416,8 +416,6 @@
declare_constant(JVMCINMethodData::SPECULATION_LENGTH_BITS) \
\
declare_constant(JVM_ACC_WRITTEN_FLAGS) \
declare_constant(JVM_ACC_MONITOR_MATCH) \
declare_constant(JVM_ACC_HAS_MONITOR_BYTECODES) \
declare_constant(JVM_ACC_HAS_FINALIZER) \
declare_constant(JVM_ACC_IS_CLONEABLE_FAST) \
declare_constant(JVM_ACC_IS_HIDDEN_CLASS) \
@ -582,11 +580,16 @@
declare_constant(ConstantPool::CPCACHE_INDEX_TAG) \
declare_constant(ConstantPool::_has_dynamic_constant) \
\
declare_constant(ConstMethod::_has_linenumber_table) \
declare_constant(ConstMethod::_has_localvariable_table) \
declare_constant(ConstMethod::_has_exception_table) \
declare_constant(ConstMethod::_has_method_annotations) \
declare_constant(ConstMethod::_has_parameter_annotations) \
declare_constant(ConstMethodFlags::_misc_has_linenumber_table) \
declare_constant(ConstMethodFlags::_misc_has_localvariable_table) \
declare_constant(ConstMethodFlags::_misc_has_exception_table) \
declare_constant(ConstMethodFlags::_misc_has_method_annotations) \
declare_constant(ConstMethodFlags::_misc_has_parameter_annotations) \
declare_constant(ConstMethodFlags::_misc_caller_sensitive) \
declare_constant(ConstMethodFlags::_misc_is_hidden) \
declare_constant(ConstMethodFlags::_misc_intrinsic_candidate) \
declare_constant(ConstMethodFlags::_misc_reserved_stack_access) \
declare_constant(ConstMethodFlags::_misc_changes_current_thread) \
\
declare_constant(CounterData::count_off) \
\
@ -683,13 +686,8 @@
\
declare_constant(markWord::no_hash) \
\
declare_constant(Method::_caller_sensitive) \
declare_constant(Method::_force_inline) \
declare_constant(Method::_dont_inline) \
declare_constant(Method::_hidden) \
declare_constant(Method::_intrinsic_candidate) \
declare_constant(Method::_reserved_stack_access) \
declare_constant(Method::_changes_current_thread) \
declare_constant(MethodFlags::_misc_force_inline) \
declare_constant(MethodFlags::_misc_dont_inline) \
\
declare_constant(Method::nonvirtual_vtable_index) \
declare_constant(Method::invalid_vtable_index) \

View File

@ -199,7 +199,7 @@ u2* ConstMethod::checked_exceptions_length_addr() const {
}
u2* ConstMethod::exception_table_length_addr() const {
assert(has_exception_handler(), "called only if table is present");
assert(has_exception_table(), "called only if table is present");
if (has_checked_exceptions()) {
// If checked_exception present, locate immediately before them.
return (u2*) checked_exceptions_start() - 1;
@ -217,7 +217,7 @@ u2* ConstMethod::exception_table_length_addr() const {
u2* ConstMethod::localvariable_table_length_addr() const {
assert(has_localvariable_table(), "called only if table is present");
if (has_exception_handler()) {
if (has_exception_table()) {
// If exception_table present, locate immediately before them.
return (u2*) exception_table_start() - 1;
} else {
@ -239,30 +239,29 @@ u2* ConstMethod::localvariable_table_length_addr() const {
// Update the flags to indicate the presence of these optional fields.
void ConstMethod::set_inlined_tables_length(InlineTableSizes* sizes) {
_flags = 0;
if (sizes->compressed_linenumber_size() > 0)
_flags |= _has_linenumber_table;
set_has_linenumber_table();
if (sizes->generic_signature_index() != 0)
_flags |= _has_generic_signature;
set_has_generic_signature();
if (sizes->method_parameters_length() >= 0)
_flags |= _has_method_parameters;
set_has_method_parameters();
if (sizes->checked_exceptions_length() > 0)
_flags |= _has_checked_exceptions;
set_has_checked_exceptions();
if (sizes->exception_table_length() > 0)
_flags |= _has_exception_table;
set_has_exception_table();
if (sizes->localvariable_table_length() > 0)
_flags |= _has_localvariable_table;
set_has_localvariable_table();
// annotations, they are all pointer sized embedded objects so don't have
// a length embedded also.
if (sizes->method_annotations_length() > 0)
_flags |= _has_method_annotations;
set_has_method_annotations();
if (sizes->parameter_annotations_length() > 0)
_flags |= _has_parameter_annotations;
set_has_parameter_annotations();
if (sizes->type_annotations_length() > 0)
_flags |= _has_type_annotations;
set_has_type_annotations();
if (sizes->default_annotations_length() > 0)
_flags |= _has_default_annotations;
set_has_default_annotations();
// This code is extremely brittle and should possibly be revised.
// The *_length_addr functions walk backwards through the
@ -329,7 +328,7 @@ LocalVariableTableElement* ConstMethod::localvariable_table_start() const {
}
int ConstMethod::exception_table_length() const {
return has_exception_handler() ? *(exception_table_length_addr()) : 0;
return has_exception_table() ? *(exception_table_length_addr()) : 0;
}
ExceptionTableElement* ConstMethod::exception_table_start() const {
@ -431,13 +430,14 @@ void ConstMethod::print_on(outputStream* st) const {
ResourceMark rm;
st->print_cr("%s", internal_name());
Method* m = method();
st->print(" - method: " PTR_FORMAT " ", p2i(m));
st->print(" - method: " PTR_FORMAT " ", p2i(m));
if (m != nullptr) {
m->print_value_on(st);
}
st->cr();
st->print(" - flags: 0x%x ", _flags.as_int()); _flags.print_on(st); st->cr();
if (has_stackmap_table()) {
st->print(" - stackmap data: ");
st->print(" - stackmap data: ");
stackmap_data()->print_value_on(st);
st->cr();
}
@ -484,7 +484,7 @@ void ConstMethod::verify_on(outputStream* st) {
u2* addr = checked_exceptions_length_addr();
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
}
if (has_exception_handler()) {
if (has_exception_table()) {
u2* addr = exception_table_length_addr();
guarantee(*addr > 0 && (address) addr >= compressed_table_end && (address) addr < m_end, "invalid method layout");
}
@ -496,7 +496,7 @@ void ConstMethod::verify_on(outputStream* st) {
u2* uncompressed_table_start;
if (has_localvariable_table()) {
uncompressed_table_start = (u2*) localvariable_table_start();
} else if (has_exception_handler()) {
} else if (has_exception_table()) {
uncompressed_table_start = (u2*) exception_table_start();
} else if (has_checked_exceptions()) {
uncompressed_table_start = (u2*) checked_exceptions_start();

View File

@ -25,6 +25,7 @@
#ifndef SHARE_OOPS_CONSTMETHOD_HPP
#define SHARE_OOPS_CONSTMETHOD_HPP
#include "oops/constMethodFlags.hpp"
#include "oops/oop.hpp"
#include "utilities/align.hpp"
@ -173,19 +174,6 @@ public:
typedef enum { NORMAL, OVERPASS } MethodType;
private:
enum {
_has_linenumber_table = 0x0001,
_has_checked_exceptions = 0x0002,
_has_localvariable_table = 0x0004,
_has_exception_table = 0x0008,
_has_generic_signature = 0x0010,
_has_method_parameters = 0x0020,
_is_overpass = 0x0040,
_has_method_annotations = 0x0080,
_has_parameter_annotations = 0x0100,
_has_type_annotations = 0x0200,
_has_default_annotations = 0x0400
};
// Bit vector of signature
// Callers interpret 0=not initialized yet and
@ -204,7 +192,7 @@ private:
Array<u1>* _stackmap_data;
int _constMethod_size;
u2 _flags;
ConstMethodFlags _flags; // for sizing
u1 _result_type; // BasicType of result
// Size of Java bytecodes allocated immediately after Method*.
@ -236,33 +224,20 @@ public:
// Inlined tables
void set_inlined_tables_length(InlineTableSizes* sizes);
bool has_generic_signature() const
{ return (_flags & _has_generic_signature) != 0; }
bool has_linenumber_table() const
{ return (_flags & _has_linenumber_table) != 0; }
bool has_checked_exceptions() const
{ return (_flags & _has_checked_exceptions) != 0; }
bool has_localvariable_table() const
{ return (_flags & _has_localvariable_table) != 0; }
bool has_exception_handler() const
{ return (_flags & _has_exception_table) != 0; }
bool has_method_parameters() const
{ return (_flags & _has_method_parameters) != 0; }
// Create getters and setters for the flag values.
#define CM_FLAGS_GET_SET(name, ignore) \
bool name() const { return _flags.name(); } \
void set_##name() { _flags.set_##name(); }
CM_FLAGS_DO(CM_FLAGS_GET_SET)
#undef CM_FLAGS_GET_SET
MethodType method_type() const {
return ((_flags & _is_overpass) == 0) ? NORMAL : OVERPASS;
return (_flags.is_overpass()) ? OVERPASS : NORMAL;
}
void set_method_type(MethodType mt) {
if (mt == NORMAL) {
_flags &= ~(_is_overpass);
} else {
_flags |= _is_overpass;
if (mt != NORMAL) {
set_is_overpass();
}
}
@ -382,20 +357,6 @@ public:
int method_parameters_length() const;
MethodParametersElement* method_parameters_start() const;
// method annotations
bool has_method_annotations() const
{ return (_flags & _has_method_annotations) != 0; }
bool has_parameter_annotations() const
{ return (_flags & _has_parameter_annotations) != 0; }
bool has_type_annotations() const
{ return (_flags & _has_type_annotations) != 0; }
bool has_default_annotations() const
{ return (_flags & _has_default_annotations) != 0; }
AnnotationArray** method_annotations_addr() const;
AnnotationArray* method_annotations() const {
return has_method_annotations() ? *(method_annotations_addr()) : nullptr;

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "oops/constMethodFlags.hpp"
#include "runtime/atomic.hpp"
#include "utilities/ostream.hpp"
void ConstMethodFlags::print_on(outputStream* st) const {
#define CM_PRINT(name, ignore) \
if (name()) st->print(" " #name " ");
CM_FLAGS_DO(CM_PRINT)
#undef CM_PRINT
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_OOPS_CONSTMETHODFLAGS_HPP
#define SHARE_OOPS_CONSTMETHODFLAGS_HPP
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
class outputStream;
// The ConstMethodFlags class contains the parse-time flags associated with
// a Method, and its associated accessors.
// These flags are JVM internal and not part of the AccessFlags classfile specification.
class ConstMethodFlags {
friend class VMStructs;
friend class JVMCIVMStructs;
#define CM_FLAGS_DO(flag) \
flag(has_linenumber_table , 1 << 0) \
flag(has_checked_exceptions , 1 << 1) \
flag(has_localvariable_table , 1 << 2) \
flag(has_exception_table , 1 << 3) \
flag(has_generic_signature , 1 << 4) \
flag(has_method_parameters , 1 << 5) \
flag(is_overpass , 1 << 6) \
flag(has_method_annotations , 1 << 7) \
flag(has_parameter_annotations , 1 << 8) \
flag(has_type_annotations , 1 << 9) \
flag(has_default_annotations , 1 << 10) \
flag(caller_sensitive , 1 << 11) \
flag(is_hidden , 1 << 12) \
flag(has_injected_profile , 1 << 13) \
flag(intrinsic_candidate , 1 << 14) \
flag(reserved_stack_access , 1 << 15) \
flag(is_scoped , 1 << 16) \
flag(changes_current_thread , 1 << 17) \
flag(jvmti_mount_transition , 1 << 18) \
/* end of list */
#define CM_FLAGS_ENUM_NAME(name, value) _misc_##name = value,
enum {
CM_FLAGS_DO(CM_FLAGS_ENUM_NAME)
};
#undef CM_FLAGS_ENUM_NAME
// These flags are write-once before the class is published and then read-only so don't require atomic updates.
u4 _flags;
public:
ConstMethodFlags() : _flags(0) {}
// Create getters and setters for the flag values.
#define CM_FLAGS_GET_SET(name, ignore) \
bool name() const { return (_flags & _misc_##name) != 0; } \
void set_##name() { \
_flags |= _misc_##name; \
}
CM_FLAGS_DO(CM_FLAGS_GET_SET)
#undef CM_FLAGS_GET_SET
int as_int() const { return _flags; }
void print_on(outputStream* st) const;
};
#endif // SHARE_OOPS_CONSTMETHODFLAGS_HPP

View File

@ -3477,6 +3477,7 @@ void InstanceKlass::print_on(outputStream* st) const {
st->print(BULLET"instance size: %d", size_helper()); st->cr();
st->print(BULLET"klass size: %d", size()); st->cr();
st->print(BULLET"access: "); access_flags().print_on(st); st->cr();
st->print(BULLET"flags: "); _misc_flags.print_on(st); st->cr();
st->print(BULLET"state: "); st->print_cr("%s", init_state_name());
st->print(BULLET"name: "); name()->print_value_on(st); st->cr();
st->print(BULLET"super: "); Metadata::print_value_on_maybe_null(st, super()); st->cr();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -29,6 +29,7 @@
#include "runtime/atomic.hpp"
#include "runtime/safepoint.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
// This can be removed for the atomic bitset functions, when available.
void InstanceKlassFlags::atomic_set_bits(u1 bits) {
@ -51,6 +52,15 @@ void InstanceKlassFlags::atomic_clear_bits(u1 bits) {
} while(f != old_status);
}
void InstanceKlassFlags::print_on(outputStream* st) const {
#define IK_FLAGS_PRINT(name, ignore) \
if (name()) st->print(" ##name ");
IK_FLAGS_DO(IK_FLAGS_PRINT)
IK_STATUS_DO(IK_FLAGS_PRINT)
#undef IK_FLAGS_PRINT
st->cr();
}
#if INCLUDE_CDS
void InstanceKlassFlags::set_shared_class_loader_type(s2 loader_type) {
switch (loader_type) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -66,7 +66,8 @@ class InstanceKlassFlags {
status(has_resolved_methods , 1 << 1) /* True if the klass has resolved MethodHandle methods */ \
status(has_been_redefined , 1 << 2) /* class has been redefined */ \
status(is_scratch_class , 1 << 3) /* class is the redefined scratch class */ \
status(is_marked_dependent , 1 << 4) /* class is the redefined scratch class */
status(is_marked_dependent , 1 << 4) /* class is the redefined scratch class */ \
/* end of list */
#define IK_STATUS_ENUM_NAME(name, value) _misc_##name = value,
enum {
@ -89,18 +90,14 @@ class InstanceKlassFlags {
InstanceKlassFlags() : _flags(0), _status(0) {}
// Create getters and setters for the flag values.
#define IK_FLAGS_GET(name, ignore) \
bool name() const { return (_flags & _misc_##name) != 0; }
IK_FLAGS_DO(IK_FLAGS_GET)
#undef IK_FLAGS_GET
#define IK_FLAGS_SET(name, ignore) \
#define IK_FLAGS_GET_SET(name, ignore) \
bool name() const { return (_flags & _misc_##name) != 0; } \
void set_##name(bool b) { \
assert_is_safe(name()); \
if (b) _flags |= _misc_##name; \
}
IK_FLAGS_DO(IK_FLAGS_SET)
#undef IK_FLAGS_SET
IK_FLAGS_DO(IK_FLAGS_GET_SET)
#undef IK_FLAGS_GET_SET
bool is_shared_unregistered_class() const {
return (_flags & shared_loader_type_bits()) == 0;
@ -112,12 +109,8 @@ class InstanceKlassFlags {
void assert_is_safe(bool set) NOT_DEBUG_RETURN;
// Create getters and setters for the status values.
#define IK_STATUS_GET(name, ignore) \
bool name() const { return (_status & _misc_##name) != 0; }
IK_STATUS_DO(IK_STATUS_GET)
#undef IK_STATUS_GET
#define IK_STATUS_SET(name, ignore) \
#define IK_STATUS_GET_SET(name, ignore) \
bool name() const { return (_status & _misc_##name) != 0; } \
void set_##name(bool b) { \
if (b) { \
atomic_set_bits(_misc_##name); \
@ -125,11 +118,12 @@ class InstanceKlassFlags {
atomic_clear_bits(_misc_##name); \
} \
}
IK_STATUS_DO(IK_STATUS_SET)
#undef IK_STATUS_SET
IK_STATUS_DO(IK_STATUS_GET_SET)
#undef IK_STATUS_GET_SET
void atomic_set_bits(u1 bits);
void atomic_clear_bits(u1 bits);
void print_on(outputStream* st) const;
};
#endif // SHARE_OOPS_INSTANCEKLASSFLAGS_HPP

View File

@ -102,11 +102,6 @@ Method::Method(ConstMethod* xconst, AccessFlags access_flags, Symbol* name) {
set_constMethod(xconst);
set_access_flags(access_flags);
set_intrinsic_id(vmIntrinsics::_none);
set_force_inline(false);
set_hidden(false);
set_dont_inline(false);
set_changes_current_thread(false);
set_has_injected_profile(false);
set_method_data(nullptr);
clear_method_counters();
set_vtable_index(Method::garbage_vtable_index);
@ -736,24 +731,27 @@ bool Method::compute_has_loops_flag() {
case Bytecodes::_if_acmpne:
case Bytecodes::_goto:
case Bytecodes::_jsr:
if (bcs.dest() < bcs.next_bci()) _access_flags.set_has_loops();
if (bcs.dest() < bcs.next_bci()) {
return set_has_loops();
}
break;
case Bytecodes::_goto_w:
case Bytecodes::_jsr_w:
if (bcs.dest_w() < bcs.next_bci()) _access_flags.set_has_loops();
if (bcs.dest_w() < bcs.next_bci()) {
return set_has_loops();
}
break;
case Bytecodes::_lookupswitch: {
Bytecode_lookupswitch lookupswitch(this, bcs.bcp());
if (lookupswitch.default_offset() < 0) {
_access_flags.set_has_loops();
return set_has_loops();
} else {
for (int i = 0; i < lookupswitch.number_of_pairs(); ++i) {
LookupswitchPair pair = lookupswitch.pair_at(i);
if (pair.offset() < 0) {
_access_flags.set_has_loops();
break;
return set_has_loops();
}
}
}
@ -762,11 +760,11 @@ bool Method::compute_has_loops_flag() {
case Bytecodes::_tableswitch: {
Bytecode_tableswitch tableswitch(this, bcs.bcp());
if (tableswitch.default_offset() < 0) {
_access_flags.set_has_loops();
return set_has_loops();
} else {
for (int i = 0; i < tableswitch.length(); ++i) {
if (tableswitch.dest_offset_at(i) < 0) {
_access_flags.set_has_loops();
return set_has_loops();
}
}
}
@ -776,8 +774,9 @@ bool Method::compute_has_loops_flag() {
break;
}
}
_access_flags.set_loops_flag_init();
return _access_flags.has_loops();
_flags.set_has_loops_flag_init(true);
return false;
}
bool Method::is_final_method(AccessFlags class_access_flags) const {
@ -1108,13 +1107,13 @@ void Method::set_not_compilable(const char* reason, int comp_level, bool report)
}
print_made_not_compilable(comp_level, /*is_osr*/ false, report, reason);
if (comp_level == CompLevel_all) {
set_not_c1_compilable();
set_not_c2_compilable();
set_is_not_c1_compilable();
set_is_not_c2_compilable();
} else {
if (is_c1_compile(comp_level))
set_not_c1_compilable();
set_is_not_c1_compilable();
if (is_c2_compile(comp_level))
set_not_c2_compilable();
set_is_not_c2_compilable();
}
assert(!CompilationPolicy::can_be_compiled(methodHandle(Thread::current(), this), comp_level), "sanity check");
}
@ -1134,13 +1133,13 @@ bool Method::is_not_osr_compilable(int comp_level) const {
void Method::set_not_osr_compilable(const char* reason, int comp_level, bool report) {
print_made_not_compilable(comp_level, /*is_osr*/ true, report, reason);
if (comp_level == CompLevel_all) {
set_not_c1_osr_compilable();
set_not_c2_osr_compilable();
set_is_not_c1_osr_compilable();
set_is_not_c2_osr_compilable();
} else {
if (is_c1_compile(comp_level))
set_not_c1_osr_compilable();
set_is_not_c1_osr_compilable();
if (is_c2_compile(comp_level))
set_not_c2_osr_compilable();
set_is_not_c2_osr_compilable();
}
assert(!CompilationPolicy::can_be_osr_compiled(methodHandle(Thread::current(), this), comp_level), "sanity check");
}
@ -1663,7 +1662,7 @@ void Method::init_intrinsic_id(vmSymbolID klass_id) {
set_intrinsic_id(id);
if (id == vmIntrinsics::_Class_cast) {
// Even if the intrinsic is rejected, we want to inline this simple method.
set_force_inline(true);
set_force_inline();
}
return;
}
@ -2241,8 +2240,8 @@ void Method::set_on_stack(const bool value) {
// on stack means some method referring to it is also on the stack.
constants()->set_on_stack(value);
bool already_set = on_stack();
_access_flags.set_on_stack(value);
bool already_set = on_stack_flag();
set_on_stack_flag(value);
if (value && !already_set) {
MetadataOnStackMark::record(this);
}
@ -2304,6 +2303,7 @@ void Method::print_on(outputStream* st) const {
st->print (" - constants: " PTR_FORMAT " ", p2i(constants()));
constants()->print_value_on(st); st->cr();
st->print (" - access: 0x%x ", access_flags().as_int()); access_flags().print_on(st); st->cr();
st->print (" - flags: 0x%x ", _flags.as_int()); _flags.print_on(st); st->cr();
st->print (" - name: "); name()->print_value_on(st); st->cr();
st->print (" - signature: "); signature()->print_value_on(st); st->cr();
st->print_cr(" - max stack: %d", max_stack());

View File

@ -31,6 +31,7 @@
#include "oops/annotations.hpp"
#include "oops/constantPool.hpp"
#include "oops/methodCounters.hpp"
#include "oops/methodFlags.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.hpp"
#include "oops/typeArrayOop.hpp"
@ -79,23 +80,9 @@ class Method : public Metadata {
AdapterHandlerEntry* _adapter;
AccessFlags _access_flags; // Access flags
int _vtable_index; // vtable index of this method (see VtableIndexFlag)
// note: can have vtables with >2**16 elements (because of inheritance)
u2 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none)
MethodFlags _flags;
// Flags
enum Flags {
_caller_sensitive = 1 << 0,
_force_inline = 1 << 1,
_dont_inline = 1 << 2,
_hidden = 1 << 3,
_has_injected_profile = 1 << 4,
_intrinsic_candidate = 1 << 5,
_reserved_stack_access = 1 << 6,
_scoped = 1 << 7,
_changes_current_thread = 1 << 8,
_jvmti_mount_transition = 1 << 9,
};
mutable u2 _flags;
u2 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none)
JFR_ONLY(DEFINE_TRACE_FLAG;)
@ -332,7 +319,7 @@ class Method : public Metadata {
// exception handler table
bool has_exception_handler() const
{ return constMethod()->has_exception_handler(); }
{ return constMethod()->has_exception_table(); }
int exception_table_length() const
{ return constMethod()->exception_table_length(); }
ExceptionTableElement* exception_table_start() const
@ -602,31 +589,35 @@ public:
// true if method can omit stack trace in throw in compiled code.
bool can_omit_stack_trace();
// Flags getting and setting.
#define M_STATUS_GET_SET(name, ignore) \
bool name() const { return _flags.name(); } \
void set_##name(bool x) { _flags.set_##name(x); } \
void set_##name() { _flags.set_##name(true); }
M_STATUS_DO(M_STATUS_GET_SET)
#undef M_STATUS_GET_SET
// returns true if the method has any backward branches.
bool has_loops() {
return access_flags().loops_flag_init() ? access_flags().has_loops() : compute_has_loops_flag();
return has_loops_flag_init() ? has_loops_flag() : compute_has_loops_flag();
};
bool compute_has_loops_flag();
bool has_jsrs() {
return access_flags().has_jsrs();
};
void set_has_jsrs() {
_access_flags.set_has_jsrs();
bool set_has_loops() {
// set both the flags and that it's been initialized.
set_has_loops_flag();
set_has_loops_flag_init();
return true;
}
// returns true if the method has any monitors.
bool has_monitors() const { return is_synchronized() || access_flags().has_monitor_bytecodes(); }
bool has_monitor_bytecodes() const { return access_flags().has_monitor_bytecodes(); }
void set_has_monitor_bytecodes() { _access_flags.set_has_monitor_bytecodes(); }
bool has_monitors() const { return is_synchronized() || has_monitor_bytecodes(); }
// monitor matching. This returns a conservative estimate of whether the monitorenter/monitorexit bytecodes
// propererly nest in the method. It might return false, even though they actually nest properly, since the info.
// properly nest in the method. It might return false, even though they actually nest properly, since the info.
// has not been computed yet.
bool guaranteed_monitor_matching() const { return access_flags().is_monitor_matching(); }
void set_guaranteed_monitor_matching() { _access_flags.set_monitor_matching(); }
bool guaranteed_monitor_matching() const { return monitor_matching(); }
void set_guaranteed_monitor_matching() { set_monitor_matching(); }
// returns true if the method is an accessor function (setter/getter).
bool is_accessor() const;
@ -745,14 +736,7 @@ public:
static int extra_stack_words(); // = extra_stack_entries() * Interpreter::stackElementSize
// RedefineClasses() support:
bool is_old() const { return access_flags().is_old(); }
void set_is_old() { _access_flags.set_is_old(); }
bool is_obsolete() const { return access_flags().is_obsolete(); }
void set_is_obsolete() { _access_flags.set_is_obsolete(); }
bool is_deleted() const { return access_flags().is_deleted(); }
void set_is_deleted() { _access_flags.set_is_deleted(); }
bool on_stack() const { return access_flags().on_stack(); }
bool on_stack() const { return on_stack_flag(); }
void set_on_stack(const bool value);
void record_gc_epoch();
@ -760,10 +744,6 @@ public:
// see the definition in Method*.cpp for the gory details
bool should_not_be_cached() const;
// JVMTI Native method prefixing support:
bool is_prefixed_native() const { return access_flags().is_prefixed_native(); }
void set_is_prefixed_native() { _access_flags.set_is_prefixed_native(); }
// Rewriting support
static methodHandle clone_with_new_data(const methodHandle& m, u_char* new_code, int new_code_length,
u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS);
@ -820,78 +800,29 @@ public:
void init_intrinsic_id(vmSymbolID klass_id); // updates from _none if a match
static vmSymbolID klass_id_for_intrinsics(const Klass* holder);
bool caller_sensitive() {
return (_flags & _caller_sensitive) != 0;
}
void set_caller_sensitive(bool x) {
_flags = x ? (_flags | _caller_sensitive) : (_flags & ~_caller_sensitive);
}
bool caller_sensitive() const { return constMethod()->caller_sensitive(); }
void set_caller_sensitive() { constMethod()->set_caller_sensitive(); }
bool force_inline() {
return (_flags & _force_inline) != 0;
}
void set_force_inline(bool x) {
_flags = x ? (_flags | _force_inline) : (_flags & ~_force_inline);
}
bool changes_current_thread() const { return constMethod()->changes_current_thread(); }
void set_changes_current_thread() { constMethod()->set_changes_current_thread(); }
bool dont_inline() {
return (_flags & _dont_inline) != 0;
}
void set_dont_inline(bool x) {
_flags = x ? (_flags | _dont_inline) : (_flags & ~_dont_inline);
}
bool jvmti_mount_transition() const { return constMethod()->jvmti_mount_transition(); }
void set_jvmti_mount_transition() { constMethod()->set_jvmti_mount_transition(); }
bool changes_current_thread() {
return (_flags & _changes_current_thread) != 0;
}
void set_changes_current_thread(bool x) {
_flags = x ? (_flags | _changes_current_thread) : (_flags & ~_changes_current_thread);
}
bool is_hidden() const { return constMethod()->is_hidden(); }
void set_is_hidden() { constMethod()->set_is_hidden(); }
bool jvmti_mount_transition() {
return (_flags & _jvmti_mount_transition) != 0;
}
void set_jvmti_mount_transition(bool x) {
_flags = x ? (_flags | _jvmti_mount_transition) : (_flags & ~_jvmti_mount_transition);
}
bool is_scoped() const { return constMethod()->is_scoped(); }
void set_scoped() { constMethod()->set_is_scoped(); }
bool is_hidden() const {
return (_flags & _hidden) != 0;
}
bool intrinsic_candidate() const { return constMethod()->intrinsic_candidate(); }
void set_intrinsic_candidate() { constMethod()->set_intrinsic_candidate(); }
void set_hidden(bool x) {
_flags = x ? (_flags | _hidden) : (_flags & ~_hidden);
}
bool has_injected_profile() const { return constMethod()->has_injected_profile(); }
void set_has_injected_profile() { constMethod()->set_has_injected_profile(); }
bool is_scoped() const {
return (_flags & _scoped) != 0;
}
void set_scoped(bool x) {
_flags = x ? (_flags | _scoped) : (_flags & ~_scoped);
}
bool intrinsic_candidate() {
return (_flags & _intrinsic_candidate) != 0;
}
void set_intrinsic_candidate(bool x) {
_flags = x ? (_flags | _intrinsic_candidate) : (_flags & ~_intrinsic_candidate);
}
bool has_injected_profile() {
return (_flags & _has_injected_profile) != 0;
}
void set_has_injected_profile(bool x) {
_flags = x ? (_flags | _has_injected_profile) : (_flags & ~_has_injected_profile);
}
bool has_reserved_stack_access() {
return (_flags & _reserved_stack_access) != 0;
}
void set_has_reserved_stack_access(bool x) {
_flags = x ? (_flags | _reserved_stack_access) : (_flags & ~_reserved_stack_access);
}
bool has_reserved_stack_access() const { return constMethod()->reserved_stack_access(); }
void set_has_reserved_stack_access() { constMethod()->set_reserved_stack_access(); }
JFR_ONLY(DEFINE_TRACE_FLAG_ACCESSOR;)
@ -939,24 +870,17 @@ public:
return _method_counters;
}
bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); }
void set_not_c1_compilable() { _access_flags.set_not_c1_compilable(); }
void clear_not_c1_compilable() { _access_flags.clear_not_c1_compilable(); }
bool is_not_c2_compilable() const { return access_flags().is_not_c2_compilable(); }
void set_not_c2_compilable() { _access_flags.set_not_c2_compilable(); }
void clear_not_c2_compilable() { _access_flags.clear_not_c2_compilable(); }
void clear_is_not_c1_compilable() { set_is_not_c1_compilable(false); }
void clear_is_not_c2_compilable() { set_is_not_c2_compilable(false); }
void clear_is_not_c2_osr_compilable() { set_is_not_c2_osr_compilable(false); }
bool is_not_c1_osr_compilable() const { return is_not_c1_compilable(); } // don't waste an accessFlags bit
void set_not_c1_osr_compilable() { set_not_c1_compilable(); } // don't waste an accessFlags bit
void clear_not_c1_osr_compilable() { clear_not_c1_compilable(); } // don't waste an accessFlags bit
bool is_not_c2_osr_compilable() const { return access_flags().is_not_c2_osr_compilable(); }
void set_not_c2_osr_compilable() { _access_flags.set_not_c2_osr_compilable(); }
void clear_not_c2_osr_compilable() { _access_flags.clear_not_c2_osr_compilable(); }
// not_c1_osr_compilable == not_c1_compilable
bool is_not_c1_osr_compilable() const { return is_not_c1_compilable(); }
void set_is_not_c1_osr_compilable() { set_is_not_c1_compilable(); }
void clear_is_not_c1_osr_compilable() { clear_is_not_c1_compilable(); }
// Background compilation support
bool queued_for_compilation() const { return access_flags().queued_for_compilation(); }
void set_queued_for_compilation() { _access_flags.set_queued_for_compilation(); }
void clear_queued_for_compilation() { _access_flags.clear_queued_for_compilation(); }
void clear_queued_for_compilation() { set_queued_for_compilation(false); }
// Resolve all classes in signature, return 'true' if successful
static bool load_signature_classes(const methodHandle& m, TRAPS);

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "oops/methodFlags.hpp"
#include "runtime/atomic.hpp"
#include "utilities/ostream.hpp"
// This can be removed for the atomic bitset functions, when available.
void MethodFlags::atomic_set_bits(u4 bits) {
// Atomically update the status with the bits given
u4 old_status, new_status, f;
do {
old_status = _status;
new_status = old_status | bits;
f = Atomic::cmpxchg(&_status, old_status, new_status);
} while(f != old_status);
}
void MethodFlags::atomic_clear_bits(u4 bits) {
// Atomically update the status with the bits given
u4 old_status, new_status, f;
do {
old_status = _status;
new_status = old_status & ~bits;
f = Atomic::cmpxchg(&_status, old_status, new_status);
} while(f != old_status);
}
void MethodFlags::print_on(outputStream* st) const {
#define M_PRINT(name, ignore) \
if (name()) st->print(" " #name " ");
M_STATUS_DO(M_PRINT)
#undef M_PRINT
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#ifndef SHARE_OOPS_METHODFLAGS_HPP
#define SHARE_OOPS_METHODFLAGS_HPP
#include "utilities/globalDefinitions.hpp"
#include "utilities/macros.hpp"
class outputStream;
// The MethodFlags class contains the writeable flags aka. status associated with
// an Method, and their associated accessors.
// _status are set at runtime and require atomic access.
// These flags are JVM internal and not part of the AccessFlags classfile specification.
class MethodFlags {
friend class VMStructs;
friend class JVMCIVMStructs;
/* end of list */
#define M_STATUS_DO(status) \
status(has_monitor_bytecodes , 1 << 0) /* Method contains monitorenter/monitorexit bytecodes */ \
status(has_jsrs , 1 << 1) \
status(is_old , 1 << 2) /* RedefineClasses() has replaced this method */ \
status(is_obsolete , 1 << 3) /* RedefineClasses() has made method obsolete */ \
status(is_deleted , 1 << 4) /* RedefineClasses() has deleted this method */ \
status(is_prefixed_native , 1 << 5) /* JVMTI has prefixed this native method */ \
status(monitor_matching , 1 << 6) /* True if we know that monitorenter/monitorexit bytecodes match */ \
status(queued_for_compilation , 1 << 7) \
status(is_not_c2_compilable , 1 << 8) \
status(is_not_c1_compilable , 1 << 9) \
status(is_not_c2_osr_compilable , 1 << 10) \
status(force_inline , 1 << 11) /* Annotations but also set/reset at runtime */ \
status(dont_inline , 1 << 12) \
status(has_loops_flag , 1 << 13) /* Method has loops */ \
status(has_loops_flag_init , 1 << 14) /* The loop flag has been initialized */ \
status(on_stack_flag , 1 << 15) /* RedefineClasses support to keep Metadata from being cleaned */ \
/* end of list */
#define M_STATUS_ENUM_NAME(name, value) _misc_##name = value,
enum {
M_STATUS_DO(M_STATUS_ENUM_NAME)
};
#undef M_STATUS_ENUM_NAME
// These flags are written during execution so require atomic stores
u4 _status;
public:
MethodFlags() : _status(0) {}
// Create getters and setters for the status values.
#define M_STATUS_GET_SET(name, ignore) \
bool name() const { return (_status & _misc_##name) != 0; } \
void set_##name(bool b) { \
if (b) { \
atomic_set_bits(_misc_##name); \
} else { \
atomic_clear_bits(_misc_##name); \
} \
}
M_STATUS_DO(M_STATUS_GET_SET)
#undef M_STATUS_GET_SET
int as_int() const { return _status; }
void atomic_set_bits(u4 bits);
void atomic_clear_bits(u4 bits);
void print_on(outputStream* st) const;
};
#endif // SHARE_OOPS_METHODFLAGS_HPP

View File

@ -1206,9 +1206,9 @@ WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
mdo->clean_method_data(/*always_clean*/true);
}
mh->clear_not_c1_compilable();
mh->clear_not_c2_compilable();
mh->clear_not_c2_osr_compilable();
mh->clear_is_not_c1_compilable();
mh->clear_is_not_c2_compilable();
mh->clear_is_not_c2_osr_compilable();
NOT_PRODUCT(mh->set_compiled_invocation_count(0));
if (mcs != nullptr) {
mcs->clear_counters();

View File

@ -299,7 +299,6 @@
nonstatic_field(Method, _access_flags, AccessFlags) \
nonstatic_field(Method, _vtable_index, int) \
nonstatic_field(Method, _intrinsic_id, u2) \
nonstatic_field(Method, _flags, u2) \
volatile_nonstatic_field(Method, _code, CompiledMethod*) \
nonstatic_field(Method, _i2i_entry, address) \
volatile_nonstatic_field(Method, _from_compiled_entry, address) \
@ -308,7 +307,7 @@
nonstatic_field(ConstMethod, _constants, ConstantPool*) \
nonstatic_field(ConstMethod, _stackmap_data, Array<u1>*) \
nonstatic_field(ConstMethod, _constMethod_size, int) \
nonstatic_field(ConstMethod, _flags, u2) \
nonstatic_field(ConstMethod, _flags._flags, u4) \
nonstatic_field(ConstMethod, _code_size, u2) \
nonstatic_field(ConstMethod, _name_index, u2) \
nonstatic_field(ConstMethod, _signature_index, u2) \
@ -2085,16 +2084,6 @@
/************************************************************/ \
\
declare_constant(JVM_ACC_WRITTEN_FLAGS) \
declare_constant(JVM_ACC_MONITOR_MATCH) \
declare_constant(JVM_ACC_HAS_MONITOR_BYTECODES) \
declare_constant(JVM_ACC_HAS_LOOPS) \
declare_constant(JVM_ACC_LOOPS_FLAG_INIT) \
declare_constant(JVM_ACC_QUEUED) \
declare_constant(JVM_ACC_NOT_C2_OSR_COMPILABLE) \
declare_constant(JVM_ACC_HAS_JSRS) \
declare_constant(JVM_ACC_IS_OLD) \
declare_constant(JVM_ACC_IS_OBSOLETE) \
declare_constant(JVM_ACC_IS_PREFIXED_NATIVE) \
declare_constant(JVM_ACC_HAS_FINALIZER) \
declare_constant(JVM_ACC_IS_CLONEABLE_FAST) \
\
@ -2178,30 +2167,23 @@
declare_constant(Klass::_lh_array_tag_type_value) \
declare_constant(Klass::_lh_array_tag_obj_value) \
\
declare_constant(Method::nonvirtual_vtable_index) \
declare_constant(Method::extra_stack_entries_for_jsr292) \
\
/********************************/ \
/* ConstMethod anon-enum */ \
/********************************/ \
\
declare_constant(Method::_caller_sensitive) \
declare_constant(Method::_force_inline) \
declare_constant(Method::_dont_inline) \
declare_constant(Method::_hidden) \
declare_constant(Method::_changes_current_thread) \
\
declare_constant(Method::nonvirtual_vtable_index) \
\
declare_constant(Method::extra_stack_entries_for_jsr292) \
\
declare_constant(ConstMethod::_has_linenumber_table) \
declare_constant(ConstMethod::_has_checked_exceptions) \
declare_constant(ConstMethod::_has_localvariable_table) \
declare_constant(ConstMethod::_has_exception_table) \
declare_constant(ConstMethod::_has_generic_signature) \
declare_constant(ConstMethod::_has_method_parameters) \
declare_constant(ConstMethod::_has_method_annotations) \
declare_constant(ConstMethod::_has_parameter_annotations) \
declare_constant(ConstMethod::_has_default_annotations) \
declare_constant(ConstMethod::_has_type_annotations) \
declare_constant(ConstMethodFlags::_misc_has_linenumber_table) \
declare_constant(ConstMethodFlags::_misc_has_checked_exceptions) \
declare_constant(ConstMethodFlags::_misc_has_localvariable_table) \
declare_constant(ConstMethodFlags::_misc_has_exception_table) \
declare_constant(ConstMethodFlags::_misc_has_generic_signature) \
declare_constant(ConstMethodFlags::_misc_has_method_parameters) \
declare_constant(ConstMethodFlags::_misc_has_method_annotations) \
declare_constant(ConstMethodFlags::_misc_has_parameter_annotations) \
declare_constant(ConstMethodFlags::_misc_has_default_annotations) \
declare_constant(ConstMethodFlags::_misc_has_type_annotations) \
\
/**************/ \
/* DataLayout */ \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,27 +27,6 @@
#include "runtime/atomic.hpp"
#include "utilities/accessFlags.hpp"
void AccessFlags::atomic_set_bits(jint bits) {
// Atomically update the flags with the bits given
jint old_flags, new_flags, f;
do {
old_flags = _flags;
new_flags = old_flags | bits;
f = Atomic::cmpxchg(&_flags, old_flags, new_flags);
} while(f != old_flags);
}
void AccessFlags::atomic_clear_bits(jint bits) {
// Atomically update the flags with the bits given
jint old_flags, new_flags, f;
do {
old_flags = _flags;
new_flags = old_flags & ~bits;
f = Atomic::cmpxchg(&_flags, old_flags, new_flags);
} while(f != old_flags);
}
#if !defined(PRODUCT) || INCLUDE_JVMTI
void AccessFlags::print_on(outputStream* st) const {
@ -63,9 +42,6 @@ void AccessFlags::print_on(outputStream* st) const {
if (is_interface ()) st->print("interface " );
if (is_abstract ()) st->print("abstract " );
if (is_synthetic ()) st->print("synthetic " );
if (is_old ()) st->print("{old} " );
if (is_obsolete ()) st->print("{obsolete} " );
if (on_stack ()) st->print("{on_stack} " );
}
#endif // !PRODUCT || INCLUDE_JVMTI

View File

@ -42,22 +42,6 @@ enum {
// flags actually put in .class file
JVM_ACC_WRITTEN_FLAGS = 0x00007FFF,
// Method* flags
JVM_ACC_MONITOR_MATCH = 0x10000000, // True if we know that monitorenter/monitorexit bytecodes match
JVM_ACC_HAS_MONITOR_BYTECODES = 0x20000000, // Method contains monitorenter/monitorexit bytecodes
JVM_ACC_HAS_LOOPS = 0x40000000, // Method has loops
JVM_ACC_LOOPS_FLAG_INIT = (int)0x80000000,// The loop flag has been initialized
JVM_ACC_QUEUED = 0x01000000, // Queued for compilation
JVM_ACC_NOT_C2_COMPILABLE = 0x02000000,
JVM_ACC_NOT_C1_COMPILABLE = 0x04000000,
JVM_ACC_NOT_C2_OSR_COMPILABLE = 0x08000000,
JVM_ACC_HAS_JSRS = 0x00800000,
JVM_ACC_IS_OLD = 0x00010000, // RedefineClasses() has replaced this method
JVM_ACC_IS_OBSOLETE = 0x00020000, // RedefineClasses() has made method obsolete
JVM_ACC_IS_PREFIXED_NATIVE = 0x00040000, // JVMTI has prefixed this native method
JVM_ACC_ON_STACK = 0x00080000, // RedefineClasses() was used on the stack
JVM_ACC_IS_DELETED = 0x00008000, // RedefineClasses() has deleted this method
// Klass* flags
JVM_ACC_HAS_FINALIZER = 0x40000000, // True if klass has a non-empty finalize() method
JVM_ACC_IS_CLONEABLE_FAST = (int)0x80000000,// True if klass implements the Cloneable interface and can be optimized in generated code
@ -92,29 +76,12 @@ class AccessFlags {
// Attribute flags
bool is_synthetic () const { return (_flags & JVM_ACC_SYNTHETIC ) != 0; }
// Method* flags
bool is_monitor_matching () const { return (_flags & JVM_ACC_MONITOR_MATCH ) != 0; }
bool has_monitor_bytecodes () const { return (_flags & JVM_ACC_HAS_MONITOR_BYTECODES ) != 0; }
bool has_loops () const { return (_flags & JVM_ACC_HAS_LOOPS ) != 0; }
bool loops_flag_init () const { return (_flags & JVM_ACC_LOOPS_FLAG_INIT ) != 0; }
bool queued_for_compilation () const { return (_flags & JVM_ACC_QUEUED ) != 0; }
bool is_not_c1_compilable () const { return (_flags & JVM_ACC_NOT_C1_COMPILABLE ) != 0; }
bool is_not_c2_compilable () const { return (_flags & JVM_ACC_NOT_C2_COMPILABLE ) != 0; }
bool is_not_c2_osr_compilable() const { return (_flags & JVM_ACC_NOT_C2_OSR_COMPILABLE ) != 0; }
bool has_jsrs () const { return (_flags & JVM_ACC_HAS_JSRS ) != 0; }
bool is_old () const { return (_flags & JVM_ACC_IS_OLD ) != 0; }
bool is_obsolete () const { return (_flags & JVM_ACC_IS_OBSOLETE ) != 0; }
bool is_deleted () const { return (_flags & JVM_ACC_IS_DELETED ) != 0; }
bool is_prefixed_native () const { return (_flags & JVM_ACC_IS_PREFIXED_NATIVE ) != 0; }
// Klass* flags
bool has_finalizer () const { return (_flags & JVM_ACC_HAS_FINALIZER ) != 0; }
bool is_cloneable_fast () const { return (_flags & JVM_ACC_IS_CLONEABLE_FAST ) != 0; }
bool is_hidden_class () const { return (_flags & JVM_ACC_IS_HIDDEN_CLASS ) != 0; }
bool is_value_based_class () const { return (_flags & JVM_ACC_IS_VALUE_BASED_CLASS ) != 0; }
bool on_stack() const { return (_flags & JVM_ACC_ON_STACK) != 0; }
// get .class file flags
jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); }
@ -125,55 +92,23 @@ class AccessFlags {
}
void set_flags(jint flags) { _flags = (flags & JVM_ACC_WRITTEN_FLAGS); }
void set_queued_for_compilation() { atomic_set_bits(JVM_ACC_QUEUED); }
void clear_queued_for_compilation() { atomic_clear_bits(JVM_ACC_QUEUED); }
// Atomic update of flags
void atomic_set_bits(jint bits);
void atomic_clear_bits(jint bits);
private:
friend class Method;
friend class Klass;
friend class ClassFileParser;
// the functions below should only be called on the _access_flags inst var directly,
// otherwise they are just changing a copy of the flags
// attribute flags
void set_is_synthetic() { atomic_set_bits(JVM_ACC_SYNTHETIC); }
void set_is_synthetic() { _flags |= JVM_ACC_SYNTHETIC; }
// Method* flags
void set_monitor_matching() { atomic_set_bits(JVM_ACC_MONITOR_MATCH); }
void set_has_monitor_bytecodes() { atomic_set_bits(JVM_ACC_HAS_MONITOR_BYTECODES); }
void set_has_loops() { atomic_set_bits(JVM_ACC_HAS_LOOPS); }
void set_loops_flag_init() { atomic_set_bits(JVM_ACC_LOOPS_FLAG_INIT); }
void set_not_c1_compilable() { atomic_set_bits(JVM_ACC_NOT_C1_COMPILABLE); }
void set_not_c2_compilable() { atomic_set_bits(JVM_ACC_NOT_C2_COMPILABLE); }
void set_not_c2_osr_compilable() { atomic_set_bits(JVM_ACC_NOT_C2_OSR_COMPILABLE); }
void set_has_jsrs() { atomic_set_bits(JVM_ACC_HAS_JSRS); }
void set_is_old() { atomic_set_bits(JVM_ACC_IS_OLD); }
void set_is_obsolete() { atomic_set_bits(JVM_ACC_IS_OBSOLETE); }
void set_is_deleted() { atomic_set_bits(JVM_ACC_IS_DELETED); }
void set_is_prefixed_native() { atomic_set_bits(JVM_ACC_IS_PREFIXED_NATIVE); }
void clear_not_c1_compilable() { atomic_clear_bits(JVM_ACC_NOT_C1_COMPILABLE); }
void clear_not_c2_compilable() { atomic_clear_bits(JVM_ACC_NOT_C2_COMPILABLE); }
void clear_not_c2_osr_compilable() { atomic_clear_bits(JVM_ACC_NOT_C2_OSR_COMPILABLE); }
// Klass* flags
void set_has_finalizer() { atomic_set_bits(JVM_ACC_HAS_FINALIZER); }
void set_is_cloneable_fast() { atomic_set_bits(JVM_ACC_IS_CLONEABLE_FAST); }
void set_is_hidden_class() { atomic_set_bits(JVM_ACC_IS_HIDDEN_CLASS); }
void set_is_value_based_class() { atomic_set_bits(JVM_ACC_IS_VALUE_BASED_CLASS); }
// These are set at classfile parsing time so do not require atomic access.
void set_has_finalizer() { _flags |= JVM_ACC_HAS_FINALIZER; }
void set_is_cloneable_fast() { _flags |= JVM_ACC_IS_CLONEABLE_FAST; }
void set_is_hidden_class() { _flags |= JVM_ACC_IS_HIDDEN_CLASS; }
void set_is_value_based_class() { _flags |= JVM_ACC_IS_VALUE_BASED_CLASS; }
public:
void set_on_stack(const bool value)
{
if (value) {
atomic_set_bits(JVM_ACC_ON_STACK);
} else {
atomic_clear_bits(JVM_ACC_ON_STACK);
}
}
// Conversion
jshort as_short() const { return (jshort)_flags; }
jint as_int() const { return _flags; }

View File

@ -56,17 +56,6 @@ public class AccessFlags implements /* imports */ ClassConstants {
public long getValue () { return flags; }
// Hotspot internal flags
// Method* flags
public boolean isMonitorMatching () { return (flags & JVM_ACC_MONITOR_MATCH ) != 0; }
public boolean hasMonitorBytecodes () { return (flags & JVM_ACC_HAS_MONITOR_BYTECODES ) != 0; }
public boolean hasLoops () { return (flags & JVM_ACC_HAS_LOOPS ) != 0; }
public boolean loopsFlagInit () { return (flags & JVM_ACC_LOOPS_FLAG_INIT ) != 0; }
public boolean queuedForCompilation() { return (flags & JVM_ACC_QUEUED ) != 0; }
public boolean isNotOsrCompilable () { return (flags & JVM_ACC_NOT_OSR_COMPILABLE ) != 0; }
public boolean hasJsrs () { return (flags & JVM_ACC_HAS_JSRS ) != 0; }
public boolean isObsolete () { return (flags & JVM_ACC_IS_OBSOLETE ) != 0; }
// Klass* flags
public boolean hasFinalizer () { return (flags & JVM_ACC_HAS_FINALIZER ) != 0; }
public boolean isCloneable () { return (flags & JVM_ACC_IS_CLONEABLE ) != 0; }

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -63,19 +63,19 @@ public class ConstMethod extends Metadata {
Type type = db.lookupType("ConstMethod");
constants = new MetadataField(type.getAddressField("_constants"), 0);
constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0);
flags = new CIntField(type.getCIntegerField("_flags"), 0);
flags = new CIntField(type.getCIntegerField("_flags._flags"), 0);
// enum constants for flags
HAS_LINENUMBER_TABLE = db.lookupIntConstant("ConstMethod::_has_linenumber_table").intValue();
HAS_CHECKED_EXCEPTIONS = db.lookupIntConstant("ConstMethod::_has_checked_exceptions").intValue();
HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("ConstMethod::_has_localvariable_table").intValue();
HAS_EXCEPTION_TABLE = db.lookupIntConstant("ConstMethod::_has_exception_table").intValue();
HAS_GENERIC_SIGNATURE = db.lookupIntConstant("ConstMethod::_has_generic_signature").intValue();
HAS_METHOD_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_method_annotations").intValue();
HAS_PARAMETER_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_parameter_annotations").intValue();
HAS_METHOD_PARAMETERS = db.lookupIntConstant("ConstMethod::_has_method_parameters").intValue();
HAS_DEFAULT_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_default_annotations").intValue();
HAS_TYPE_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_type_annotations").intValue();
HAS_LINENUMBER_TABLE = db.lookupIntConstant("ConstMethodFlags::_misc_has_linenumber_table").intValue();
HAS_CHECKED_EXCEPTIONS = db.lookupIntConstant("ConstMethodFlags::_misc_has_checked_exceptions").intValue();
HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("ConstMethodFlags::_misc_has_localvariable_table").intValue();
HAS_EXCEPTION_TABLE = db.lookupIntConstant("ConstMethodFlags::_misc_has_exception_table").intValue();
HAS_GENERIC_SIGNATURE = db.lookupIntConstant("ConstMethodFlags::_misc_has_generic_signature").intValue();
HAS_METHOD_ANNOTATIONS = db.lookupIntConstant("ConstMethodFlags::_misc_has_method_annotations").intValue();
HAS_PARAMETER_ANNOTATIONS = db.lookupIntConstant("ConstMethodFlags::_misc_has_parameter_annotations").intValue();
HAS_METHOD_PARAMETERS = db.lookupIntConstant("ConstMethodFlags::_misc_has_method_parameters").intValue();
HAS_DEFAULT_ANNOTATIONS = db.lookupIntConstant("ConstMethodFlags::_misc_has_default_annotations").intValue();
HAS_TYPE_ANNOTATIONS = db.lookupIntConstant("ConstMethodFlags::_misc_has_type_annotations").intValue();
// Size of Java bytecodes allocated immediately after ConstMethod*.
codeSize = new CIntField(type.getCIntegerField("_code_size"), 0);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -252,10 +252,6 @@ public class Method extends Metadata {
return isStatic() && getName().equals(classInitializerName());
}
public boolean isObsolete() {
return getAccessFlagsObj().isObsolete();
}
public OopMapCacheEntry getMaskFor(int bci) {
OopMapCacheEntry entry = new OopMapCacheEntry();
entry.fill(this, bci);

View File

@ -103,25 +103,6 @@ public interface ClassConstants
// flags actually put in .class file
public static final long JVM_ACC_WRITTEN_FLAGS = 0x00007FFF;
// Method* flags
// monitorenter/monitorexit bytecodes match
public static final long JVM_ACC_MONITOR_MATCH = 0x10000000;
// Method contains monitorenter/monitorexit bytecodes
public static final long JVM_ACC_HAS_MONITOR_BYTECODES = 0x20000000;
// Method has loops
public static final long JVM_ACC_HAS_LOOPS = 0x40000000;
// The loop flag has been initialized
public static final long JVM_ACC_LOOPS_FLAG_INIT = (int)0x80000000;
// Queued for compilation
public static final long JVM_ACC_QUEUED = 0x01000000;
// TEMPORARY: currently on stack replacement compilation is not built into the
// invocation counter machinery. Until it is, we will keep track of methods which
// cannot be on stack replaced in the access flags.
public static final long JVM_ACC_NOT_OSR_COMPILABLE = 0x08000000;
public static final long JVM_ACC_HAS_JSRS = 0x00800000;
// RedefineClasses() has made method obsolete
public static final long JVM_ACC_IS_OBSOLETE = 0x00010000;
// Klass* flags
// True if klass has a non-empty finalize() method
public static final long JVM_ACC_HAS_FINALIZER = 0x40000000;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -317,7 +317,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
*/
@Override
public boolean isCallerSensitive() {
return (getFlags() & config().methodFlagsCallerSensitive) != 0;
return (getConstMethodFlags() & config().constMethodFlagsCallerSensitive) != 0;
}
/**
@ -337,7 +337,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
*/
@Override
public boolean hasReservedStackAccess() {
return (getFlags() & config().methodFlagsReservedStackAccess) != 0;
return (getConstMethodFlags() & config().constMethodFlagsReservedStackAccess) != 0;
}
/**
@ -737,7 +737,7 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
@Override
public boolean isIntrinsicCandidate() {
return (getFlags() & config().methodFlagsIntrinsicCandidate) != 0;
return (getConstMethodFlags() & config().constMethodFlagsIntrinsicCandidate) != 0;
}
/**

View File

@ -149,17 +149,14 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
final int methodAccessFlagsOffset = getFieldOffset("Method::_access_flags", Integer.class, "AccessFlags");
final int methodConstMethodOffset = getFieldOffset("Method::_constMethod", Integer.class, "ConstMethod*");
final int methodIntrinsicIdOffset = getFieldOffset("Method::_intrinsic_id", Integer.class, "u2");
final int methodFlagsOffset = getFieldOffset("Method::_flags", Integer.class, "u2");
final int methodFlagsOffset = getFieldOffset("Method::_flags._status", Integer.class, "u4");
final int methodVtableIndexOffset = getFieldOffset("Method::_vtable_index", Integer.class, "int");
final int methodDataOffset = getFieldOffset("Method::_method_data", Integer.class, "MethodData*");
final int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, "CompiledMethod*");
final int methodFlagsCallerSensitive = getConstant("Method::_caller_sensitive", Integer.class);
final int methodFlagsForceInline = getConstant("Method::_force_inline", Integer.class);
final int methodFlagsIntrinsicCandidate = getConstant("Method::_intrinsic_candidate", Integer.class);
final int methodFlagsDontInline = getConstant("Method::_dont_inline", Integer.class);
final int methodFlagsReservedStackAccess = getConstant("Method::_reserved_stack_access", Integer.class);
final int methodFlagsForceInline = getConstant("MethodFlags::_misc_force_inline", Integer.class);
final int methodFlagsDontInline = getConstant("MethodFlags::_misc_dont_inline", Integer.class);
final int nonvirtualVtableIndex = getConstant("Method::nonvirtual_vtable_index", Integer.class);
final int invalidVtableIndex = getConstant("Method::invalid_vtable_index", Integer.class);
@ -190,7 +187,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
final int extraStackEntries = getFieldValue("CompilerToVM::Data::Method_extra_stack_entries", Integer.class, "int");
final int constMethodConstantsOffset = getFieldOffset("ConstMethod::_constants", Integer.class, "ConstantPool*");
final int constMethodFlagsOffset = getFieldOffset("ConstMethod::_flags", Integer.class, "u2");
final int constMethodFlagsOffset = getFieldOffset("ConstMethod::_flags._flags", Integer.class, "u4");
final int constMethodCodeSizeOffset = getFieldOffset("ConstMethod::_code_size", Integer.class, "u2");
final int constMethodNameIndexOffset = getFieldOffset("ConstMethod::_name_index", Integer.class, "u2");
final int constMethodSignatureIndexOffset = getFieldOffset("ConstMethod::_signature_index", Integer.class, "u2");
@ -198,11 +195,14 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
final int constMethodMaxStackOffset = getFieldOffset("ConstMethod::_max_stack", Integer.class, "u2");
final int methodMaxLocalsOffset = getFieldOffset("ConstMethod::_max_locals", Integer.class, "u2");
final int constMethodHasLineNumberTable = getConstant("ConstMethod::_has_linenumber_table", Integer.class);
final int constMethodHasLocalVariableTable = getConstant("ConstMethod::_has_localvariable_table", Integer.class);
final int constMethodHasMethodAnnotations = getConstant("ConstMethod::_has_method_annotations", Integer.class);
final int constMethodHasParameterAnnotations = getConstant("ConstMethod::_has_parameter_annotations", Integer.class);
final int constMethodHasExceptionTable = getConstant("ConstMethod::_has_exception_table", Integer.class);
final int constMethodFlagsReservedStackAccess = getConstant("ConstMethodFlags::_misc_reserved_stack_access", Integer.class);
final int constMethodFlagsCallerSensitive = getConstant("ConstMethodFlags::_misc_caller_sensitive", Integer.class);
final int constMethodFlagsIntrinsicCandidate = getConstant("ConstMethodFlags::_misc_intrinsic_candidate", Integer.class);
final int constMethodHasLineNumberTable = getConstant("ConstMethodFlags::_misc_has_linenumber_table", Integer.class);
final int constMethodHasLocalVariableTable = getConstant("ConstMethodFlags::_misc_has_localvariable_table", Integer.class);
final int constMethodHasMethodAnnotations = getConstant("ConstMethodFlags::_misc_has_method_annotations", Integer.class);
final int constMethodHasParameterAnnotations = getConstant("ConstMethodFlags::_misc_has_parameter_annotations", Integer.class);
final int constMethodHasExceptionTable = getConstant("ConstMethodFlags::_misc_has_exception_table", Integer.class);
final int exceptionTableElementSize = getFieldValue("CompilerToVM::Data::sizeof_ExceptionTableElement", Integer.class, "int");
final int exceptionTableElementStartPcOffset = getFieldOffset("ExceptionTableElement::start_pc", Integer.class, "u2");