bool equal(CellTypeState a) const { return _state == a._state; }
bool equal_kind(CellTypeState a) const {
return (_state & bits_mask) == (a._state & bits_mask);
}
char to_char() const;
CellTypeState merge (CellTypeState cts, int slot) const;
void print(outputStream *os);
static CellTypeState bottom;
static CellTypeState uninit;
static CellTypeState ref;
static CellTypeState value;
static CellTypeState refUninit;
static CellTypeState varUninit;
static CellTypeState top;
static CellTypeState addr;
};
class BasicBlock: ResourceObj {
private:
bool _changed; // Reached a fixpoint or not
public:
enum Constants {
_dead_basic_block = -2,
_unreached = -1 // Alive but not yet reached by analysis
};
int _bci; // Start of basic block
int _end_bci; // Bci of last instruction in basicblock
int _max_locals; // Determines split between vars and stack
int _max_stack; // Determines split between stack and monitors
CellTypeState* _state; // State (vars, stack) at entry.
int _stack_top; // -1 indicates bottom stack value.
int _monitor_top; // -1 indicates bottom monitor stack value.
CellTypeState* vars() { return _state; }
CellTypeState* stack() { return _state + _max_locals; }
bool changed() { return _changed; }
void set_changed(bool s) { _changed = s; }
bool is_reachable() const { return _stack_top >= 0; } // Analysis has reached this basicblock
bool is_dead() const { return _stack_top == _dead_basic_block; }
bool is_alive() const { return _stack_top != _dead_basic_block; }
void mark_as_alive() { assert(is_dead(), "must be dead"); _stack_top = _unreached; }
};
class GenerateOopMap VALUE_OBJ_CLASS_SPEC {
protected:
enum { bad_monitors = -1 };
methodHandle _method; // The method we are examine
RetTable _rt; // Contains the return address mappings
int _max_locals; // Cached value of no. of locals
int _max_stack; // Cached value of max. stack depth
int _max_monitors; // Cached value of max. monitor stack depth
int _has_exceptions; // True, if exceptions exist for method
bool _got_error; // True, if an error occurred during interpretation.
Handle _exception; // Exception if got_error is true.
bool _did_rewriting; // was bytecodes rewritten
bool _did_relocation; // was relocation neccessary
bool _monitor_safe; // The monitors in this method have been determined
int _state_len; // Size of states
CellTypeState *_state; // list of states
char *_state_vec_buf; // Buffer used to print a readable version of a state
int _stack_top;
int _monitor_top;
static elapsedTimer _total_oopmap_time; // Holds cumulative oopmap generation time
static long _total_byte_count; // Holds cumulative number of bytes inspected
void init_state();
void make_context_uninitialized ();
int methodsig_to_effect (Symbol* signature, bool isStatic, CellTypeState* effect);
bool merge_local_state_vectors (CellTypeState* cts, CellTypeState* bbts);
bool merge_monitor_state_vectors(CellTypeState* cts, CellTypeState* bbts);
void copy_state (CellTypeState *dst, CellTypeState *src);
void merge_state_into_bb (BasicBlock *bb);
static void merge_state (GenerateOopMap *gom, int bcidelta, int* data);
void set_var (int localNo, CellTypeState cts);
CellTypeState get_var (int localNo);
CellTypeState pop ();
void push (CellTypeState cts);
CellTypeState monitor_pop ();
void monitor_push (CellTypeState cts);
CellTypeState * vars () { return _state; }
CellTypeState * stack () { return _state+_max_locals; }
CellTypeState * monitors () { return _state+_max_locals+_max_stack; }
void replace_all_CTS_matches (CellTypeState match,
CellTypeState replace);
void print_states (outputStream *os, CellTypeState *vector, int num);
void print_current_state (outputStream *os,
BytecodeStream *itr,
bool detailed);
void report_monitor_mismatch (const char *msg);
BasicBlock * _basic_blocks; // Array of basicblock info
int _gc_points;
int _bb_count;
BitMap _bb_hdr_bits;
void initialize_bb ();
void mark_bbheaders_and_count_gc_points();
bool is_bb_header (int bci) const {
return _bb_hdr_bits.at(bci);
}
int gc_points () const { return _gc_points; }
int bb_count () const { return _bb_count; }
void set_bbmark_bit (int bci) {
_bb_hdr_bits.at_put(bci, true);
}
void clear_bbmark_bit (int bci) {
_bb_hdr_bits.at_put(bci, false);
}
BasicBlock * get_basic_block_at (int bci) const;
BasicBlock * get_basic_block_containing (int bci) const;
void interp_bb (BasicBlock *bb);
void restore_state (BasicBlock *bb);
int next_bb_start_pc (BasicBlock *bb);
void update_basic_blocks (int bci, int delta, int new_method_size);
static void bb_mark_fct (GenerateOopMap *c, int deltaBci, int *data);
void mark_reachable_code();
static void reachable_basicblock (GenerateOopMap *c, int deltaBci, int *data);
void do_interpretation ();
void init_basic_blocks ();
void setup_method_entry_state ();
void interp_all ();
void interp1 (BytecodeStream *itr);
void do_exception_edge (BytecodeStream *itr);
void check_type (CellTypeState expected, CellTypeState actual);
void ppstore (CellTypeState *in, int loc_no);
void ppload (CellTypeState *out, int loc_no);
void ppush1 (CellTypeState in);
void ppush (CellTypeState *in);
void ppop1 (CellTypeState out);
void ppop (CellTypeState *out);
void ppop_any (int poplen);
void pp (CellTypeState *in, CellTypeState *out);
void pp_new_ref (CellTypeState *in, int bci);
void ppdupswap (int poplen, const char *out);
void do_ldc (int bci);
void do_astore (int idx);
void do_jsr (int delta);
void do_field (int is_get, int is_static, int idx, int bci);
void do_method (int is_static, int is_interface, int idx, int bci);
void do_multianewarray (int dims, int bci);
void do_monitorenter (int bci);
void do_monitorexit (int bci);
void do_return_monitor_check ();
void do_checkcast ();
CellTypeState *sigchar_to_effect (char sigch, int bci, CellTypeState *out);
int copy_cts (CellTypeState *dst, CellTypeState *src);
void error_work (const char *format, va_list ap) ATTRIBUTE_PRINTF(2, 0);
void report_error (const char *format, ...) ATTRIBUTE_PRINTF(2, 3);
void verify_error (const char *format, ...) ATTRIBUTE_PRINTF(2, 3);
bool got_error() { return _got_error; }
bool _report_result;
bool _report_result_for_send; // Unfortunatly, stackmaps for sends are special, so we need some extra
BytecodeStream *_itr_send; // variables to handle them properly.
void report_result ();
GrowableArray<intptr_t> * _init_vars;
void initialize_vars ();
void add_to_ref_init_set (int localNo);
bool _conflict; // True, if a conflict occurred during interpretation
int _nof_refval_conflicts; // No. of conflicts that require rewrites
int * _new_var_map;
void record_refval_conflict (int varNo);
void rewrite_refval_conflicts ();
void rewrite_refval_conflict (int from, int to);
bool rewrite_refval_conflict_inst (BytecodeStream *i, int from, int to);
bool rewrite_load_or_store (BytecodeStream *i, Bytecodes::Code bc, Bytecodes::Code bc0, unsigned int varNo);
void expand_current_instr (int bci, int ilen, int newIlen, u_char inst_buffer[]);
bool is_astore (BytecodeStream *itr, int *index);
bool is_aload (BytecodeStream *itr, int *index);
GrowableArray<intptr_t> *_ret_adr_tos;
bool stack_top_holds_ret_addr (int bci);
void compute_ret_adr_at_TOS ();
void update_ret_adr_at_TOS (int bci, int delta);
int binsToHold (int no) { return ((no+(BitsPerWord-1))/BitsPerWord); }
char *state_vec_to_string (CellTypeState* vec, int len);
void ret_jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int varNo,int *data);
bool jump_targets_do (BytecodeStream *bcs, jmpFct_t jmpFct, int *data);
friend class RelocCallback;
public:
GenerateOopMap(methodHandle method);
void compute_map(TRAPS);
void result_for_basicblock(int bci); // Do a callback on fill_stackmap_for_opcodes for basicblock containing bci
int max_locals() const { return _max_locals; }
Method* method() const { return _method(); }
methodHandle method_as_handle() const { return _method; }
bool did_rewriting() { return _did_rewriting; }
bool did_relocation() { return _did_relocation; }
static void print_time();
bool monitor_safe() { return _monitor_safe; }
virtual bool allow_rewrites () const { return false; }
virtual bool report_results () const { return true; }
virtual bool report_init_vars () const { return true; }
virtual bool possible_gc_point (BytecodeStream *bcs) { ShouldNotReachHere(); return false; }
virtual void fill_stackmap_prolog (int nof_gc_points) { ShouldNotReachHere(); }
virtual void fill_stackmap_epilog () { ShouldNotReachHere(); }
virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs,
CellTypeState* vars,
CellTypeState* stack,
int stackTop) { ShouldNotReachHere(); }
virtual void fill_init_vars (GrowableArray<intptr_t> *init_vars) { ShouldNotReachHere();; }
};
class ResolveOopMapConflicts: public GenerateOopMap {
private:
bool _must_clear_locals;
virtual bool report_results() const { return false; }
virtual bool report_init_vars() const { return true; }
virtual bool allow_rewrites() const { return true; }
virtual bool possible_gc_point (BytecodeStream *bcs) { return false; }
virtual void fill_stackmap_prolog (int nof_gc_points) {}
virtual void fill_stackmap_epilog () {}
virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs,
CellTypeState* vars,
CellTypeState* stack,
int stack_top) {}
virtual void fill_init_vars (GrowableArray<intptr_t> *init_vars) { _must_clear_locals = init_vars->length() > 0; }
#ifndef PRODUCT
static int _nof_invocations;
static int _nof_rewrites;
static int _nof_relocations;
#endif
public:
ResolveOopMapConflicts(methodHandle method) : GenerateOopMap(method) { _must_clear_locals = false; };
methodHandle do_potential_rewrite(TRAPS);
bool must_clear_locals() const { return _must_clear_locals; }
};
class GeneratePairingInfo: public GenerateOopMap {
private:
virtual bool report_results() const { return false; }
virtual bool report_init_vars() const { return false; }
virtual bool allow_rewrites() const { return false; }
virtual bool possible_gc_point (BytecodeStream *bcs) { return false; }
virtual void fill_stackmap_prolog (int nof_gc_points) {}
virtual void fill_stackmap_epilog () {}
virtual void fill_stackmap_for_opcodes (BytecodeStream *bcs,
CellTypeState* vars,
CellTypeState* stack,
int stack_top) {}
virtual void fill_init_vars (GrowableArray<intptr_t> *init_vars) {}
public:
GeneratePairingInfo(methodHandle method) : GenerateOopMap(method) {};
};
#endif // SHARE_VM_OOPS_GENERATEOOPMAP_HPP
C:\hotspot-69087d08d473\src\share\vm/oops/instanceClassLoaderKlass.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc_implementation/shared/markSweep.inline.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "memory/genOopClosures.inline.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/oopFactory.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceClassLoaderKlass.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/instanceOop.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/parNew/parOopClosures.inline.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
#include "oops/oop.pcgc.inline.hpp"
#endif // INCLUDE_ALL_GCS
#define InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)\
\
int InstanceClassLoaderKlass:: \
oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
int size = InstanceKlass::oop_oop_iterate##nv_suffix(obj, closure); \
\
if_do_metadata_checked(closure, nv_suffix) { \
ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj); \
if (cld != NULL) { \
closure->do_class_loader_data(cld); \
} \
} \
\
return size; \
}
#if INCLUDE_ALL_GCS
#define InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
\
int InstanceClassLoaderKlass:: \
oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
int size = InstanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \
return size; \
}
#endif // INCLUDE_ALL_GCS
#define InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \
\
int InstanceClassLoaderKlass:: \
oop_oop_iterate##nv_suffix##_m(oop obj, \
OopClosureType* closure, \
MemRegion mr) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
\
int size = InstanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr); \
\
if_do_metadata_checked(closure, nv_suffix) { \
if (mr.contains(obj)) { \
ClassLoaderData* cld = java_lang_ClassLoader::loader_data(obj); \
if (cld != NULL) { \
closure->do_class_loader_data(cld); \
} \
} \
} \
\
return size; \
}
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN)
#if INCLUDE_ALL_GCS
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
#endif // INCLUDE_ALL_GCS
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m)
void InstanceClassLoaderKlass::oop_follow_contents(oop obj) {
InstanceKlass::oop_follow_contents(obj);
ClassLoaderData * const loader_data = java_lang_ClassLoader::loader_data(obj);
if(loader_data != NULL) {
MarkSweep::follow_class_loader(loader_data);
}
}
#if INCLUDE_ALL_GCS
void InstanceClassLoaderKlass::oop_follow_contents(ParCompactionManager* cm,
oop obj) {
InstanceKlass::oop_follow_contents(cm, obj);
ClassLoaderData * const loader_data = java_lang_ClassLoader::loader_data(obj);
if (loader_data != NULL) {
PSParallelCompact::follow_class_loader(cm, loader_data);
}
}
void InstanceClassLoaderKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
InstanceKlass::oop_push_contents(pm, obj);
}
int InstanceClassLoaderKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
InstanceKlass::oop_update_pointers(cm, obj);
return size_helper();
}
#endif // INCLUDE_ALL_GCS
C:\hotspot-69087d08d473\src\share\vm/oops/instanceClassLoaderKlass.hpp
#ifndef SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_HPP
#define SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_HPP
#include "oops/instanceKlass.hpp"
#include "utilities/macros.hpp"
class InstanceClassLoaderKlass: public InstanceKlass {
friend class VMStructs;
friend class InstanceKlass;
InstanceClassLoaderKlass(int vtable_len, int itable_len, int static_field_size, int nonstatic_oop_map_size, ReferenceType rt, AccessFlags access_flags, bool is_anonymous)
: InstanceKlass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt, access_flags, is_anonymous) {}
public:
virtual bool oop_is_instanceClassLoader() const { return true; }
InstanceClassLoaderKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
int oop_oop_iterate(oop obj, ExtendedOopClosure* blk) {
return oop_oop_iterate_v(obj, blk);
}
int oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) {
return oop_oop_iterate_v_m(obj, blk, mr);
}
#define InstanceClassLoaderKlass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
int oop_oop_iterate##nv_suffix(oop obj, OopClosureType* blk); \
int oop_oop_iterate##nv_suffix##_m(oop obj, OopClosureType* blk, MemRegion mr);
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DECL)
#if INCLUDE_ALL_GCS
#define InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \
int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk);
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
#endif // INCLUDE_ALL_GCS
void oop_follow_contents(oop obj);
PARALLEL_GC_DECLS
};
#endif // SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_HPP
C:\hotspot-69087d08d473\src\share\vm/oops/instanceKlass.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/verifier.hpp"
#include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
#include "gc_implementation/shared/markSweep.inline.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "interpreter/oopMapCache.hpp"
#include "interpreter/rewriter.hpp"
#include "jvmtifiles/jvmti.h"
#include "memory/genOopClosures.inline.hpp"
#include "memory/heapInspection.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/oopFactory.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/instanceClassLoaderKlass.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/instanceOop.hpp"
#include "oops/klass.inline.hpp"
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
#include "prims/jvmtiThreadState.hpp"
#include "prims/methodComparator.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "runtime/thread.inline.hpp"
#include "services/classLoadingService.hpp"
#include "services/threadService.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
#include "gc_implementation/g1/g1RemSet.inline.hpp"
#include "gc_implementation/g1/heapRegionManager.inline.hpp"
#include "gc_implementation/parNew/parOopClosures.inline.hpp"
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.inline.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
#include "oops/oop.pcgc.inline.hpp"
#endif // INCLUDE_ALL_GCS
#ifdef COMPILER1
#include "c1/c1_Compiler.hpp"
#endif
#if INCLUDE_JFR
#include "jfr/jfrEvents.hpp"
#endif
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
#ifdef DTRACE_ENABLED
#ifndef USDT2
HS_DTRACE_PROBE_DECL4(hotspot, class__initialization__required,
char*, intptr_t, oop, intptr_t);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__recursive,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__concurrent,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__erroneous,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__super__failed,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__clinit,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__error,
char*, intptr_t, oop, intptr_t, int);
HS_DTRACE_PROBE_DECL5(hotspot, class__initialization__end,
char*, intptr_t, oop, intptr_t, int);
#define DTRACE_CLASSINIT_PROBE(type, clss, thread_type) \
{ \
char* data = NULL; \
int len = 0; \
Symbol* name = (clss)->name(); \
if (name != NULL) { \
data = (char*)name->bytes(); \
len = name->utf8_length(); \
} \
HS_DTRACE_PROBE4(hotspot, class__initialization__##type, \
data, len, (void *)(clss)->class_loader(), thread_type); \
}
#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \
{ \
char* data = NULL; \
int len = 0; \
Symbol* name = (clss)->name(); \
if (name != NULL) { \
data = (char*)name->bytes(); \
len = name->utf8_length(); \
} \
HS_DTRACE_PROBE5(hotspot, class__initialization__##type, \
data, len, (void *)(clss)->class_loader(), thread_type, wait); \
}
#else /* USDT2 */
#define HOTSPOT_CLASS_INITIALIZATION_required HOTSPOT_CLASS_INITIALIZATION_REQUIRED
#define HOTSPOT_CLASS_INITIALIZATION_recursive HOTSPOT_CLASS_INITIALIZATION_RECURSIVE
#define HOTSPOT_CLASS_INITIALIZATION_concurrent HOTSPOT_CLASS_INITIALIZATION_CONCURRENT
#define HOTSPOT_CLASS_INITIALIZATION_erroneous HOTSPOT_CLASS_INITIALIZATION_ERRONEOUS
#define HOTSPOT_CLASS_INITIALIZATION_super__failed HOTSPOT_CLASS_INITIALIZATION_SUPER_FAILED
#define HOTSPOT_CLASS_INITIALIZATION_clinit HOTSPOT_CLASS_INITIALIZATION_CLINIT
#define HOTSPOT_CLASS_INITIALIZATION_error HOTSPOT_CLASS_INITIALIZATION_ERROR
#define HOTSPOT_CLASS_INITIALIZATION_end HOTSPOT_CLASS_INITIALIZATION_END
#define DTRACE_CLASSINIT_PROBE(type, clss, thread_type) \
{ \
char* data = NULL; \
int len = 0; \
Symbol* name = (clss)->name(); \
if (name != NULL) { \
data = (char*)name->bytes(); \
len = name->utf8_length(); \
} \
HOTSPOT_CLASS_INITIALIZATION_##type( \
data, len, (void *)(clss)->class_loader(), thread_type); \
}
#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait) \
{ \
char* data = NULL; \
int len = 0; \
Symbol* name = (clss)->name(); \
if (name != NULL) { \
data = (char*)name->bytes(); \
len = name->utf8_length(); \
} \
HOTSPOT_CLASS_INITIALIZATION_##type( \
data, len, (void *)(clss)->class_loader(), thread_type, wait); \
}
#endif /* USDT2 */
#else // ndef DTRACE_ENABLED
#define DTRACE_CLASSINIT_PROBE(type, clss, thread_type)
#define DTRACE_CLASSINIT_PROBE_WAIT(type, clss, thread_type, wait)
#endif // ndef DTRACE_ENABLED
volatile int InstanceKlass::_total_instanceKlass_count = 0;
InstanceKlass* InstanceKlass::allocate_instance_klass(
ClassLoaderData* loader_data,
int vtable_len,
int itable_len,
int static_field_size,
int nonstatic_oop_map_size,
ReferenceType rt,
AccessFlags access_flags,
Symbol* name,
Klass* super_klass,
bool is_anonymous,
TRAPS) {
int size = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
access_flags.is_interface(), is_anonymous);
InstanceKlass* ik;
if (rt == REF_NONE) {
if (name == vmSymbols::java_lang_Class()) {
ik = new (loader_data, size, THREAD) InstanceMirrorKlass(
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
access_flags, is_anonymous);
} else if (name == vmSymbols::java_lang_ClassLoader() ||
(SystemDictionary::ClassLoader_klass_loaded() &&
super_klass != NULL &&
super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass()))) {
ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
access_flags, is_anonymous);
} else {
ik = new (loader_data, size, THREAD) InstanceKlass(
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
access_flags, is_anonymous);
}
} else {
ik = new (loader_data, size, THREAD) InstanceRefKlass(
vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt,
access_flags, is_anonymous);
}
if (HAS_PENDING_EXCEPTION) {
return NULL;
}
loader_data->add_class(ik);
Atomic::inc(&_total_instanceKlass_count);
return ik;
}
void InstanceKlass::copy_method_ordering(intArray* m, TRAPS) {
if (m != NULL) {
_method_ordering = MetadataFactory::new_array<int>(class_loader_data(), m->length(), CHECK);
for (int i = 0; i < m->length(); i++) {
_method_ordering->at_put(i, m->at(i));
}
} else {
_method_ordering = Universe::the_empty_int_array();
}
}
Array<int>* InstanceKlass::create_new_default_vtable_indices(int len, TRAPS) {
Array<int>* vtable_indices = MetadataFactory::new_array<int>(class_loader_data(), len, CHECK_NULL);
assert(default_vtable_indices() == NULL, "only create once");
set_default_vtable_indices(vtable_indices);
return vtable_indices;
}
InstanceKlass::InstanceKlass(int vtable_len,
int itable_len,
int static_field_size,
int nonstatic_oop_map_size,
ReferenceType rt,
AccessFlags access_flags,
bool is_anonymous) {
No_Safepoint_Verifier no_safepoint; // until k becomes parsable
int iksize = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size,
access_flags.is_interface(), is_anonymous);
set_vtable_length(vtable_len);
set_itable_length(itable_len);
set_static_field_size(static_field_size);
set_nonstatic_oop_map_size(nonstatic_oop_map_size);
set_access_flags(access_flags);
_misc_flags = 0; // initialize to zero
set_is_anonymous(is_anonymous);
assert(size() == iksize, "wrong size for object");
set_array_klasses(NULL);
set_methods(NULL);
set_method_ordering(NULL);
set_default_methods(NULL);
set_default_vtable_indices(NULL);
set_local_interfaces(NULL);
set_transitive_interfaces(NULL);
init_implementor();
set_fields(NULL, 0);
set_constants(NULL);
set_class_loader_data(NULL);
set_source_file_name_index(0);
set_source_debug_extension(NULL, 0);
set_array_name(NULL);
set_inner_classes(NULL);
set_static_oop_field_count(0);
set_nonstatic_field_size(0);
set_is_marked_dependent(false);
set_has_unloaded_dependent(false);
set_init_state(InstanceKlass::allocated);
set_init_thread(NULL);
set_init_state(allocated);
set_reference_type(rt);
set_oop_map_cache(NULL);
set_jni_ids(NULL);
set_osr_nmethods_head(NULL);
set_breakpoints(NULL);
init_previous_versions();
set_generic_signature_index(0);
release_set_methods_jmethod_ids(NULL);
set_annotations(NULL);
set_jvmti_cached_class_field_map(NULL);
set_initial_method_idnum(0);
_dependencies = NULL;
set_jvmti_cached_class_field_map(NULL);
set_cached_class_file(NULL);
set_initial_method_idnum(0);
set_minor_version(0);
set_major_version(0);
NOT_PRODUCT(_verify_count = 0;)
intptr_t* p = (intptr_t*)this;
for (int index = InstanceKlass::header_size(); index < iksize; index++) {
p[index] = NULL_WORD;
}
set_layout_helper(Klass::instance_layout_helper(0, true));
}
void InstanceKlass::deallocate_methods(ClassLoaderData* loader_data,
Array<Method*>* methods) {
if (methods != NULL && methods != Universe::the_empty_method_array() &&
!methods->is_shared()) {
for (int i = 0; i < methods->length(); i++) {
Method* method = methods->at(i);
if (method == NULL) continue; // maybe null if error processing
assert (!method->on_stack(), "shouldn't be called with methods on stack");
MetadataFactory::free_metadata(loader_data, method);
}
MetadataFactory::free_array<Method*>(loader_data, methods);
}
}
void InstanceKlass::deallocate_interfaces(ClassLoaderData* loader_data,
Klass* super_klass,
Array<Klass*>* local_interfaces,
Array<Klass*>* transitive_interfaces) {
Array<Klass*>* ti = transitive_interfaces;
if (ti != Universe::the_empty_klass_array() && ti != local_interfaces) {
Array<Klass*>* sti = (super_klass == NULL) ? NULL :
InstanceKlass::cast(super_klass)->transitive_interfaces();
if (ti != sti && ti != NULL && !ti->is_shared()) {
MetadataFactory::free_array<Klass*>(loader_data, ti);
}
}
if (local_interfaces != Universe::the_empty_klass_array() &&
local_interfaces != NULL && !local_interfaces->is_shared()) {
MetadataFactory::free_array<Klass*>(loader_data, local_interfaces);
}
}
void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) {
if (java_mirror() != NULL) {
java_lang_Class::set_klass(java_mirror(), NULL);
}
loader_data->remove_class(this);
assert(array_klasses() == NULL, "array classes shouldn't be created for this class yet");
release_C_heap_structures();
deallocate_methods(loader_data, methods());
set_methods(NULL);
if (method_ordering() != NULL &&
method_ordering() != Universe::the_empty_int_array() &&
!method_ordering()->is_shared()) {
MetadataFactory::free_array<int>(loader_data, method_ordering());
}
set_method_ordering(NULL);
if (default_methods() != NULL &&
default_methods() != Universe::the_empty_method_array() &&
!default_methods()->is_shared()) {
MetadataFactory::free_array<Method*>(loader_data, default_methods());
}
set_default_methods(NULL);
if (default_vtable_indices() != NULL &&
!default_vtable_indices()->is_shared()) {
MetadataFactory::free_array<int>(loader_data, default_vtable_indices());
}
set_default_vtable_indices(NULL);
if (secondary_supers() != NULL &&
secondary_supers() != Universe::the_empty_klass_array() &&
secondary_supers() != transitive_interfaces() &&
!secondary_supers()->is_shared()) {
MetadataFactory::free_array<Klass*>(loader_data, secondary_supers());
}
set_secondary_supers(NULL);
deallocate_interfaces(loader_data, super(), local_interfaces(), transitive_interfaces());
set_transitive_interfaces(NULL);
set_local_interfaces(NULL);
if (fields() != NULL && !fields()->is_shared()) {
MetadataFactory::free_array<jushort>(loader_data, fields());
}
set_fields(NULL, 0);
if (constants() != NULL) {
assert (!constants()->on_stack(), "shouldn't be called if anything is onstack");
if (!constants()->is_shared()) {
MetadataFactory::free_metadata(loader_data, constants());
}
SystemDictionary::delete_resolution_error(constants());
set_constants(NULL);
}
if (inner_classes() != NULL &&
inner_classes() != Universe::the_empty_short_array() &&
!inner_classes()->is_shared()) {
MetadataFactory::free_array<jushort>(loader_data, inner_classes());
}
set_inner_classes(NULL);
if (annotations() != NULL && !annotations()->is_shared()) {
MetadataFactory::free_metadata(loader_data, annotations());
}
set_annotations(NULL);
}
bool InstanceKlass::should_be_initialized() const {
return !is_initialized();
}
klassVtable* InstanceKlass::vtable() const {
return new klassVtable(this, start_of_vtable(), vtable_length() / vtableEntry::size());
}
klassItable* InstanceKlass::itable() const {
return new klassItable(instanceKlassHandle(this));
}
void InstanceKlass::eager_initialize(Thread *thread) {
if (!EagerInitialization) return;
if (this->is_not_initialized()) {
if (this->class_initializer() != NULL) return;
Klass* super = this->super();
if (super == NULL) return;
if (!InstanceKlass::cast(super)->is_initialized()) return;
instanceKlassHandle this_oop(thread, this);
eager_initialize_impl(this_oop);
}
}
oop InstanceKlass::protection_domain() const {
return java_lang_Class::protection_domain(java_mirror());
}
objArrayOop InstanceKlass::signers() const {
return java_lang_Class::signers(java_mirror());
}
oop InstanceKlass::init_lock() const {
oop lock = java_lang_Class::init_lock(java_mirror());
OrderAccess::loadload();
assert((oop)lock != NULL || !is_not_initialized(), // initialized or in_error state
"only fully initialized state can have a null lock");
return lock;
}
void InstanceKlass::fence_and_clear_init_lock() {
OrderAccess::storestore();
java_lang_Class::set_init_lock(java_mirror(), NULL);
assert(!is_not_initialized(), "class must be initialized now");
}
void InstanceKlass::eager_initialize_impl(instanceKlassHandle this_oop) {
EXCEPTION_MARK;
oop init_lock = this_oop->init_lock();
ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
if (!this_oop->is_not_initialized()) return; // note: not equivalent to is_initialized()
ClassState old_state = this_oop->init_state();
link_class_impl(this_oop, true, THREAD);
if (HAS_PENDING_EXCEPTION) {
CLEAR_PENDING_EXCEPTION;
if( old_state != this_oop->_init_state )
this_oop->set_init_state (old_state);
} else {
this_oop->set_init_state (fully_initialized);
this_oop->fence_and_clear_init_lock();
if (TraceClassInitialization) {
ResourceMark rm(THREAD);
tty->print_cr("[Initialized %s without side effects]", this_oop->external_name());
}
}
}
void InstanceKlass::initialize(TRAPS) {
if (this->should_be_initialized()) {
HandleMark hm(THREAD);
instanceKlassHandle this_oop(THREAD, this);
initialize_impl(this_oop, CHECK);
} else {
assert(is_initialized(), "sanity check");
}
}
bool InstanceKlass::verify_code(
instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS) {
Verifier::Mode mode =
throw_verifyerror ? Verifier::ThrowException : Verifier::NoException;
return Verifier::verify(this_oop, mode, this_oop->should_verify_class(), THREAD);
}
void InstanceKlass::unlink_class() {
assert(is_linked(), "must be linked");
_init_state = loaded;
}
void InstanceKlass::link_class(TRAPS) {
assert(is_loaded(), "must be loaded");
if (!is_linked()) {
HandleMark hm(THREAD);
instanceKlassHandle this_oop(THREAD, this);
link_class_impl(this_oop, true, CHECK);
}
}
bool InstanceKlass::link_class_or_fail(TRAPS) {
assert(is_loaded(), "must be loaded");
if (!is_linked()) {
HandleMark hm(THREAD);
instanceKlassHandle this_oop(THREAD, this);
link_class_impl(this_oop, false, CHECK_false);
}
return is_linked();
}
bool InstanceKlass::link_class_impl(
instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS) {
if (this_oop->is_in_error_state()) {
ResourceMark rm(THREAD);
THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(),
this_oop->external_name(), false);
}
if (this_oop->is_linked()) {
return true;
}
assert(THREAD->is_Java_thread(), "non-JavaThread in link_class_impl");
JavaThread* jt = (JavaThread*)THREAD;
instanceKlassHandle super(THREAD, this_oop->super());
if (super.not_null()) {
if (super->is_interface()) { // check if super class is an interface
ResourceMark rm(THREAD);
Exceptions::fthrow(
THREAD_AND_LOCATION,
vmSymbols::java_lang_IncompatibleClassChangeError(),
"class %s has interface %s as super class",
this_oop->external_name(),
super->external_name()
);
return false;
}
link_class_impl(super, throw_verifyerror, CHECK_false);
}
Array<Klass*>* interfaces = this_oop->local_interfaces();
int num_interfaces = interfaces->length();
for (int index = 0; index < num_interfaces; index++) {
HandleMark hm(THREAD);
instanceKlassHandle ih(THREAD, interfaces->at(index));
link_class_impl(ih, throw_verifyerror, CHECK_false);
}
if (this_oop->is_linked()) {
return true;
}
PerfClassTraceTime vmtimer(ClassLoader::perf_class_link_time(),
ClassLoader::perf_class_link_selftime(),
ClassLoader::perf_classes_linked(),
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_LINK);
{
oop init_lock = this_oop->init_lock();
ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
if (!this_oop->is_linked()) {
if (!this_oop->is_rewritten()) {
{
PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
ClassLoader::perf_class_verify_selftime(),
ClassLoader::perf_classes_verified(),
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_VERIFY);
bool verify_ok = verify_code(this_oop, throw_verifyerror, THREAD);
if (!verify_ok) {
return false;
}
}
if (this_oop->is_linked()) {
return true;
}
this_oop->rewrite_class(CHECK_false);
} else if (this_oop()->is_shared()) {
ResourceMark rm(THREAD);
char* message_buffer; // res-allocated by check_verification_dependencies
Handle loader = this_oop()->class_loader();
Handle pd = this_oop()->protection_domain();
bool verified = SystemDictionaryShared::check_verification_dependencies(this_oop(),
loader, pd, &message_buffer, THREAD);
if (!verified) {
THROW_MSG_(vmSymbols::java_lang_VerifyError(), message_buffer, false);
}
}
this_oop->link_methods(CHECK_false);
ClassLoaderData * loader_data = this_oop->class_loader_data();
if (!(this_oop()->is_shared() &&
loader_data->is_the_null_class_loader_data())) {
ResourceMark rm(THREAD);
this_oop->vtable()->initialize_vtable(true, CHECK_false);
this_oop->itable()->initialize_itable(true, CHECK_false);
}
#ifdef ASSERT
else {
ResourceMark rm(THREAD);
this_oop->vtable()->verify(tty, true);
}
#endif
this_oop->set_init_state(linked);
if (JvmtiExport::should_post_class_prepare()) {
Thread *thread = THREAD;
assert(thread->is_Java_thread(), "thread->is_Java_thread()");
JvmtiExport::post_class_prepare((JavaThread *) thread, this_oop());
}
}
}
return true;
}
void InstanceKlass::rewrite_class(TRAPS) {
assert(is_loaded(), "must be loaded");
instanceKlassHandle this_oop(THREAD, this);
if (this_oop->is_rewritten()) {
assert(this_oop()->is_shared(), "rewriting an unshared class?");
return;
}
Rewriter::rewrite(this_oop, CHECK);
this_oop->set_rewritten();
}
void InstanceKlass::link_methods(TRAPS) {
int len = methods()->length();
for (int i = len-1; i >= 0; i--) {
methodHandle m(THREAD, methods()->at(i));
m->link_method(m, CHECK);
#ifdef ASSERT
if (StressMethodComparator) {
ResourceMark rm(THREAD);
static int nmc = 0;
for (int j = i; j >= 0 && j >= i-4; j--) {
if ((++nmc % 1000) == 0) tty->print_cr("Have run MethodComparator %d times...", nmc);
bool z = MethodComparator::methods_EMCP(m(),
methods()->at(j));
if (j == i && !z) {
tty->print("MethodComparator FAIL: "); m->print(); m->print_codes();
assert(z, "method must compare equal to itself");
}
}
}
#endif //ASSERT
}
}
void InstanceKlass::initialize_super_interfaces(instanceKlassHandle this_k, TRAPS) {
assert (this_k->has_default_methods(), "caller should have checked this");
for (int i = 0; i < this_k->local_interfaces()->length(); ++i) {
Klass* iface = this_k->local_interfaces()->at(i);
InstanceKlass* ik = InstanceKlass::cast(iface);
if (ik->has_default_methods()) {
ik->initialize_super_interfaces(ik, CHECK);
}
if (ik->should_be_initialized() && ik->declares_default_methods()) {
ik->initialize(CHECK);
}
}
}
void InstanceKlass::initialize_impl(instanceKlassHandle this_oop, TRAPS) {
this_oop->link_class(CHECK);
DTRACE_CLASSINIT_PROBE(required, InstanceKlass::cast(this_oop()), -1);
bool wait = false;
{
oop init_lock = this_oop->init_lock();
ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
Thread *self = THREAD; // it's passed the current thread
while(this_oop->is_being_initialized() && !this_oop->is_reentrant_initialization(self)) {
wait = true;
ol.waitUninterruptibly(CHECK);
}
if (this_oop->is_being_initialized() && this_oop->is_reentrant_initialization(self)) {
DTRACE_CLASSINIT_PROBE_WAIT(recursive, InstanceKlass::cast(this_oop()), -1,wait);
return;
}
if (this_oop->is_initialized()) {
DTRACE_CLASSINIT_PROBE_WAIT(concurrent, InstanceKlass::cast(this_oop()), -1,wait);
return;
}
if (this_oop->is_in_error_state()) {
DTRACE_CLASSINIT_PROBE_WAIT(erroneous, InstanceKlass::cast(this_oop()), -1,wait);
ResourceMark rm(THREAD);
const char* desc = "Could not initialize class ";
const char* className = this_oop->external_name();
size_t msglen = strlen(desc) + strlen(className) + 1;
char* message = NEW_RESOURCE_ARRAY(char, msglen);
if (NULL == message) {
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), className);
} else {
jio_snprintf(message, msglen, "%s%s", desc, className);
THROW_MSG(vmSymbols::java_lang_NoClassDefFoundError(), message);
}
}
this_oop->set_init_state(being_initialized);
this_oop->set_init_thread(self);
}
if (!this_oop->is_interface()) {
Klass* super_klass = this_oop->super();
if (super_klass != NULL && super_klass->should_be_initialized()) {
super_klass->initialize(THREAD);
}
if (!HAS_PENDING_EXCEPTION && this_oop->has_default_methods()) {
this_oop->initialize_super_interfaces(this_oop, THREAD);
}
if (HAS_PENDING_EXCEPTION) {
Handle e(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
{
EXCEPTION_MARK;
this_oop->set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION;
}
DTRACE_CLASSINIT_PROBE_WAIT(super__failed, InstanceKlass::cast(this_oop()), -1,wait);
THROW_OOP(e());
}
}
{
assert(THREAD->is_Java_thread(), "non-JavaThread in initialize_impl");
JavaThread* jt = (JavaThread*)THREAD;
DTRACE_CLASSINIT_PROBE_WAIT(clinit, InstanceKlass::cast(this_oop()), -1,wait);
PerfClassTraceTime timer(ClassLoader::perf_class_init_time(),
ClassLoader::perf_class_init_selftime(),
ClassLoader::perf_classes_inited(),
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_CLINIT);
this_oop->call_class_initializer(THREAD);
}
if (!HAS_PENDING_EXCEPTION) {
this_oop->set_initialization_state_and_notify(fully_initialized, CHECK);
{ ResourceMark rm(THREAD);
debug_only(this_oop->vtable()->verify(tty, true);)
}
}
else {
Handle e(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
{
EXCEPTION_MARK;
this_oop->set_initialization_state_and_notify(initialization_error, THREAD);
CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, class initialization error is thrown below
JvmtiExport::clear_detected_exception((JavaThread*)THREAD);
}
DTRACE_CLASSINIT_PROBE_WAIT(error, InstanceKlass::cast(this_oop()), -1,wait);
if (e->is_a(SystemDictionary::Error_klass())) {
THROW_OOP(e());
} else {
JavaCallArguments args(e);
THROW_ARG(vmSymbols::java_lang_ExceptionInInitializerError(),
vmSymbols::throwable_void_signature(),
&args);
}
}
DTRACE_CLASSINIT_PROBE_WAIT(end, InstanceKlass::cast(this_oop()), -1,wait);
}
void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS) {
instanceKlassHandle kh(THREAD, this);
set_initialization_state_and_notify_impl(kh, state, CHECK);
}
void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_oop, ClassState state, TRAPS) {
oop init_lock = this_oop->init_lock();
if (init_lock != NULL) {
ObjectLocker ol(init_lock, THREAD);
this_oop->set_init_thread(NULL); // reset _init_thread before changing _init_state
this_oop->set_init_state(state);
this_oop->fence_and_clear_init_lock();
ol.notify_all(CHECK);
} else {
assert(init_lock != NULL, "The initialization state should never be set twice");
this_oop->set_init_thread(NULL); // reset _init_thread before changing _init_state
this_oop->set_init_state(state);
}
}
void InstanceKlass::add_implementor(Klass* k) {
assert(Compile_lock->owned_by_self(), "");
assert(is_interface(), "not interface");
if (InstanceKlass::cast(k)->is_interface()) return;
Klass* sk = InstanceKlass::cast(k)->super();
if (sk != NULL && InstanceKlass::cast(sk)->implements_interface(this))
return;
Klass* ik = implementor();
if (ik == NULL) {
set_implementor(k);
} else if (ik != this) {
set_implementor(this);
}
for (int index = 0; index < local_interfaces()->length(); index++) {
InstanceKlass::cast(local_interfaces()->at(index))->add_implementor(k);
}
}
void InstanceKlass::init_implementor() {
if (is_interface()) {
set_implementor(NULL);
}
}
void InstanceKlass::process_interfaces(Thread *thread) {
Klass* this_as_klass_oop = this;
for (int i = local_interfaces()->length() - 1; i >= 0; i--) {
assert(local_interfaces()->at(i)->is_klass(), "must be a klass");
InstanceKlass* interf = InstanceKlass::cast(local_interfaces()->at(i));
assert(interf->is_interface(), "expected interface");
interf->add_implementor(this_as_klass_oop);
}
}
bool InstanceKlass::can_be_primary_super_slow() const {
if (is_interface())
return false;
else
return Klass::can_be_primary_super_slow();
}
GrowableArray<Klass*>* InstanceKlass::compute_secondary_supers(int num_extra_slots) {
InstanceKlass* ik = InstanceKlass::cast(this);
Array<Klass*>* interfaces = ik->transitive_interfaces();
int num_secondaries = num_extra_slots + interfaces->length();
if (num_secondaries == 0) {
set_secondary_supers(Universe::the_empty_klass_array());
return NULL;
} else if (num_extra_slots == 0) {
set_secondary_supers(interfaces);
return NULL;
} else {
GrowableArray<Klass*>* secondaries = new GrowableArray<Klass*>(interfaces->length());
for (int i = 0; i < interfaces->length(); i++) {
secondaries->push(interfaces->at(i));
}
return secondaries;
}
}
bool InstanceKlass::compute_is_subtype_of(Klass* k) {
if (k->is_interface()) {
return implements_interface(k);
} else {
return Klass::compute_is_subtype_of(k);
}
}
bool InstanceKlass::implements_interface(Klass* k) const {
if (this == k) return true;
assert(k->is_interface(), "should be an interface class");
for (int i = 0; i < transitive_interfaces()->length(); i++) {
if (transitive_interfaces()->at(i) == k) {
return true;
}
}
return false;
}
bool InstanceKlass::is_same_or_direct_interface(Klass *k) const {
if (this == k) return true;
assert(k->is_interface(), "should be an interface class");
for (int i = 0; i < local_interfaces()->length(); i++) {
if (local_interfaces()->at(i) == k) {
return true;
}
}
return false;
}
objArrayOop InstanceKlass::allocate_objArray(int n, int length, TRAPS) {
if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
if (length > arrayOopDesc::max_array_length(T_OBJECT)) {
report_java_out_of_memory("Requested array size exceeds VM limit");
JvmtiExport::post_array_size_exhausted();
THROW_OOP_0(Universe::out_of_memory_error_array_size());
}
int size = objArrayOopDesc::object_size(length);
Klass* ak = array_klass(n, CHECK_NULL);
KlassHandle h_ak (THREAD, ak);
objArrayOop o =
(objArrayOop)CollectedHeap::array_allocate(h_ak, size, length, CHECK_NULL);
return o;
}
instanceOop InstanceKlass::register_finalizer(instanceOop i, TRAPS) {
if (TraceFinalizerRegistration) {
tty->print("Registered ");
i->print_value_on(tty);
tty->print_cr(" (" INTPTR_FORMAT ") as finalizable", (address)i);
}
instanceHandle h_i(THREAD, i);
JavaValue result(T_VOID);
JavaCallArguments args(h_i);
methodHandle mh (THREAD, Universe::finalizer_register_method());
JavaCalls::call(&result, mh, &args, CHECK_NULL);
return h_i();
}
instanceOop InstanceKlass::allocate_instance(TRAPS) {
bool has_finalizer_flag = has_finalizer(); // Query before possible GC
int size = size_helper(); // Query before forming handle.
KlassHandle h_k(THREAD, this);
instanceOop i;
i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL);
if (has_finalizer_flag && !RegisterFinalizersAtInit) {
i = register_finalizer(i, CHECK_NULL);
}
return i;
}
void InstanceKlass::check_valid_for_instantiation(bool throwError, TRAPS) {
if (is_interface() || is_abstract()) {
ResourceMark rm(THREAD);
THROW_MSG(throwError ? vmSymbols::java_lang_InstantiationError()
: vmSymbols::java_lang_InstantiationException(), external_name());
}
if (this == SystemDictionary::Class_klass()) {
ResourceMark rm(THREAD);
THROW_MSG(throwError ? vmSymbols::java_lang_IllegalAccessError()
: vmSymbols::java_lang_IllegalAccessException(), external_name());
}
}
Klass* InstanceKlass::array_klass_impl(bool or_null, int n, TRAPS) {
instanceKlassHandle this_oop(THREAD, this);
return array_klass_impl(this_oop, or_null, n, THREAD);
}
Klass* InstanceKlass::array_klass_impl(instanceKlassHandle this_oop, bool or_null, int n, TRAPS) {
if (this_oop->array_klasses() == NULL) {
if (or_null) return NULL;
ResourceMark rm;
JavaThread *jt = (JavaThread *)THREAD;
{
MutexLocker mc(Compile_lock, THREAD); // for vtables
MutexLocker ma(MultiArray_lock, THREAD);
if (this_oop->array_klasses() == NULL) {
Klass* k = ObjArrayKlass::allocate_objArray_klass(this_oop->class_loader_data(), 1, this_oop, CHECK_NULL);
this_oop->set_array_klasses(k);
}
}
}
ObjArrayKlass* oak = (ObjArrayKlass*)this_oop->array_klasses();
if (or_null) {
return oak->array_klass_or_null(n);
}
return oak->array_klass(n, THREAD);
}
Klass* InstanceKlass::array_klass_impl(bool or_null, TRAPS) {
return array_klass_impl(or_null, 1, THREAD);
}
void InstanceKlass::call_class_initializer(TRAPS) {
instanceKlassHandle ik (THREAD, this);
call_class_initializer_impl(ik, THREAD);
}
static int call_class_initializer_impl_counter = 0; // for debugging
Method* InstanceKlass::class_initializer() {
Method* clinit = find_method(
vmSymbols::class_initializer_name(), vmSymbols::void_method_signature());
if (clinit != NULL && clinit->has_valid_initializer_flags()) {
return clinit;
}
return NULL;
}
void InstanceKlass::call_class_initializer_impl(instanceKlassHandle this_oop, TRAPS) {
if (ReplayCompiles &&
(ReplaySuppressInitializers == 1 ||
ReplaySuppressInitializers >= 2 && this_oop->class_loader() != NULL)) {
return;
}
methodHandle h_method(THREAD, this_oop->class_initializer());
assert(!this_oop->is_initialized(), "we cannot initialize twice");
if (TraceClassInitialization) {
tty->print("%d Initializing ", call_class_initializer_impl_counter++);
this_oop->name()->print_value();
tty->print_cr("%s (" INTPTR_FORMAT ")", h_method() == NULL ? "(no method)" : "", (address)this_oop());
}
if (h_method() != NULL) {
JavaCallArguments args; // No arguments
JavaValue result(T_VOID);
JavaCalls::call(&result, h_method, &args, CHECK); // Static call (no args)
}
}
void InstanceKlass::mask_for(methodHandle method, int bci,
InterpreterOopMap* entry_for) {
if (_oop_map_cache == NULL) {
MutexLocker x(OopMapCacheAlloc_lock);
if (_oop_map_cache == NULL) {
OrderAccess::release_store_ptr(&_oop_map_cache, new OopMapCache());
}
}
_oop_map_cache->lookup(method, bci, entry_for);
}
bool InstanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
Symbol* f_name = fs.name();
Symbol* f_sig = fs.signature();
if (f_name == name && f_sig == sig) {
fd->reinitialize(const_cast<InstanceKlass*>(this), fs.index());
return true;
}
}
return false;
}
Klass* InstanceKlass::find_interface_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
const int n = local_interfaces()->length();
for (int i = 0; i < n; i++) {
Klass* intf1 = local_interfaces()->at(i);
assert(intf1->is_interface(), "just checking type");
if (InstanceKlass::cast(intf1)->find_local_field(name, sig, fd)) {
assert(fd->is_static(), "interface field must be static");
return intf1;
}
Klass* intf2 = InstanceKlass::cast(intf1)->find_interface_field(name, sig, fd);
if (intf2 != NULL) return intf2;
}
return NULL;
}
Klass* InstanceKlass::find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
if (find_local_field(name, sig, fd)) {
return const_cast<InstanceKlass*>(this);
}
{ Klass* intf = find_interface_field(name, sig, fd);
if (intf != NULL) return intf;
}
{ Klass* supr = super();
if (supr != NULL) return InstanceKlass::cast(supr)->find_field(name, sig, fd);
}
return NULL;
}
Klass* InstanceKlass::find_field(Symbol* name, Symbol* sig, bool is_static, fieldDescriptor* fd) const {
if (find_local_field(name, sig, fd)) {
if (fd->is_static() == is_static) return const_cast<InstanceKlass*>(this);
}
if (is_static) {
Klass* intf = find_interface_field(name, sig, fd);
if (intf != NULL) return intf;
}
{ Klass* supr = super();
if (supr != NULL) return InstanceKlass::cast(supr)->find_field(name, sig, is_static, fd);
}
return NULL;
}
bool InstanceKlass::find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const {
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
if (fs.offset() == offset) {
fd->reinitialize(const_cast<InstanceKlass*>(this), fs.index());
if (fd->is_static() == is_static) return true;
}
}
return false;
}
bool InstanceKlass::find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const {
Klass* klass = const_cast<InstanceKlass*>(this);
while (klass != NULL) {
if (InstanceKlass::cast(klass)->find_local_field_from_offset(offset, is_static, fd)) {
return true;
}
klass = klass->super();
}
return false;
}
void InstanceKlass::methods_do(void f(Method* method)) {
int len = methods()->length();
for (int index = 0; index < len; index++) {
Method* m = methods()->at(index);
assert(m->is_method(), "must be method");
f(m);
}
}
void InstanceKlass::do_local_static_fields(FieldClosure* cl) {
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) {
fieldDescriptor& fd = fs.field_descriptor();
cl->do_field(&fd);
}
}
}
void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle mirror, TRAPS) {
instanceKlassHandle h_this(THREAD, this);
do_local_static_fields_impl(h_this, f, mirror, CHECK);
}
void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_k,
void f(fieldDescriptor* fd, Handle mirror, TRAPS), Handle mirror, TRAPS) {
for (JavaFieldStream fs(this_k()); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) {
fieldDescriptor& fd = fs.field_descriptor();
f(&fd, mirror, CHECK);
}
}
}
static int compare_fields_by_offset(int* a, int* b) {
return a[0] - b[0];
}
void InstanceKlass::do_nonstatic_fields(FieldClosure* cl) {
InstanceKlass* super = superklass();
if (super != NULL) {
super->do_nonstatic_fields(cl);
}
fieldDescriptor fd;
int length = java_fields_count();
int* fields_sorted = NEW_C_HEAP_ARRAY(int, 2*(length+1), mtClass);
int j = 0;
for (int i = 0; i < length; i += 1) {
fd.reinitialize(this, i);
if (!fd.is_static()) {
fields_sorted[j + 0] = fd.offset();
fields_sorted[j + 1] = i;
j += 2;
}
}
if (j > 0) {
length = j;
qsort(fields_sorted, length/2, 2*sizeof(int), (_sort_Fn)compare_fields_by_offset);
for (int i = 0; i < length; i += 2) {
fd.reinitialize(this, fields_sorted[i + 1]);
assert(!fd.is_static() && fd.offset() == fields_sorted[i], "only nonstatic fields");
cl->do_field(&fd);
}
}
FREE_C_HEAP_ARRAY(int, fields_sorted, mtClass);
}
void InstanceKlass::array_klasses_do(void f(Klass* k, TRAPS), TRAPS) {
if (array_klasses() != NULL)
ArrayKlass::cast(array_klasses())->array_klasses_do(f, THREAD);
}
void InstanceKlass::array_klasses_do(void f(Klass* k)) {
if (array_klasses() != NULL)
ArrayKlass::cast(array_klasses())->array_klasses_do(f);
}
#ifdef ASSERT
static int linear_search(Array<Method*>* methods, Symbol* name, Symbol* signature) {
int len = methods->length();
for (int index = 0; index < len; index++) {
Method* m = methods->at(index);
assert(m->is_method(), "must be method");
if (m->signature() == signature && m->name() == name) {
return index;
}
}
return -1;
}
#endif
static int binary_search(Array<Method*>* methods, Symbol* name) {
int len = methods->length();
int l = 0;
int h = len - 1;
while (l <= h) {
int mid = (l + h) >> 1;
Method* m = methods->at(mid);
assert(m->is_method(), "must be method");
int res = m->name()->fast_compare(name);
if (res == 0) {
return mid;
} else if (res < 0) {
l = mid + 1;
} else {
h = mid - 1;
}
}
return -1;
}
Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
return find_method_impl(name, signature, find_overpass, find_static, find_private);
}
Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode) const {
return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode, private_mode);
}
Method* InstanceKlass::find_instance_method(Array<Method*>* methods,
Symbol* name,
Symbol* signature,
PrivateLookupMode private_mode) {
Method* meth = InstanceKlass::find_method_impl(methods, name, signature,
find_overpass, skip_static, private_mode);
assert(((meth == NULL) || !meth->is_static()), "find_instance_method should have skipped statics");
return meth;
}
Method* InstanceKlass::find_instance_method(Symbol* name,
Symbol* signature,
PrivateLookupMode private_mode) {
return InstanceKlass::find_instance_method(methods(), name, signature, private_mode);
}
Method* InstanceKlass::find_local_method(Symbol* name, Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode) const {
return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode, private_mode);
}
Method* InstanceKlass::find_local_method(Array<Method*>* methods,
Symbol* name, Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode) {
return InstanceKlass::find_method_impl(methods, name, signature, overpass_mode, static_mode, private_mode);
}
Method* InstanceKlass::find_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
return InstanceKlass::find_method_impl(methods, name, signature, find_overpass, find_static, find_private);
}
Method* InstanceKlass::find_method_impl(
Array<Method*>* methods, Symbol* name, Symbol* signature,
OverpassLookupMode overpass_mode, StaticLookupMode static_mode,
PrivateLookupMode private_mode) {
int hit = find_method_index(methods, name, signature, overpass_mode, static_mode, private_mode);
return hit >= 0 ? methods->at(hit): NULL;
}
bool InstanceKlass::method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static, bool skipping_private) {
return ((m->signature() == signature) &&
(!skipping_overpass || !m->is_overpass()) &&
(!skipping_static || !m->is_static()) &&
(!skipping_private || !m->is_private()));
}
int InstanceKlass::find_method_index(
Array<Method*>* methods, Symbol* name, Symbol* signature,
OverpassLookupMode overpass_mode, StaticLookupMode static_mode,
PrivateLookupMode private_mode) {
bool skipping_overpass = (overpass_mode == skip_overpass);
bool skipping_static = (static_mode == skip_static);
bool skipping_private = (private_mode == skip_private);
int hit = binary_search(methods, name);
if (hit != -1) {
Method* m = methods->at(hit);
if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return hit;
int i;
for (i = hit - 1; i >= 0; --i) {
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return i;
}
for (i = hit + 1; i < methods->length(); ++i) {
Method* m = methods->at(i);
assert(m->is_method(), "must be method");
if (m->name() != name) break;
if (method_matches(m, signature, skipping_overpass, skipping_static, skipping_private)) return i;
}
#ifdef ASSERT
int index = (skipping_overpass || skipping_static || skipping_private) ? -1 : linear_search(methods, name, signature);
assert(index == -1, err_msg("binary search should have found entry %d", index));
#endif
}
return -1;
}
int InstanceKlass::find_method_by_name(Symbol* name, int* end) {
return find_method_by_name(methods(), name, end);
}
int InstanceKlass::find_method_by_name(
Array<Method*>* methods, Symbol* name, int* end_ptr) {
assert(end_ptr != NULL, "just checking");
int start = binary_search(methods, name);
int end = start + 1;
if (start != -1) {
while (start - 1 >= 0 && (methods->at(start - 1))->name() == name) --start;
while (end < methods->length() && (methods->at(end))->name() == name) ++end;
return start;
}
return -1;
}
Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const {
OverpassLookupMode overpass_local_mode = overpass_mode;
Klass* klass = const_cast<InstanceKlass*>(this);
while (klass != NULL) {
Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, overpass_local_mode, find_static, find_private);
if (method != NULL) {
return method;
}
klass = InstanceKlass::cast(klass)->super();
overpass_local_mode = skip_overpass; // Always ignore overpass methods in superclasses
}
return NULL;
}
#ifdef ASSERT
bool InstanceKlass::has_redefined_this_or_super() const {
const InstanceKlass* klass = this;
while (klass != NULL) {
if (klass->has_been_redefined()) {
return true;
}
klass = InstanceKlass::cast(klass->super());
}
return false;
}
#endif
Method* InstanceKlass::lookup_method_in_ordered_interfaces(Symbol* name,
Symbol* signature) const {
Method* m = NULL;
if (default_methods() != NULL) {
m = find_method(default_methods(), name, signature);
}
if (m == NULL) {
m = lookup_method_in_all_interfaces(name, signature, find_defaults);
}
return m;
}
Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name,
Symbol* signature,
DefaultsLookupMode defaults_mode) const {
Array<Klass*>* all_ifs = transitive_interfaces();
int num_ifs = all_ifs->length();
InstanceKlass *ik = NULL;
for (int i = 0; i < num_ifs; i++) {
ik = InstanceKlass::cast(all_ifs->at(i));
Method* m = ik->lookup_method(name, signature);
if (m != NULL && m->is_public() && !m->is_static() &&
((defaults_mode != skip_defaults) || !m->is_default_method())) {
return m;
}
}
return NULL;
}
JNIid* InstanceKlass::jni_id_for_impl(instanceKlassHandle this_oop, int offset) {
MutexLocker ml(JfieldIdCreation_lock);
JNIid* probe = this_oop->jni_ids() == NULL ? NULL : this_oop->jni_ids()->find(offset);
if (probe == NULL) {
probe = new JNIid(this_oop(), offset, this_oop->jni_ids());
this_oop->set_jni_ids(probe);
}
return probe;
}
JNIid* InstanceKlass::jni_id_for(int offset) {
JNIid* probe = jni_ids() == NULL ? NULL : jni_ids()->find(offset);
if (probe == NULL) {
probe = jni_id_for_impl(this, offset);
}
return probe;
}
u2 InstanceKlass::enclosing_method_data(int offset) {
Array<jushort>* inner_class_list = inner_classes();
if (inner_class_list == NULL) {
return 0;
}
int length = inner_class_list->length();
if (length % inner_class_next_offset == 0) {
return 0;
} else {
int index = length - enclosing_method_attribute_size;
assert(offset < enclosing_method_attribute_size, "invalid offset");
return inner_class_list->at(index + offset);
}
}
void InstanceKlass::set_enclosing_method_indices(u2 class_index,
u2 method_index) {
Array<jushort>* inner_class_list = inner_classes();
assert (inner_class_list != NULL, "_inner_classes list is not set up");
int length = inner_class_list->length();
if (length % inner_class_next_offset == enclosing_method_attribute_size) {
int index = length - enclosing_method_attribute_size;
inner_class_list->at_put(
index + enclosing_method_class_index_offset, class_index);
inner_class_list->at_put(
index + enclosing_method_method_index_offset, method_index);
}
}
jmethodID InstanceKlass::get_jmethod_id(instanceKlassHandle ik_h, methodHandle method_h) {
size_t idnum = (size_t)method_h->method_idnum();
jmethodID* jmeths = ik_h->methods_jmethod_ids_acquire();
size_t length = 0;
jmethodID id = NULL;
if (jmeths != NULL) {
if (!ik_h->idnum_can_increment()) {
get_jmethod_id_length_value(jmeths, idnum, &length, &id);
} else {
if (Threads::number_of_threads() == 0 ||
SafepointSynchronize::is_at_safepoint()) {
get_jmethod_id_length_value(jmeths, idnum, &length, &id);
} else {
MutexLocker ml(JmethodIdCreation_lock);
get_jmethod_id_length_value(jmeths, idnum, &length, &id);
}
}
}
if (jmeths == NULL || // no cache yet
length <= idnum || // cache is too short
id == NULL) { // cache doesn't contain entry
jmethodID to_dealloc_id = NULL;
jmethodID* to_dealloc_jmeths = NULL;
jmethodID* new_jmeths = NULL;
if (length <= idnum) {
size_t size = MAX2(idnum+1, (size_t)ik_h->idnum_allocated_count());
new_jmeths = NEW_C_HEAP_ARRAY(jmethodID, size+1, mtClass);
memset(new_jmeths, 0, (size+1)*sizeof(jmethodID));
new_jmeths[0] = (jmethodID)size;
}
jmethodID new_id = NULL;
if (method_h->is_old() && !method_h->is_obsolete()) {
Method* current_method = ik_h->method_with_idnum((int)idnum);
assert(current_method != NULL, "old and but not obsolete, so should exist");
new_id = Method::make_jmethod_id(ik_h->class_loader_data(), current_method);
} else {
new_id = Method::make_jmethod_id(ik_h->class_loader_data(), method_h());
}
if (Threads::number_of_threads() == 0 ||
SafepointSynchronize::is_at_safepoint()) {
id = get_jmethod_id_fetch_or_update(ik_h, idnum, new_id, new_jmeths,
&to_dealloc_id, &to_dealloc_jmeths);
} else {
MutexLocker ml(JmethodIdCreation_lock);
id = get_jmethod_id_fetch_or_update(ik_h, idnum, new_id, new_jmeths,
&to_dealloc_id, &to_dealloc_jmeths);
}
if (to_dealloc_jmeths != NULL) {
FreeHeap(to_dealloc_jmeths);
}
if (to_dealloc_id != NULL) {
Method::destroy_jmethod_id(ik_h->class_loader_data(), to_dealloc_id);
}
}
return id;
}
jmethodID InstanceKlass::get_jmethod_id_fetch_or_update(
instanceKlassHandle ik_h, size_t idnum, jmethodID new_id,
jmethodID* new_jmeths, jmethodID* to_dealloc_id_p,
jmethodID** to_dealloc_jmeths_p) {
assert(new_id != NULL, "sanity check");
assert(to_dealloc_id_p != NULL, "sanity check");
assert(to_dealloc_jmeths_p != NULL, "sanity check");
assert(Threads::number_of_threads() == 0 ||
SafepointSynchronize::is_at_safepoint() ||
JmethodIdCreation_lock->owned_by_self(), "sanity check");
jmethodID* jmeths = ik_h->methods_jmethod_ids_acquire();
jmethodID id = NULL;
size_t length = 0;
if (jmeths == NULL || // no cache yet
(length = (size_t)jmeths[0]) <= idnum) { // cache is too short
if (jmeths != NULL) {
for (size_t index = 0; index < length; index++) {
new_jmeths[index+1] = jmeths[index+1];
}
}
ik_h->release_set_methods_jmethod_ids(jmeths = new_jmeths);
} else {
id = jmeths[idnum+1];
}
if (id == NULL) {
id = new_id;
OrderAccess::release_store_ptr(&jmeths[idnum+1], id);
} else {
}
return id;
}
void InstanceKlass::get_jmethod_id_length_value(jmethodID* cache,
size_t idnum, size_t *length_p, jmethodID* id_p) {
assert(cache != NULL, "sanity check");
assert(length_p != NULL, "sanity check");
assert(id_p != NULL, "sanity check");
if (*length_p <= idnum) { // cache is too short
} else {
}
}
jmethodID InstanceKlass::jmethod_id_or_null(Method* method) {
size_t idnum = (size_t)method->method_idnum();
jmethodID* jmeths = methods_jmethod_ids_acquire();
size_t length; // length assigned as debugging crumb
jmethodID id = NULL;
if (jmeths != NULL && // If there is a cache
(length = (size_t)jmeths[0]) > idnum) { // and if it is long enough,
id = jmeths[idnum+1]; // Look up the id (may be NULL)
}
return id;
}
int nmethodBucket::decrement() {
return Atomic::add(-1, (volatile int *)&_count);
}
int InstanceKlass::mark_dependent_nmethods(DepChange& changes) {
assert_locked_or_safepoint(CodeCache_lock);
int found = 0;
nmethodBucket* b = _dependencies;
while (b != NULL) {
nmethod* nm = b->get_nmethod();
if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization() && nm->check_dependency_on(changes)) {
if (TraceDependencies) {
ResourceMark rm;
tty->print_cr("Marked for deoptimization");
tty->print_cr(" context = %s", this->external_name());
changes.print();
nm->print();
nm->print_dependencies();
}
nm->mark_for_deoptimization();
found++;
}
b = b->next();
}
return found;
}
void InstanceKlass::clean_dependent_nmethods() {
assert_locked_or_safepoint(CodeCache_lock);
if (has_unloaded_dependent()) {
nmethodBucket* b = _dependencies;
nmethodBucket* last = NULL;
while (b != NULL) {
assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
nmethodBucket* next = b->next();
if (b->count() == 0) {
if (last == NULL) {
_dependencies = next;
} else {
last->set_next(next);
}
delete b;
} else {
last = b;
}
b = next;
}
set_has_unloaded_dependent(false);
}
#ifdef ASSERT
else {
for (nmethodBucket* b = _dependencies; b != NULL; b = b->next()) {
assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
assert(b->count() != 0, "empty buckets need to be cleaned");
}
}
#endif
}
void InstanceKlass::add_dependent_nmethod(nmethod* nm) {
assert_locked_or_safepoint(CodeCache_lock);
nmethodBucket* b = _dependencies;
nmethodBucket* last = NULL;
while (b != NULL) {
if (nm == b->get_nmethod()) {
b->increment();
return;
}
b = b->next();
}
_dependencies = new nmethodBucket(nm, _dependencies);
}
void InstanceKlass::remove_dependent_nmethod(nmethod* nm, bool delete_immediately) {
assert_locked_or_safepoint(CodeCache_lock);
nmethodBucket* b = _dependencies;
nmethodBucket* last = NULL;
while (b != NULL) {
if (nm == b->get_nmethod()) {
int val = b->decrement();
guarantee(val >= 0, err_msg("Underflow: %d", val));
if (val == 0) {
if (delete_immediately) {
if (last == NULL) {
_dependencies = b->next();
} else {
last->set_next(b->next());
}
delete b;
} else {
set_has_unloaded_dependent(true);
}
}
return;
}
last = b;
b = b->next();
}
#ifdef ASSERT
tty->print_cr("### %s can't find dependent nmethod:", this->external_name());
nm->print();
#endif // ASSERT
ShouldNotReachHere();
}
#ifndef PRODUCT
void InstanceKlass::print_dependent_nmethods(bool verbose) {
nmethodBucket* b = _dependencies;
int idx = 0;
while (b != NULL) {
nmethod* nm = b->get_nmethod();
tty->print("[%d] count=%d { ", idx++, b->count());
if (!verbose) {
nm->print_on(tty, "nmethod");
tty->print_cr(" } ");
} else {
nm->print();
nm->print_dependencies();
tty->print_cr("--- } ");
}
b = b->next();
}
}
bool InstanceKlass::is_dependent_nmethod(nmethod* nm) {
nmethodBucket* b = _dependencies;
while (b != NULL) {
if (nm == b->get_nmethod()) {
#ifdef ASSERT
int count = b->count();
assert(count >= 0, err_msg("count shouldn't be negative: %d", count));
#endif
return true;
}
b = b->next();
}
return false;
}
#endif //PRODUCT
#ifdef ASSERT
template <class T> void assert_is_in(T *p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop o = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(Universe::heap()->is_in(o), "should be in heap");
}
}
template <class T> void assert_is_in_closed_subset(T *p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop o = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(Universe::heap()->is_in_closed_subset(o),
err_msg("should be in closed *p " INTPTR_FORMAT " " INTPTR_FORMAT, (address)p, (address)o));
}
}
template <class T> void assert_is_in_reserved(T *p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop o = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(Universe::heap()->is_in_reserved(o), "should be in reserved");
}
}
template <class T> void assert_nothing(T *p) {}
#else
template <class T> void assert_is_in(T *p) {}
template <class T> void assert_is_in_closed_subset(T *p) {}
template <class T> void assert_is_in_reserved(T *p) {}
template <class T> void assert_nothing(T *p) {}
#endif // ASSERT
#define InstanceKlass_SPECIALIZED_OOP_ITERATE( \
T, start_p, count, do_oop, \
assert_fn) \
{ \
T* p = (T*)(start_p); \
T* const end = p + (count); \
while (p < end) { \
(assert_fn)(p); \
do_oop; \
++p; \
} \
}
#define InstanceKlass_SPECIALIZED_OOP_REVERSE_ITERATE( \
T, start_p, count, do_oop, \
assert_fn) \
{ \
T* const start = (T*)(start_p); \
T* p = start + (count); \
while (start < p) { \
--p; \
(assert_fn)(p); \
do_oop; \
} \
}
#define InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE( \
T, start_p, count, low, high, \
do_oop, assert_fn) \
{ \
T* const l = (T*)(low); \
T* const h = (T*)(high); \
assert(mask_bits((intptr_t)l, sizeof(T)-1) == 0 && \
mask_bits((intptr_t)h, sizeof(T)-1) == 0, \
"bounded region must be properly aligned"); \
T* p = (T*)(start_p); \
T* end = p + (count); \
if (p < l) p = l; \
if (end > h) end = h; \
while (p < end) { \
(assert_fn)(p); \
do_oop; \
++p; \
} \
}
#define InstanceKlass_OOP_MAP_ITERATE(obj, do_oop, assert_fn) \
{ \
is nonstatic_oop_map_size == 1. */ \
OopMapBlock* map = start_of_nonstatic_oop_maps(); \
OopMapBlock* const end_map = map + nonstatic_oop_map_count(); \
if (UseCompressedOops) { \
while (map < end_map) { \
InstanceKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \
obj->obj_field_addr<narrowOop>(map->offset()), map->count(), \
do_oop, assert_fn) \
++map; \
} \
} else { \
while (map < end_map) { \
InstanceKlass_SPECIALIZED_OOP_ITERATE(oop, \
obj->obj_field_addr<oop>(map->offset()), map->count(), \
do_oop, assert_fn) \
++map; \
} \
} \
}
#define InstanceKlass_OOP_MAP_REVERSE_ITERATE(obj, do_oop, assert_fn) \
{ \
OopMapBlock* const start_map = start_of_nonstatic_oop_maps(); \
OopMapBlock* map = start_map + nonstatic_oop_map_count(); \
if (UseCompressedOops) { \
while (start_map < map) { \
--map; \
InstanceKlass_SPECIALIZED_OOP_REVERSE_ITERATE(narrowOop, \
obj->obj_field_addr<narrowOop>(map->offset()), map->count(), \
do_oop, assert_fn) \
} \
} else { \
while (start_map < map) { \
--map; \
InstanceKlass_SPECIALIZED_OOP_REVERSE_ITERATE(oop, \
obj->obj_field_addr<oop>(map->offset()), map->count(), \
do_oop, assert_fn) \
} \
} \
}
#define InstanceKlass_BOUNDED_OOP_MAP_ITERATE(obj, low, high, do_oop, \
assert_fn) \
{ \
nonstatic_oop_map_size == 1, so we accept the \
usually non-existent extra overhead of examining \
all the maps. */ \
OopMapBlock* map = start_of_nonstatic_oop_maps(); \
OopMapBlock* const end_map = map + nonstatic_oop_map_count(); \
if (UseCompressedOops) { \
while (map < end_map) { \
InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \
obj->obj_field_addr<narrowOop>(map->offset()), map->count(), \
low, high, \
do_oop, assert_fn) \
++map; \
} \
} else { \
while (map < end_map) { \
InstanceKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \
obj->obj_field_addr<oop>(map->offset()), map->count(), \
low, high, \
do_oop, assert_fn) \
++map; \
} \
} \
}
void InstanceKlass::oop_follow_contents(oop obj) {
assert(obj != NULL, "can't follow the content of NULL object");
MarkSweep::follow_klass(obj->klass());
InstanceKlass_OOP_MAP_ITERATE( \
obj, \
MarkSweep::mark_and_push(p), \
assert_is_in_closed_subset)
}
#if INCLUDE_ALL_GCS
void InstanceKlass::oop_follow_contents(ParCompactionManager* cm,
oop obj) {
assert(obj != NULL, "can't follow the content of NULL object");
PSParallelCompact::follow_klass(cm, obj->klass());
InstanceKlass_OOP_MAP_ITERATE( \
obj, \
PSParallelCompact::mark_and_push(cm, p), \
assert_is_in)
}
#endif // INCLUDE_ALL_GCS
#define InstanceKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
\
int InstanceKlass::oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::ik);\
if_do_metadata_checked(closure, nv_suffix) { \
closure->do_klass##nv_suffix(obj->klass()); \
} \
InstanceKlass_OOP_MAP_ITERATE( \
obj, \
SpecializationStats:: \
record_do_oop_call##nv_suffix(SpecializationStats::ik); \
(closure)->do_oop##nv_suffix(p), \
assert_is_in_closed_subset) \
return size_helper(); \
}
#if INCLUDE_ALL_GCS
#define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
\
int InstanceKlass::oop_oop_iterate_backwards##nv_suffix(oop obj, \
OopClosureType* closure) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::ik); \
\
assert_should_ignore_metadata(closure, nv_suffix); \
\
InstanceKlass_OOP_MAP_REVERSE_ITERATE( \
obj, \
SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::ik);\
(closure)->do_oop##nv_suffix(p), \
assert_is_in_closed_subset) \
return size_helper(); \
}
#endif // INCLUDE_ALL_GCS
#define InstanceKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \
\
int InstanceKlass::oop_oop_iterate##nv_suffix##_m(oop obj, \
OopClosureType* closure, \
MemRegion mr) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::ik);\
if_do_metadata_checked(closure, nv_suffix) { \
if (mr.contains(obj)) { \
closure->do_klass##nv_suffix(obj->klass()); \
} \
} \
InstanceKlass_BOUNDED_OOP_MAP_ITERATE( \
obj, mr.start(), mr.end(), \
(closure)->do_oop##nv_suffix(p), \
assert_is_in_closed_subset) \
return size_helper(); \
}
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN_m)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN_m)
#if INCLUDE_ALL_GCS
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
#endif // INCLUDE_ALL_GCS
int InstanceKlass::oop_adjust_pointers(oop obj) {
int size = size_helper();
InstanceKlass_OOP_MAP_ITERATE( \
obj, \
MarkSweep::adjust_pointer(p), \
assert_is_in)
return size;
}
#if INCLUDE_ALL_GCS
void InstanceKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
InstanceKlass_OOP_MAP_REVERSE_ITERATE( \
obj, \
if (PSScavenge::should_scavenge(p)) { \
pm->claim_or_forward_depth(p); \
}, \
assert_nothing )
}
int InstanceKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
int size = size_helper();
InstanceKlass_OOP_MAP_ITERATE( \
obj, \
PSParallelCompact::adjust_pointer(p), \
assert_is_in)
return size;
}
#endif // INCLUDE_ALL_GCS
void InstanceKlass::clean_weak_instanceklass_links(BoolObjectClosure* is_alive) {
clean_implementors_list(is_alive);
clean_method_data(is_alive);
clean_dependent_nmethods();
}
void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
assert(class_loader_data()->is_alive(is_alive), "this klass should be live");
if (is_interface()) {
if (ClassUnloading) {
Klass* impl = implementor();
if (impl != NULL) {
if (!impl->is_loader_alive(is_alive)) {
Klass** klass = adr_implementor();
assert(klass != NULL, "null klass");
if (klass != NULL) {
}
}
}
}
}
}
void InstanceKlass::clean_method_data(BoolObjectClosure* is_alive) {
for (int m = 0; m < methods()->length(); m++) {
MethodData* mdo = methods()->at(m)->method_data();
if (mdo != NULL) {
mdo->clean_method_data(is_alive);
}
}
}
static void remove_unshareable_in_class(Klass* k) {
k->remove_unshareable_info();
}
void InstanceKlass::remove_unshareable_info() {
Klass::remove_unshareable_info();
if (is_linked()) {
unlink_class();
}
init_implementor();
constants()->remove_unshareable_info();
for (int i = 0; i < methods()->length(); i++) {
Method* m = methods()->at(i);
m->remove_unshareable_info();
}
array_klasses_do(remove_unshareable_in_class);
}
static void restore_unshareable_in_class(Klass* k, TRAPS) {
k->restore_unshareable_info(ClassLoaderData::the_null_class_loader_data(), Handle(), CHECK);
}
void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
instanceKlassHandle ik(THREAD, this);
Array<Method*>* methods = ik->methods();
int num_methods = methods->length();
for (int index2 = 0; index2 < num_methods; ++index2) {
methodHandle m(THREAD, methods->at(index2));
m->restore_unshareable_info(CHECK);
}
if (JvmtiExport::has_redefined_a_class()) {
ResourceMark rm(THREAD);
ik->vtable()->initialize_vtable(false, CHECK);
ik->itable()->initialize_itable(false, CHECK);
}
ik->constants()->restore_unshareable_info(CHECK);
ik->array_klasses_do(restore_unshareable_in_class, CHECK);
}
bool InstanceKlass::check_sharing_error_state() {
assert(DumpSharedSpaces, "should only be called during dumping");
bool old_state = is_in_error_state();
if (!is_in_error_state()) {
bool bad = false;
for (InstanceKlass* sup = java_super(); sup; sup = sup->java_super()) {
if (sup->is_in_error_state()) {
bad = true;
break;
}
}
if (!bad) {
Array<Klass*>* interfaces = transitive_interfaces();
for (int i = 0; i < interfaces->length(); i++) {
Klass* iface = interfaces->at(i);
if (InstanceKlass::cast(iface)->is_in_error_state()) {
bad = true;
break;
}
}
}
if (bad) {
set_in_error_state();
}
}
return (old_state != is_in_error_state());
}
static void clear_all_breakpoints(Method* m) {
m->clear_all_breakpoints();
}
void InstanceKlass::notify_unload_class(InstanceKlass* ik) {
if (JvmtiExport::should_post_class_unload()) {
JvmtiExport::post_class_unload(ik);
}
ClassLoadingService::notify_class_unloaded(ik);
#if INCLUDE_JFR
assert(ik != NULL, "invariant");
EventClassUnload event;
event.set_unloadedClass(ik);
event.set_definingClassLoader(ik->class_loader_data());
event.commit();
#endif
}
void InstanceKlass::release_C_heap_structures(InstanceKlass* ik) {
ik->release_C_heap_structures();
ik->constants()->release_C_heap_structures();
}
void InstanceKlass::release_C_heap_structures() {
if (_oop_map_cache != NULL) {
delete _oop_map_cache;
_oop_map_cache = NULL;
}
JNIid::deallocate(jni_ids());
set_jni_ids(NULL);
jmethodID* jmeths = methods_jmethod_ids_acquire();
if (jmeths != (jmethodID*)NULL) {
release_set_methods_jmethod_ids(NULL);
FreeHeap(jmeths);
}
{
Mutex* lock_or_null = SafepointSynchronize::is_at_safepoint() ? NULL : MemberNameTable_lock;
MutexLockerEx ml(lock_or_null, Mutex::_no_safepoint_check_flag);
MemberNameTable* mnt = member_names();
if (mnt != NULL) {
delete mnt;
set_member_names(NULL);
}
}
nmethodBucket* b = _dependencies;
_dependencies = NULL;
while (b != NULL) {
nmethodBucket* next = b->next();
delete b;
b = next;
}
if (breakpoints() != 0x0) {
methods_do(clear_all_breakpoints);
assert(breakpoints() == 0x0, "should have cleared breakpoints");
}
if (_cached_class_file != NULL) {
os::free(_cached_class_file, mtClass);
_cached_class_file = NULL;
}
if (_name != NULL) _name->decrement_refcount();
if (_array_name != NULL) _array_name->decrement_refcount();
if (_source_debug_extension != NULL) FREE_C_HEAP_ARRAY(char, _source_debug_extension, mtClass);
assert(_total_instanceKlass_count >= 1, "Sanity check");
Atomic::dec(&_total_instanceKlass_count);
}
void InstanceKlass::set_source_debug_extension(char* array, int length) {
if (array == NULL) {
_source_debug_extension = NULL;
} else {
assert((length+1) > length, "Overflow checking");
char* sde = NEW_C_HEAP_ARRAY(char, (length + 1), mtClass);
for (int i = 0; i < length; i++) {
sde[i] = array[i];
}
sde[length] = '\0';
_source_debug_extension = sde;
}
}
address InstanceKlass::static_field_addr(int offset) {
return (address)(offset + InstanceMirrorKlass::offset_of_static_fields() + cast_from_oop<intptr_t>(java_mirror()));
}
const char* InstanceKlass::signature_name() const {
int hash_len = 0;
char hash_buf[40];
if (is_anonymous()) {
assert(EnableInvokeDynamic, "EnableInvokeDynamic was not set.");
intptr_t hash = (java_mirror() != NULL) ? java_mirror()->identity_hash() : 0;
sprintf(hash_buf, "/" UINTX_FORMAT, (uintx)hash);
hash_len = (int)strlen(hash_buf);
}
const char* src = (const char*) (name()->as_C_string());
const int src_length = (int)strlen(src);
char* dest = NEW_RESOURCE_ARRAY(char, src_length + hash_len + 3);
int dest_index = 0;
dest[dest_index++] = 'L';
for (int src_index = 0; src_index < src_length; ) {
dest[dest_index++] = src[src_index++];
}
for (int hash_index = 0; hash_index < hash_len; ) {
dest[dest_index++] = hash_buf[hash_index++];
}
dest[dest_index++] = ';';
dest[dest_index] = '\0';
return dest;
}
bool InstanceKlass::is_same_class_package(Klass* class2) {
Klass* class1 = this;
oop classloader1 = InstanceKlass::cast(class1)->class_loader();
Symbol* classname1 = class1->name();
if (class2->oop_is_objArray()) {
class2 = ObjArrayKlass::cast(class2)->bottom_klass();
}
oop classloader2;
if (class2->oop_is_instance()) {
classloader2 = InstanceKlass::cast(class2)->class_loader();
} else {
assert(class2->oop_is_typeArray(), "should be type array");
classloader2 = NULL;
}
Symbol* classname2 = class2->name();
return InstanceKlass::is_same_class_package(classloader1, classname1,
classloader2, classname2);
}
bool InstanceKlass::is_same_class_package(oop classloader2, Symbol* classname2) {
Klass* class1 = this;
oop classloader1 = InstanceKlass::cast(class1)->class_loader();
Symbol* classname1 = class1->name();
return InstanceKlass::is_same_class_package(classloader1, classname1,
classloader2, classname2);
}
bool InstanceKlass::is_same_class_package(oop class_loader1, Symbol* class_name1,
oop class_loader2, Symbol* class_name2) {
if (class_loader1 != class_loader2) {
return false;
} else if (class_name1 == class_name2) {
return true; // skip painful bytewise comparison
} else {
ResourceMark rm;
const jbyte *name1 = class_name1->base();
const jbyte *name2 = class_name2->base();
const jbyte *last_slash1 = UTF8::strrchr(name1, class_name1->utf8_length(), '/');
const jbyte *last_slash2 = UTF8::strrchr(name2, class_name2->utf8_length(), '/');
if ((last_slash1 == NULL) || (last_slash2 == NULL)) {
return last_slash1 == last_slash2;
} else {
if (*name1 == '[') {
do {
name1++;
} while (*name1 == '[');
if (*name1 != 'L') {
return false;
}
}
if (*name2 == '[') {
do {
name2++;
} while (*name2 == '[');
if (*name2 != 'L') {
return false;
}
}
int length1 = last_slash1 - name1;
int length2 = last_slash2 - name2;
return UTF8::equal(name1, length1, name2, length2);
}
}
}
bool InstanceKlass::is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS) {
if (super_method->is_private()) {
return false;
}
if ((super_method->is_protected()) ||
(super_method->is_public())) {
return true;
}
assert(super_method->is_package_private(), "must be package private");
return(is_same_class_package(targetclassloader(), targetclassname));
}
Klass* InstanceKlass::compute_enclosing_class_impl(instanceKlassHandle self,
Symbol*& simple_name_result, TRAPS) {
...
}
bool InstanceKlass::is_same_package_member_impl(instanceKlassHandle class1,
Klass* class2_oop, TRAPS) {
if (class2_oop == class1()) return true;
if (!class2_oop->oop_is_instance()) return false;
instanceKlassHandle class2(THREAD, class2_oop);
if (!class1->is_same_class_package(class2->class_loader(), class2->name()))
return false;
instanceKlassHandle outer1 = class1;
for (;;) {
bool ignore_inner_is_member;
Klass* next = outer1->compute_enclosing_class(&ignore_inner_is_member,
CHECK_false);
if (next == NULL) break;
if (next == class2()) return true;
outer1 = instanceKlassHandle(THREAD, next);
}
instanceKlassHandle outer2 = class2;
for (;;) {
bool ignore_inner_is_member;
Klass* next = outer2->compute_enclosing_class(&ignore_inner_is_member,
CHECK_false);
if (next == NULL) break;
if (next == class1()) return true;
if (next == outer1()) return true;
outer2 = instanceKlassHandle(THREAD, next);
}
return false;
}
jint InstanceKlass::compute_modifier_flags(TRAPS) const {
jint access = access_flags().as_int();
instanceKlassHandle ik(THREAD, this);
InnerClassesIterator iter(ik);
for (; !iter.done(); iter.next()) {
int ioff = iter.inner_class_info_index();
if (ioff == 0) continue;
Symbol* inner_name = ik->constants()->klass_name_at(ioff);
if ((ik->name() == inner_name)) {
access = iter.inner_access_flags();
break;
}
}
return (access & (~JVM_ACC_SUPER)) & JVM_ACC_WRITTEN_FLAGS;
}
jint InstanceKlass::jvmti_class_status() const {
jint result = 0;
if (is_linked()) {
result |= JVMTI_CLASS_STATUS_VERIFIED | JVMTI_CLASS_STATUS_PREPARED;
}
if (is_initialized()) {
assert(is_linked(), "Class status is not consistent");
result |= JVMTI_CLASS_STATUS_INITIALIZED;
}
if (is_in_error_state()) {
result |= JVMTI_CLASS_STATUS_ERROR;
}
return result;
}
Method* InstanceKlass::method_at_itable(Klass* holder, int index, TRAPS) {
itableOffsetEntry* ioe = (itableOffsetEntry*)start_of_itable();
int method_table_offset_in_words = ioe->offset()/wordSize;
int nof_interfaces = (method_table_offset_in_words - itable_offset_in_words())
/ itableOffsetEntry::size();
for (int cnt = 0 ; ; cnt ++, ioe ++) {
if (cnt >= nof_interfaces) {
THROW_NULL(vmSymbols::java_lang_IncompatibleClassChangeError());
}
Klass* ik = ioe->interface_klass();
if (ik == holder) break;
}
itableMethodEntry* ime = ioe->first_method_entry(this);
Method* m = ime[index].method();
if (m == NULL) {
THROW_NULL(vmSymbols::java_lang_AbstractMethodError());
}
return m;
}
#if INCLUDE_JVMTI
void InstanceKlass::adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed) {
if (default_methods() != NULL) {
for (int index = 0; index < default_methods()->length(); index ++) {
Method* old_method = default_methods()->at(index);
if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) {
continue; // skip uninteresting entries
}
assert(!old_method->is_deleted(), "default methods may not be deleted");
Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum());
assert(new_method != NULL, "method_with_idnum() should not be NULL");
assert(old_method != new_method, "sanity check");
default_methods()->at_put(index, new_method);
if (RC_TRACE_IN_RANGE(0x00100000, 0x00400000)) {
if (!(*trace_name_printed)) {
RC_TRACE_MESG(("adjust: klassname=%s default methods from name=%s",
external_name(),
old_method->method_holder()->external_name()));
}
RC_TRACE(0x00100000, ("default method update: %s(%s) ",
new_method->name()->as_C_string(),
new_method->signature()->as_C_string()));
}
}
}
}
#endif // INCLUDE_JVMTI
void InstanceKlass::add_osr_nmethod(nmethod* n) {
#ifndef PRODUCT
if (TieredCompilation) {
nmethod * prev = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), n->comp_level(), true);
assert(prev == NULL || !prev->is_in_use(),
"redundunt OSR recompilation detected. memory leak in CodeCache!");
}
#endif
NEEDS_CLEANUP
OsrList_lock->lock_without_safepoint_check();
assert(n->is_osr_method(), "wrong kind of nmethod");
n->set_osr_link(osr_nmethods_head());
set_osr_nmethods_head(n);
if (TieredCompilation) {
Method* m = n->method();
m->set_highest_osr_comp_level(MAX2(m->highest_osr_comp_level(), n->comp_level()));
}
OsrList_lock->unlock();
if (TieredCompilation) {
for (int l = CompLevel_limited_profile; l < n->comp_level(); l++) {
nmethod *inv = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), l, true);
if (inv != NULL && inv->is_in_use()) {
inv->make_not_entrant();
}
}
}
}
void InstanceKlass::remove_osr_nmethod(nmethod* n) {
OsrList_lock->lock_without_safepoint_check();
assert(n->is_osr_method(), "wrong kind of nmethod");
nmethod* last = NULL;
nmethod* cur = osr_nmethods_head();
int max_level = CompLevel_none; // Find the max comp level excluding n
Method* m = n->method();
while(cur != NULL && cur != n) {
if (TieredCompilation && m == cur->method()) {
max_level = MAX2(max_level, cur->comp_level());
}
last = cur;
cur = cur->osr_link();
}
nmethod* next = NULL;
if (cur == n) {
next = cur->osr_link();
if (last == NULL) {
set_osr_nmethods_head(next);
} else {
last->set_osr_link(next);
}
}
n->set_osr_link(NULL);
if (TieredCompilation) {
cur = next;
while (cur != NULL) {
if (m == cur->method()) {
max_level = MAX2(max_level, cur->comp_level());
}
cur = cur->osr_link();
}
m->set_highest_osr_comp_level(max_level);
}
OsrList_lock->unlock();
}
int InstanceKlass::mark_osr_nmethods(const Method* m) {
MutexLockerEx ml(OsrList_lock, Mutex::_no_safepoint_check_flag);
nmethod* osr = osr_nmethods_head();
int found = 0;
while (osr != NULL) {
assert(osr->is_osr_method(), "wrong kind of nmethod found in chain");
if (osr->method() == m) {
osr->mark_for_deoptimization();
found++;
}
osr = osr->osr_link();
}
return found;
}
nmethod* InstanceKlass::lookup_osr_nmethod(const Method* m, int bci, int comp_level, bool match_level) const {
OsrList_lock->lock_without_safepoint_check();
nmethod* osr = osr_nmethods_head();
nmethod* best = NULL;
while (osr != NULL) {
assert(osr->is_osr_method(), "wrong kind of nmethod found in chain");
if (osr->method() == m &&
(bci == InvocationEntryBci || osr->osr_entry_bci() == bci)) {
if (match_level) {
if (osr->comp_level() == comp_level) {
OsrList_lock->unlock();
return osr;
}
} else {
if (best == NULL || (osr->comp_level() > best->comp_level())) {
if (osr->comp_level() == CompLevel_highest_tier) {
OsrList_lock->unlock();
return osr;
}
best = osr;
}
}
}
osr = osr->osr_link();
}
OsrList_lock->unlock();
assert(match_level == false || best == NULL, "shouldn't pick up anything if match_level is set");
if (best != NULL && best->comp_level() >= comp_level) {
return best;
}
return NULL;
}
oop InstanceKlass::add_member_name(Handle mem_name, bool intern) {
jweak mem_name_wref = JNIHandles::make_weak_global(mem_name);
MutexLocker ml(MemberNameTable_lock);
DEBUG_ONLY(No_Safepoint_Verifier nsv);
Method* method = (Method*)java_lang_invoke_MemberName::vmtarget(mem_name());
if (method->is_obsolete()) {
return NULL;
} else if (method->is_old()) {
java_lang_invoke_MemberName::set_vmtarget(mem_name(), method_with_idnum(method->method_idnum()));
}
if (_member_names == NULL) {
_member_names = new (ResourceObj::C_HEAP, mtClass) MemberNameTable(idnum_allocated_count());
}
if (intern) {
return _member_names->find_or_add_member_name(mem_name_wref);
} else {
return _member_names->add_member_name(mem_name_wref);
}
}
#ifndef PRODUCT
#define BULLET " - "
static const char* state_names[] = {
"allocated", "loaded", "linked", "being_initialized", "fully_initialized", "initialization_error"
};
static void print_vtable(intptr_t* start, int len, outputStream* st) {
for (int i = 0; i < len; i++) {
intptr_t e = start[i];
st->print("%d : " INTPTR_FORMAT, i, e);
if (e != 0 && ((Metadata*)e)->is_metaspace_object()) {
st->print(" ");
((Metadata*)e)->print_value_on(st);
}
st->cr();
}
}
void InstanceKlass::print_on(outputStream* st) const {
assert(is_klass(), "must be klass");
Klass::print_on(st);
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"state: "); st->print_cr("%s", state_names[_init_state]);
st->print(BULLET"name: "); name()->print_value_on(st); st->cr();
st->print(BULLET"super: "); super()->print_value_on_maybe_null(st); st->cr();
st->print(BULLET"sub: ");
Klass* sub = subklass();
int n;
for (n = 0; sub != NULL; n++, sub = sub->next_sibling()) {
if (n < MaxSubklassPrintSize) {
sub->print_value_on(st);
st->print(" ");
}
}
if (n >= MaxSubklassPrintSize) st->print("(%d more klasses...)", n - MaxSubklassPrintSize);
st->cr();
if (is_interface()) {
st->print_cr(BULLET"nof implementors: %d", nof_implementors());
if (nof_implementors() == 1) {
st->print_cr(BULLET"implementor: ");
st->print(" ");
implementor()->print_value_on(st);
st->cr();
}
}
st->print(BULLET"arrays: "); array_klasses()->print_value_on_maybe_null(st); st->cr();
st->print(BULLET"methods: "); methods()->print_value_on(st); st->cr();
if (Verbose || WizardMode) {
Array<Method*>* method_array = methods();
for (int i = 0; i < method_array->length(); i++) {
st->print("%d : ", i); method_array->at(i)->print_value(); st->cr();
}
}
st->print(BULLET"method ordering: "); method_ordering()->print_value_on(st); st->cr();
st->print(BULLET"default_methods: "); default_methods()->print_value_on(st); st->cr();
if (Verbose && default_methods() != NULL) {
Array<Method*>* method_array = default_methods();
for (int i = 0; i < method_array->length(); i++) {
st->print("%d : ", i); method_array->at(i)->print_value(); st->cr();
}
}
if (default_vtable_indices() != NULL) {
st->print(BULLET"default vtable indices: "); default_vtable_indices()->print_value_on(st); st->cr();
}
st->print(BULLET"local interfaces: "); local_interfaces()->print_value_on(st); st->cr();
st->print(BULLET"trans. interfaces: "); transitive_interfaces()->print_value_on(st); st->cr();
st->print(BULLET"constants: "); constants()->print_value_on(st); st->cr();
if (class_loader_data() != NULL) {
st->print(BULLET"class loader data: ");
class_loader_data()->print_value_on(st);
st->cr();
}
st->print(BULLET"host class: "); host_klass()->print_value_on_maybe_null(st); st->cr();
if (source_file_name() != NULL) {
st->print(BULLET"source file: ");
source_file_name()->print_value_on(st);
st->cr();
}
if (source_debug_extension() != NULL) {
st->print(BULLET"source debug extension: ");
st->print("%s", source_debug_extension());
st->cr();
}
st->print(BULLET"class annotations: "); class_annotations()->print_value_on(st); st->cr();
st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr();
st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr();
st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr();
{
bool have_pv = false;
for (InstanceKlass* pv_node = _previous_versions;
pv_node != NULL;
pv_node = pv_node->previous_versions()) {
if (!have_pv)
st->print(BULLET"previous version: ");
have_pv = true;
pv_node->constants()->print_value_on(st);
}
if (have_pv) st->cr();
}
if (generic_signature() != NULL) {
st->print(BULLET"generic signature: ");
generic_signature()->print_value_on(st);
st->cr();
}
st->print(BULLET"inner classes: "); inner_classes()->print_value_on(st); st->cr();
st->print(BULLET"java mirror: "); java_mirror()->print_value_on(st); st->cr();
st->print(BULLET"vtable length %d (start addr: " INTPTR_FORMAT ")", vtable_length(), start_of_vtable()); st->cr();
if (vtable_length() > 0 && (Verbose || WizardMode)) print_vtable(start_of_vtable(), vtable_length(), st);
st->print(BULLET"itable length %d (start addr: " INTPTR_FORMAT ")", itable_length(), start_of_itable()); st->cr();
if (itable_length() > 0 && (Verbose || WizardMode)) print_vtable(start_of_itable(), itable_length(), st);
st->print_cr(BULLET"---- static fields (%d words):", static_field_size());
FieldPrinter print_static_field(st);
((InstanceKlass*)this)->do_local_static_fields(&print_static_field);
st->print_cr(BULLET"---- non-static fields (%d words):", nonstatic_field_size());
FieldPrinter print_nonstatic_field(st);
((InstanceKlass*)this)->do_nonstatic_fields(&print_nonstatic_field);
st->print(BULLET"non-static oop maps: ");
OopMapBlock* map = start_of_nonstatic_oop_maps();
OopMapBlock* end_map = map + nonstatic_oop_map_count();
while (map < end_map) {
st->print("%d-%d ", map->offset(), map->offset() + heapOopSize*(map->count() - 1));
map++;
}
st->cr();
}
#endif //PRODUCT
void InstanceKlass::print_value_on(outputStream* st) const {
assert(is_klass(), "must be klass");
if (Verbose || WizardMode) access_flags().print_on(st);
name()->print_value_on(st);
}
#ifndef PRODUCT
void FieldPrinter::do_field(fieldDescriptor* fd) {
_st->print(BULLET);
if (_obj == NULL) {
fd->print_on(_st);
_st->cr();
} else {
fd->print_on_for(_st, _obj);
_st->cr();
}
}
void InstanceKlass::oop_print_on(oop obj, outputStream* st) {
Klass::oop_print_on(obj, st);
if (this == SystemDictionary::String_klass()) {
typeArrayOop value = java_lang_String::value(obj);
juint offset = java_lang_String::offset(obj);
juint length = java_lang_String::length(obj);
if (value != NULL &&
value->is_typeArray() &&
offset <= (juint) value->length() &&
offset + length <= (juint) value->length()) {
st->print(BULLET"string: ");
java_lang_String::print(obj, st);
st->cr();
if (!WizardMode) return; // that is enough
}
}
st->print_cr(BULLET"---- fields (total size %d words):", oop_size(obj));
FieldPrinter print_field(st, obj);
do_nonstatic_fields(&print_field);
if (this == SystemDictionary::Class_klass()) {
st->print(BULLET"signature: ");
java_lang_Class::print_signature(obj, st);
st->cr();
Klass* mirrored_klass = java_lang_Class::as_Klass(obj);
st->print(BULLET"fake entry for mirror: ");
mirrored_klass->print_value_on_maybe_null(st);
st->cr();
Klass* array_klass = java_lang_Class::array_klass(obj);
st->print(BULLET"fake entry for array: ");
array_klass->print_value_on_maybe_null(st);
st->cr();
st->print_cr(BULLET"fake entry for oop_size: %d", java_lang_Class::oop_size(obj));
st->print_cr(BULLET"fake entry for static_oop_field_count: %d", java_lang_Class::static_oop_field_count(obj));
Klass* real_klass = java_lang_Class::as_Klass(obj);
if (real_klass != NULL && real_klass->oop_is_instance()) {
InstanceKlass::cast(real_klass)->do_local_static_fields(&print_field);
}
} else if (this == SystemDictionary::MethodType_klass()) {
st->print(BULLET"signature: ");
java_lang_invoke_MethodType::print_signature(obj, st);
st->cr();
}
}
#endif //PRODUCT
void InstanceKlass::oop_print_value_on(oop obj, outputStream* st) {
st->print("a ");
name()->print_value_on(st);
obj->print_address_on(st);
if (this == SystemDictionary::String_klass()
&& java_lang_String::value(obj) != NULL) {
ResourceMark rm;
int len = java_lang_String::length(obj);
int plen = (len < 24 ? len : 12);
char* str = java_lang_String::as_utf8_string(obj, 0, plen);
st->print(" = \"%s\"", str);
if (len > plen)
st->print("...[%d]", len);
} else if (this == SystemDictionary::Class_klass()) {
Klass* k = java_lang_Class::as_Klass(obj);
st->print(" = ");
if (k != NULL) {
k->print_value_on(st);
} else {
const char* tname = type2name(java_lang_Class::primitive_type(obj));
st->print("%s", tname ? tname : "type?");
}
} else if (this == SystemDictionary::MethodType_klass()) {
st->print(" = ");
java_lang_invoke_MethodType::print_signature(obj, st);
} else if (java_lang_boxing_object::is_instance(obj)) {
st->print(" = ");
java_lang_boxing_object::print(obj, st);
} else if (this == SystemDictionary::LambdaForm_klass()) {
oop vmentry = java_lang_invoke_LambdaForm::vmentry(obj);
if (vmentry != NULL) {
st->print(" => ");
vmentry->print_value_on(st);
}
} else if (this == SystemDictionary::MemberName_klass()) {
Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(obj);
if (vmtarget != NULL) {
st->print(" = ");
vmtarget->print_value_on(st);
} else {
java_lang_invoke_MemberName::clazz(obj)->print_value_on(st);
st->print(".");
java_lang_invoke_MemberName::name(obj)->print_value_on(st);
}
}
}
const char* InstanceKlass::internal_name() const {
return external_name();
}
#if INCLUDE_SERVICES
void InstanceKlass::collect_statistics(KlassSizeStats *sz) const {
Klass::collect_statistics(sz);
sz->_inst_size = HeapWordSize * size_helper();
sz->_vtab_bytes = HeapWordSize * align_object_offset(vtable_length());
sz->_itab_bytes = HeapWordSize * align_object_offset(itable_length());
sz->_nonstatic_oopmap_bytes = HeapWordSize *
((is_interface() || is_anonymous()) ?
align_object_offset(nonstatic_oop_map_size()) :
nonstatic_oop_map_size());
int n = 0;
n += (sz->_methods_array_bytes = sz->count_array(methods()));
n += (sz->_method_ordering_bytes = sz->count_array(method_ordering()));
n += (sz->_local_interfaces_bytes = sz->count_array(local_interfaces()));
n += (sz->_transitive_interfaces_bytes = sz->count_array(transitive_interfaces()));
n += (sz->_fields_bytes = sz->count_array(fields()));
n += (sz->_inner_classes_bytes = sz->count_array(inner_classes()));
sz->_ro_bytes += n;
const ConstantPool* cp = constants();
if (cp) {
cp->collect_statistics(sz);
}
const Annotations* anno = annotations();
if (anno) {
anno->collect_statistics(sz);
}
const Array<Method*>* methods_array = methods();
if (methods()) {
for (int i = 0; i < methods_array->length(); i++) {
Method* method = methods_array->at(i);
if (method) {
sz->_method_count ++;
method->collect_statistics(sz);
}
}
}
}
#endif // INCLUDE_SERVICES
class VerifyFieldClosure: public OopClosure {
protected:
template <class T> void do_oop_work(T* p) {
oop obj = oopDesc::load_decode_heap_oop(p);
if (!obj->is_oop_or_null()) {
tty->print_cr("Failed: " PTR_FORMAT " -> " PTR_FORMAT, p, (address)obj);
Universe::print();
guarantee(false, "boom");
}
}
public:
virtual void do_oop(oop* p) { VerifyFieldClosure::do_oop_work(p); }
virtual void do_oop(narrowOop* p) { VerifyFieldClosure::do_oop_work(p); }
};
void InstanceKlass::verify_on(outputStream* st) {
#ifndef PRODUCT
if (_verify_count == Universe::verify_count()) return;
_verify_count = Universe::verify_count();
#endif
Klass::verify_on(st);
guarantee(class_loader_data()->contains_klass(this),
"this class isn't found in class loader data");
if (is_linked()) {
ResourceMark rm;
vtable()->verify(st);
}
if (subklass_oop() != NULL) {
guarantee(subklass_oop()->is_klass(), "should be klass");
}
Klass* super = this->super();
Klass* sib = next_sibling();
if (sib != NULL) {
if (sib == this) {
fatal(err_msg("subclass points to itself " PTR_FORMAT, sib));
}
guarantee(sib->is_klass(), "should be klass");
guarantee(sib->super() == super, "siblings should have same superklass");
}
Klass* im = implementor();
if (im != NULL) {
guarantee(is_interface(), "only interfaces should have implementor set");
guarantee(im->is_klass(), "should be klass");
guarantee(!im->is_interface() || im == this,
"implementors cannot be interfaces");
}
if (local_interfaces()) {
Array<Klass*>* local_interfaces = this->local_interfaces();
for (int j = 0; j < local_interfaces->length(); j++) {
Klass* e = local_interfaces->at(j);
guarantee(e->is_klass() && e->is_interface(), "invalid local interface");
}
}
if (transitive_interfaces() != NULL) {
Array<Klass*>* transitive_interfaces = this->transitive_interfaces();
for (int j = 0; j < transitive_interfaces->length(); j++) {
Klass* e = transitive_interfaces->at(j);
guarantee(e->is_klass() && e->is_interface(), "invalid transitive interface");
}
}
if (methods() != NULL) {
Array<Method*>* methods = this->methods();
for (int j = 0; j < methods->length(); j++) {
guarantee(methods->at(j)->is_method(), "non-method in methods array");
}
for (int j = 0; j < methods->length() - 1; j++) {
Method* m1 = methods->at(j);
Method* m2 = methods->at(j + 1);
guarantee(m1->name()->fast_compare(m2->name()) <= 0, "methods not sorted correctly");
}
}
if (method_ordering() != NULL) {
Array<int>* method_ordering = this->method_ordering();
int length = method_ordering->length();
if (JvmtiExport::can_maintain_original_method_order() ||
((UseSharedSpaces || DumpSharedSpaces) && length != 0)) {
guarantee(length == methods()->length(), "invalid method ordering length");
jlong sum = 0;
for (int j = 0; j < length; j++) {
int original_index = method_ordering->at(j);
guarantee(original_index >= 0, "invalid method ordering index");
guarantee(original_index < length, "invalid method ordering index");
sum += original_index;
}
guarantee(sum == ((jlong)length*(length-1))/2, "invalid method ordering sum");
} else {
guarantee(length == 0, "invalid method ordering length");
}
}
if (default_methods() != NULL) {
Array<Method*>* methods = this->default_methods();
for (int j = 0; j < methods->length(); j++) {
guarantee(methods->at(j)->is_method(), "non-method in methods array");
}
for (int j = 0; j < methods->length() - 1; j++) {
Method* m1 = methods->at(j);
Method* m2 = methods->at(j + 1);
guarantee(m1->name()->fast_compare(m2->name()) <= 0, "methods not sorted correctly");
}
}
if (jni_ids() != NULL) {
jni_ids()->verify(this);
}
if (array_klasses() != NULL) {
guarantee(array_klasses()->is_klass(), "should be klass");
}
if (constants() != NULL) {
guarantee(constants()->is_constantPool(), "should be constant pool");
}
const Klass* host = host_klass();
if (host != NULL) {
guarantee(host->is_klass(), "should be klass");
}
}
void InstanceKlass::oop_verify_on(oop obj, outputStream* st) {
Klass::oop_verify_on(obj, st);
VerifyFieldClosure blk;
obj->oop_iterate_no_header(&blk);
}
JNIid::JNIid(Klass* holder, int offset, JNIid* next) {
_holder = holder;
_offset = offset;
_next = next;
debug_only(_is_static_field_id = false;)
}
JNIid* JNIid::find(int offset) {
JNIid* current = this;
while (current != NULL) {
if (current->offset() == offset) return current;
current = current->next();
}
return NULL;
}
void JNIid::deallocate(JNIid* current) {
while (current != NULL) {
JNIid* next = current->next();
delete current;
current = next;
}
}
void JNIid::verify(Klass* holder) {
int first_field_offset = InstanceMirrorKlass::offset_of_static_fields();
int end_field_offset;
end_field_offset = first_field_offset + (InstanceKlass::cast(holder)->static_field_size() * wordSize);
JNIid* current = this;
while (current != NULL) {
guarantee(current->holder() == holder, "Invalid klass in JNIid");
#ifdef ASSERT
int o = current->offset();
if (current->is_static_field_id()) {
guarantee(o >= first_field_offset && o < end_field_offset, "Invalid static field offset in JNIid");
}
#endif
current = current->next();
}
}
#ifdef ASSERT
void InstanceKlass::set_init_state(ClassState state) {
bool good_state = is_shared() ? (_init_state <= state)
: (_init_state < state);
assert(good_state || state == allocated, "illegal state transition");
assert(_init_thread == NULL, "should be cleared before state change");
_init_state = (u1)state;
}
#endif
void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
if (ik->previous_versions() != NULL) {
int deleted_count = 0; // leave debugging breadcrumbs
int live_count = 0;
ClassLoaderData* loader_data = ik->class_loader_data();
assert(loader_data != NULL, "should never be null");
RC_TRACE(0x00000200, ("purge: %s: previous versions", ik->external_name()));
InstanceKlass* pv_node = ik->previous_versions();
InstanceKlass* last = ik;
int version = 0;
for (; pv_node != NULL; ) {
ConstantPool* pvcp = pv_node->constants();
assert(pvcp != NULL, "cp ref was unexpectedly cleared");
if (!pvcp->on_stack()) {
pv_node = pv_node->previous_versions();
last->link_previous_versions(pv_node);
deleted_count++;
version++;
continue;
} else {
RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is alive",
pv_node));
assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
live_count++;
}
Array<Method*>* method_refs = pv_node->methods();
if (method_refs != NULL) {
RC_TRACE(0x00000200, ("purge: previous methods length=%d",
method_refs->length()));
for (int j = 0; j < method_refs->length(); j++) {
Method* method = method_refs->at(j);
if (!method->on_stack()) {
if (method->is_running_emcp()) {
method->set_running_emcp(false);
}
} else {
assert (method->is_obsolete() || method->is_running_emcp(),
"emcp method cannot run after emcp bit is cleared");
RC_TRACE(0x00000200,
("purge: %s(%s): prev method @%d in version @%d is alive",
method->name()->as_C_string(),
method->signature()->as_C_string(), j, version));
if (method->method_data() != NULL) {
method->method_data()->clean_weak_method_links();
}
}
}
}
last = pv_node;
pv_node = pv_node->previous_versions();
version++;
}
RC_TRACE(0x00000200,
("purge: previous version stats: live=%d, deleted=%d", live_count,
deleted_count));
}
Array<Method*>* methods = ik->methods();
int num_methods = methods->length();
for (int index2 = 0; index2 < num_methods; ++index2) {
if (methods->at(index2)->method_data() != NULL) {
methods->at(index2)->method_data()->clean_weak_method_links();
}
}
}
void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods,
int emcp_method_count) {
int obsolete_method_count = old_methods->length() - emcp_method_count;
if (emcp_method_count != 0 && obsolete_method_count != 0 &&
_previous_versions != NULL) {
int local_count = 0;
for (int i = 0; i < old_methods->length(); i++) {
Method* old_method = old_methods->at(i);
if (old_method->is_obsolete()) {
Symbol* m_name = old_method->name();
Symbol* m_signature = old_method->signature();
int j = 0;
for (InstanceKlass* prev_version = _previous_versions;
prev_version != NULL;
prev_version = prev_version->previous_versions(), j++) {
Array<Method*>* method_refs = prev_version->methods();
for (int k = 0; k < method_refs->length(); k++) {
Method* method = method_refs->at(k);
if (!method->is_obsolete() &&
method->name() == m_name &&
method->signature() == m_signature) {
RC_TRACE(0x00000400,
("add: %s(%s): flush obsolete method @%d in version @%d",
m_name->as_C_string(), m_signature->as_C_string(), k, j));
method->set_is_obsolete();
break;
}
}
}
if (++local_count >= obsolete_method_count) {
break;
}
}
}
}
}
void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
int emcp_method_count) {
assert(Thread::current()->is_VM_thread(),
"only VMThread can add previous versions");
RC_TRACE(0x00000400, ("adding previous version ref for %s, EMCP_cnt=%d",
scratch_class->external_name(), emcp_method_count));
purge_previous_versions(this);
Array<Method*>* old_methods = scratch_class->methods();
mark_newly_obsolete_methods(old_methods, emcp_method_count);
ConstantPool* cp_ref = scratch_class->constants();
if (!cp_ref->on_stack()) {
RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running"));
return;
}
if (emcp_method_count != 0) {
for (int i = 0; i < old_methods->length(); i++) {
Method* old_method = old_methods->at(i);
if (!old_method->is_obsolete() && old_method->on_stack()) {
old_method->set_running_emcp(true);
RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT,
old_method->name_and_sig_as_C_string(), old_method));
} else if (!old_method->is_obsolete()) {
RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT,
old_method->name_and_sig_as_C_string(), old_method));
}
}
}
RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack"));
assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
scratch_class->link_previous_versions(previous_versions());
link_previous_versions(scratch_class());
} // end add_previous_version()
Method* InstanceKlass::method_with_idnum(int idnum) {
Method* m = NULL;
if (idnum < methods()->length()) {
m = methods()->at(idnum);
}
if (m == NULL || m->method_idnum() != idnum) {
for (int index = 0; index < methods()->length(); ++index) {
m = methods()->at(index);
if (m->method_idnum() == idnum) {
return m;
}
}
return NULL;
}
return m;
}
Method* InstanceKlass::method_with_orig_idnum(int idnum) {
if (idnum >= methods()->length()) {
return NULL;
}
Method* m = methods()->at(idnum);
if (m != NULL && m->orig_method_idnum() == idnum) {
return m;
}
for (int index = 0; index < methods()->length(); ++index) {
m = methods()->at(index);
if (m->orig_method_idnum() == idnum) {
return m;
}
}
return NULL;
}
Method* InstanceKlass::method_with_orig_idnum(int idnum, int version) {
InstanceKlass* holder = get_klass_version(version);
if (holder == NULL) {
return NULL; // The version of klass is gone, no method is found
}
Method* method = holder->method_with_orig_idnum(idnum);
return method;
}
jint InstanceKlass::get_cached_class_file_len() {
return VM_RedefineClasses::get_cached_class_file_len(_cached_class_file);
}
unsigned char * InstanceKlass::get_cached_class_file_bytes() {
return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
}
C:\hotspot-69087d08d473\src\share\vm/oops/instanceKlass.hpp
#ifndef SHARE_VM_OOPS_INSTANCEKLASS_HPP
#define SHARE_VM_OOPS_INSTANCEKLASS_HPP
#include "classfile/classLoaderData.hpp"
#include "memory/referenceType.hpp"
#include "oops/annotations.hpp"
#include "oops/constMethod.hpp"
#include "oops/fieldInfo.hpp"
#include "oops/instanceOop.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/atomic.hpp"
#include "runtime/handles.hpp"
#include "runtime/os.hpp"
#include "utilities/accessFlags.hpp"
#include "utilities/bitMap.inline.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrKlassExtension.hpp"
#endif
class SuperTypeClosure;
class JNIid;
class jniIdMapBase;
class BreakpointInfo;
class fieldDescriptor;
class DepChange;
class nmethodBucket;
class JvmtiCachedClassFieldMap;
class MemberNameTable;
class FieldClosure: public StackObj {
public:
virtual void do_field(fieldDescriptor* fd) = 0;
};
#ifndef PRODUCT
class FieldPrinter: public FieldClosure {
oop _obj;
outputStream* _st;
public:
FieldPrinter(outputStream* st, oop obj = NULL) : _obj(obj), _st(st) {}
void do_field(fieldDescriptor* fd);
};
#endif // !PRODUCT
class OopMapBlock VALUE_OBJ_CLASS_SPEC {
public:
int offset() const { return _offset; }
void set_offset(int offset) { _offset = offset; }
uint count() const { return _count; }
void set_count(uint count) { _count = count; }
static const int size_in_words() {
return align_size_up(int(sizeof(OopMapBlock)), HeapWordSize) >>
LogHeapWordSize;
}
private:
int _offset;
uint _count;
};
struct JvmtiCachedClassFileData;
class InstanceKlass: public Klass {
friend class VMStructs;
friend class ClassFileParser;
friend class CompileReplay;
protected:
InstanceKlass(int vtable_len,
int itable_len,
int static_field_size,
int nonstatic_oop_map_size,
ReferenceType rt,
AccessFlags access_flags,
bool is_anonymous);
public:
static InstanceKlass* allocate_instance_klass(
ClassLoaderData* loader_data,
int vtable_len,
int itable_len,
int static_field_size,
int nonstatic_oop_map_size,
ReferenceType rt,
AccessFlags access_flags,
Symbol* name,
Klass* super_klass,
bool is_anonymous,
TRAPS);
InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
enum ClassState {
allocated, // allocated (but not yet linked)
loaded, // loaded and inserted in class hierarchy (but not linked yet)
linked, // successfully linked/verified (but not initialized yet)
being_initialized, // currently running class initializer
fully_initialized, // initialized (successfull final state)
initialization_error // error happened during initialization
};
static int number_of_instance_classes() { return _total_instanceKlass_count; }
private:
static volatile int _total_instanceKlass_count;
protected:
Annotations* _annotations;
Klass* _array_klasses;
ConstantPool* _constants;
Array<jushort>* _inner_classes;
char* _source_debug_extension;
Symbol* _array_name;
int _nonstatic_field_size;
int _static_field_size; // number words used by static fields (oop and non-oop) in this klass
u2 _generic_signature_index;
u2 _source_file_name_index;
u2 _static_oop_field_count;// number of static oop fields in this klass
u2 _java_fields_count; // The number of declared Java fields
int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
bool _is_marked_dependent; // used for marking during flushing and deoptimization
bool _is_being_redefined; // used for locking redefinition
bool _has_unloaded_dependent;
enum {
_misc_rewritten = 1 << 0, // methods rewritten.
_misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops
_misc_should_verify_class = 1 << 2, // allow caching of preverification
_misc_is_anonymous = 1 << 3, // has embedded _host_klass field
_misc_is_contended = 1 << 4, // marked with contended annotation
_misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods
_misc_declares_default_methods = 1 << 6, // directly declares default methods (any access)
_misc_has_been_redefined = 1 << 7 // class has been redefined
};
u2 _misc_flags;
u2 _minor_version; // minor version number of class file
u2 _major_version; // major version number of class file
Thread* _init_thread; // Pointer to current thread doing initialization (to handle recursive initialization)
int _vtable_len; // length of Java vtable (in words)
int _itable_len; // length of Java itable (in words)
OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily)
MemberNameTable* _member_names; // Member names
JNIid* _jni_ids; // First JNI identifier for static fields in this class
jmethodID* _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none
nmethodBucket* _dependencies; // list of dependent nmethods
nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class
BreakpointInfo* _breakpoints; // bpt lists, managed by Method*
InstanceKlass* _previous_versions;
JvmtiCachedClassFileData* _cached_class_file;
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
u1 _init_state; // state of class
u1 _reference_type; // reference type
JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration
NOT_PRODUCT(int _verify_count;) // to avoid redundant verifies
Array<Method*>* _methods;
Array<Method*>* _default_methods;
Array<Klass*>* _local_interfaces;
Array<Klass*>* _transitive_interfaces;
Array<int>* _method_ordering;
Array<int>* _default_vtable_indices;
Array<u2>* _fields;
friend class SystemDictionary;
public:
bool has_nonstatic_fields() const {
return (_misc_flags & _misc_has_nonstatic_fields) != 0;
}
void set_has_nonstatic_fields(bool b) {
if (b) {
_misc_flags |= _misc_has_nonstatic_fields;
} else {
_misc_flags &= ~_misc_has_nonstatic_fields;
}
}
int nonstatic_field_size() const { return _nonstatic_field_size; }
void set_nonstatic_field_size(int size) { _nonstatic_field_size = size; }
int static_field_size() const { return _static_field_size; }
void set_static_field_size(int size) { _static_field_size = size; }
int static_oop_field_count() const { return (int)_static_oop_field_count; }
void set_static_oop_field_count(u2 size) { _static_oop_field_count = size; }
int vtable_length() const { return _vtable_len; }
void set_vtable_length(int len) { _vtable_len = len; }
int itable_length() const { return _itable_len; }
void set_itable_length(int len) { _itable_len = len; }
Klass* array_klasses() const { return _array_klasses; }
void set_array_klasses(Klass* k) { _array_klasses = k; }
Array<Method*>* methods() const { return _methods; }
void set_methods(Array<Method*>* a) { _methods = a; }
Method* method_with_idnum(int idnum);
Method* method_with_orig_idnum(int idnum);
Method* method_with_orig_idnum(int idnum, int version);
Array<int>* method_ordering() const { return _method_ordering; }
void set_method_ordering(Array<int>* m) { _method_ordering = m; }
void copy_method_ordering(intArray* m, TRAPS);
Array<Method*>* default_methods() const { return _default_methods; }
void set_default_methods(Array<Method*>* a) { _default_methods = a; }
Array<int>* default_vtable_indices() const { return _default_vtable_indices; }
void set_default_vtable_indices(Array<int>* v) { _default_vtable_indices = v; }
Array<int>* create_new_default_vtable_indices(int len, TRAPS);
Array<Klass*>* local_interfaces() const { return _local_interfaces; }
void set_local_interfaces(Array<Klass*>* a) {
guarantee(_local_interfaces == NULL || a == NULL, "Just checking");
_local_interfaces = a; }
Array<Klass*>* transitive_interfaces() const { return _transitive_interfaces; }
void set_transitive_interfaces(Array<Klass*>* a) {
guarantee(_transitive_interfaces == NULL || a == NULL, "Just checking");
_transitive_interfaces = a;
}
private:
friend class fieldDescriptor;
FieldInfo* field(int index) const { return FieldInfo::from_field_array(_fields, index); }
public:
int field_offset (int index) const { return field(index)->offset(); }
int field_access_flags(int index) const { return field(index)->access_flags(); }
Symbol* field_name (int index) const { return field(index)->name(constants()); }
Symbol* field_signature (int index) const { return field(index)->signature(constants()); }
int java_fields_count() const { return (int)_java_fields_count; }
Array<u2>* fields() const { return _fields; }
void set_fields(Array<u2>* f, u2 java_fields_count) {
guarantee(_fields == NULL || f == NULL, "Just checking");
_fields = f;
_java_fields_count = java_fields_count;
}
Array<u2>* inner_classes() const { return _inner_classes; }
void set_inner_classes(Array<u2>* f) { _inner_classes = f; }
enum InnerClassAttributeOffset {
inner_class_inner_class_info_offset = 0,
inner_class_outer_class_info_offset = 1,
inner_class_inner_name_offset = 2,
inner_class_access_flags_offset = 3,
inner_class_next_offset = 4
};
enum EnclosingMethodAttributeOffset {
enclosing_method_class_index_offset = 0,
enclosing_method_method_index_offset = 1,
enclosing_method_attribute_size = 2
};
bool is_override(methodHandle super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
bool is_same_class_package(Klass* class2);
bool is_same_class_package(oop classloader2, Symbol* classname2);
static bool is_same_class_package(oop class_loader1, Symbol* class_name1, oop class_loader2, Symbol* class_name2);
Klass* compute_enclosing_class(bool* inner_is_member, TRAPS) {
instanceKlassHandle self(THREAD, this);
return compute_enclosing_class_impl(self, inner_is_member, THREAD);
}
static Klass* compute_enclosing_class_impl(instanceKlassHandle self,
bool* inner_is_member, TRAPS);
bool is_same_package_member(Klass* class2, TRAPS) {
instanceKlassHandle self(THREAD, this);
return is_same_package_member_impl(self, class2, THREAD);
}
static bool is_same_package_member_impl(instanceKlassHandle self,
Klass* class2, TRAPS);
bool is_loaded() const { return _init_state >= loaded; }
bool is_linked() const { return _init_state >= linked; }
bool is_initialized() const { return _init_state == fully_initialized; }
bool is_not_initialized() const { return _init_state < being_initialized; }
bool is_being_initialized() const { return _init_state == being_initialized; }
bool is_in_error_state() const { return _init_state == initialization_error; }
bool is_reentrant_initialization(Thread *thread) { return thread == _init_thread; }
ClassState init_state() { return (ClassState)_init_state; }
bool is_rewritten() const { return (_misc_flags & _misc_rewritten) != 0; }
bool should_verify_class() const {
return (_misc_flags & _misc_should_verify_class) != 0;
}
void set_should_verify_class(bool value) {
if (value) {
_misc_flags |= _misc_should_verify_class;
} else {
_misc_flags &= ~_misc_should_verify_class;
}
}
bool is_marked_dependent() const { return _is_marked_dependent; }
void set_is_marked_dependent(bool value) { _is_marked_dependent = value; }
bool has_unloaded_dependent() const { return _has_unloaded_dependent; }
void set_has_unloaded_dependent(bool value) { _has_unloaded_dependent = value; }
bool should_be_initialized() const; // means that initialize should be called
void initialize(TRAPS);
void link_class(TRAPS);
bool link_class_or_fail(TRAPS); // returns false on failure
void unlink_class();
void rewrite_class(TRAPS);
void link_methods(TRAPS);
Method* class_initializer();
void eager_initialize(Thread *thread);
ReferenceType reference_type() const { return (ReferenceType)_reference_type; }
void set_reference_type(ReferenceType t) {
assert(t == (u1)t, "overflow");
_reference_type = (u1)t;
}
static ByteSize reference_type_offset() { return in_ByteSize(offset_of(InstanceKlass, _reference_type)); }
bool find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const;
Klass* find_interface_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const;
Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const;
Klass* find_field(Symbol* name, Symbol* sig, bool is_static, fieldDescriptor* fd) const;
bool contains_field_offset(int offset) {
return instanceOopDesc::contains_field_offset(offset, nonstatic_field_size());
}
bool find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
bool find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
Method* find_method(Symbol* name, Symbol* signature) const;
static Method* find_method(Array<Method*>* methods, Symbol* name, Symbol* signature);
Method* find_instance_method(Symbol* name, Symbol* signature,
PrivateLookupMode private_mode);
static Method* find_instance_method(Array<Method*>* methods,
Symbol* name, Symbol* signature,
PrivateLookupMode private_mode);
Method* find_local_method(Symbol* name, Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode) const;
static Method* find_local_method(Array<Method*>* methods,
Symbol* name, Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode);
static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static, bool skipping_private);
static int find_method_index(Array<Method*>* methods,
Symbol* name, Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode);
Method* uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const;
Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, DefaultsLookupMode defaults_mode) const;
Method* lookup_method_in_ordered_interfaces(Symbol* name, Symbol* signature) const;
int find_method_by_name(Symbol* name, int* end);
static int find_method_by_name(Array<Method*>* methods, Symbol* name, int* end);
ConstantPool* constants() const { return _constants; }
void set_constants(ConstantPool* c) { _constants = c; }
oop protection_domain() const;
objArrayOop signers() const;
Klass* host_klass() const {
Klass** hk = (Klass**)adr_host_klass();
if (hk == NULL) {
assert(!is_anonymous(), "Anonymous classes have host klasses");
return NULL;
} else {
assert(*hk != NULL, "host klass should always be set if the address is not null");
assert(is_anonymous(), "Only anonymous classes have host klasses");
return *hk;
}
}
void set_host_klass(Klass* host) {
assert(is_anonymous(), "not anonymous");
Klass** addr = (Klass**)adr_host_klass();
assert(addr != NULL, "no reversed space");
if (addr != NULL) {
}
}
bool has_host_klass() const {
return adr_host_klass() != NULL;
}
bool is_anonymous() const {
return (_misc_flags & _misc_is_anonymous) != 0;
}
void set_is_anonymous(bool value) {
if (value) {
_misc_flags |= _misc_is_anonymous;
} else {
_misc_flags &= ~_misc_is_anonymous;
}
}
oop klass_holder() const {
return is_anonymous() ? java_mirror() : class_loader();
}
bool is_contended() const {
return (_misc_flags & _misc_is_contended) != 0;
}
void set_is_contended(bool value) {
if (value) {
_misc_flags |= _misc_is_contended;
} else {
_misc_flags &= ~_misc_is_contended;
}
}
Symbol* source_file_name() const {
return (_source_file_name_index == 0) ?
(Symbol*)NULL : _constants->symbol_at(_source_file_name_index);
}
u2 source_file_name_index() const {
return _source_file_name_index;
}
void set_source_file_name_index(u2 sourcefile_index) {
_source_file_name_index = sourcefile_index;
}
u2 minor_version() const { return _minor_version; }
void set_minor_version(u2 minor_version) { _minor_version = minor_version; }
u2 major_version() const { return _major_version; }
void set_major_version(u2 major_version) { _major_version = major_version; }
char* source_debug_extension() const { return _source_debug_extension; }
void set_source_debug_extension(char* array, int length);
Symbol* array_name() { return _array_name; }
void set_array_name(Symbol* name) { assert(_array_name == NULL || name == NULL, "name already created"); _array_name = name; }
static int nonstatic_oop_map_size(unsigned int oop_map_count) {
return oop_map_count * OopMapBlock::size_in_words();
}
unsigned int nonstatic_oop_map_count() const {
return _nonstatic_oop_map_size / OopMapBlock::size_in_words();
}
int nonstatic_oop_map_size() const { return _nonstatic_oop_map_size; }
void set_nonstatic_oop_map_size(int words) {
_nonstatic_oop_map_size = words;
}
bool is_being_redefined() const { return _is_being_redefined; }
void set_is_being_redefined(bool value) { _is_being_redefined = value; }
void add_previous_version(instanceKlassHandle ikh, int emcp_method_count);
InstanceKlass* previous_versions() const { return _previous_versions; }
bool has_been_redefined() const {
return (_misc_flags & _misc_has_been_redefined) != 0;
}
void set_has_been_redefined() {
_misc_flags |= _misc_has_been_redefined;
}
void init_previous_versions() {
_previous_versions = NULL;
}
InstanceKlass* get_klass_version(int version) {
for (InstanceKlass* ik = this; ik != NULL; ik = ik->previous_versions()) {
if (ik->constants()->version() == version) {
return ik;
}
}
return NULL;
}
static void purge_previous_versions(InstanceKlass* ik);
void set_cached_class_file(JvmtiCachedClassFileData *data) {
_cached_class_file = data;
}
JvmtiCachedClassFileData * get_cached_class_file() { return _cached_class_file; }
jint get_cached_class_file_len();
unsigned char * get_cached_class_file_bytes();
void set_jvmti_cached_class_field_map(JvmtiCachedClassFieldMap* descriptor) {
_jvmti_cached_class_field_map = descriptor;
}
JvmtiCachedClassFieldMap* jvmti_cached_class_field_map() const {
return _jvmti_cached_class_field_map;
}
bool has_default_methods() const {
return (_misc_flags & _misc_has_default_methods) != 0;
}
void set_has_default_methods(bool b) {
if (b) {
_misc_flags |= _misc_has_default_methods;
} else {
_misc_flags &= ~_misc_has_default_methods;
}
}
bool declares_default_methods() const {
return (_misc_flags & _misc_declares_default_methods) != 0;
}
void set_declares_default_methods(bool b) {
if (b) {
_misc_flags |= _misc_declares_default_methods;
} else {
_misc_flags &= ~_misc_declares_default_methods;
}
}
inline u2 next_method_idnum();
void set_initial_method_idnum(u2 value) { _idnum_allocated_count = value; }
Symbol* generic_signature() const {
return (_generic_signature_index == 0) ?
(Symbol*)NULL : _constants->symbol_at(_generic_signature_index);
}
u2 generic_signature_index() const {
return _generic_signature_index;
}
void set_generic_signature_index(u2 sig_index) {
_generic_signature_index = sig_index;
}
u2 enclosing_method_data(int offset);
u2 enclosing_method_class_index() {
return enclosing_method_data(enclosing_method_class_index_offset);
}
u2 enclosing_method_method_index() {
return enclosing_method_data(enclosing_method_method_index_offset);
}
void set_enclosing_method_indices(u2 class_index,
u2 method_index);
static jmethodID get_jmethod_id(instanceKlassHandle ik_h,
methodHandle method_h);
static jmethodID get_jmethod_id_fetch_or_update(instanceKlassHandle ik_h,
size_t idnum, jmethodID new_id, jmethodID* new_jmeths,
jmethodID* to_dealloc_id_p,
jmethodID** to_dealloc_jmeths_p);
static void get_jmethod_id_length_value(jmethodID* cache, size_t idnum,
size_t *length_p, jmethodID* id_p);
jmethodID jmethod_id_or_null(Method* method);
Annotations* annotations() const { return _annotations; }
void set_annotations(Annotations* anno) { _annotations = anno; }
AnnotationArray* class_annotations() const {
return (_annotations != NULL) ? _annotations->class_annotations() : NULL;
}
Array<AnnotationArray*>* fields_annotations() const {
return (_annotations != NULL) ? _annotations->fields_annotations() : NULL;
}
AnnotationArray* class_type_annotations() const {
return (_annotations != NULL) ? _annotations->class_type_annotations() : NULL;
}
Array<AnnotationArray*>* fields_type_annotations() const {
return (_annotations != NULL) ? _annotations->fields_type_annotations() : NULL;
}
instanceOop allocate_instance(TRAPS);
instanceHandle allocate_instance_handle(TRAPS) { return instanceHandle(THREAD, allocate_instance(THREAD)); }
objArrayOop allocate_objArray(int n, int length, TRAPS);
static instanceOop register_finalizer(instanceOop i, TRAPS);
virtual void check_valid_for_instantiation(bool throwError, TRAPS);
void call_class_initializer(TRAPS);
void set_initialization_state_and_notify(ClassState state, TRAPS);
OopMapCache* oop_map_cache() { return _oop_map_cache; }
void set_oop_map_cache(OopMapCache *cache) { _oop_map_cache = cache; }
void mask_for(methodHandle method, int bci, InterpreterOopMap* entry);
JNIid* jni_ids() { return _jni_ids; }
void set_jni_ids(JNIid* ids) { _jni_ids = ids; }
JNIid* jni_id_for(int offset);
int mark_dependent_nmethods(DepChange& changes);
void add_dependent_nmethod(nmethod* nm);
void remove_dependent_nmethod(nmethod* nm, bool delete_immediately);
nmethod* osr_nmethods_head() const { return _osr_nmethods_head; };
void set_osr_nmethods_head(nmethod* h) { _osr_nmethods_head = h; };
void add_osr_nmethod(nmethod* n);
void remove_osr_nmethod(nmethod* n);
int mark_osr_nmethods(const Method* m);
nmethod* lookup_osr_nmethod(const Method* m, int bci, int level, bool match_level) const;
BreakpointInfo* breakpoints() const { return _breakpoints; };
void set_breakpoints(BreakpointInfo* bps) { _breakpoints = bps; };
static ByteSize init_state_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_state)); }
JFR_ONLY(DEFINE_KLASS_TRACE_ID_OFFSET;)
static ByteSize init_thread_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_thread)); }
bool implements_interface(Klass* k) const;
bool is_same_or_direct_interface(Klass* k) const;
#ifdef ASSERT
bool has_redefined_this_or_super() const;
#endif
Klass* implementor() const
{
Klass** k = adr_implementor();
if (k == NULL) {
return NULL;
} else {
return *k;
}
}
void set_implementor(Klass* k) {
assert(is_interface(), "not interface");
Klass** addr = adr_implementor();
assert(addr != NULL, "null addr");
if (addr != NULL) {
}
}
int nof_implementors() const {
Klass* k = implementor();
if (k == NULL) {
return 0;
} else if (k != this) {
return 1;
} else {
return 2;
}
}
void add_implementor(Klass* k); // k is a new class that implements this interface
void init_implementor(); // initialize
void process_interfaces(Thread *thread);
bool is_leaf_class() const { return _subklass == NULL; }
GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots);
bool compute_is_subtype_of(Klass* k);
bool can_be_primary_super_slow() const;
int oop_size(oop obj) const { return size_helper(); }
bool oop_is_instance_slow() const { return true; }
void do_local_static_fields(FieldClosure* cl);
void do_nonstatic_fields(FieldClosure* cl); // including inherited fields
void do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle, TRAPS);
void methods_do(void f(Method* method));
void array_klasses_do(void f(Klass* k));
void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
bool super_types_do(SuperTypeClosure* blk);
static InstanceKlass* cast(Klass* k) {
assert(k == NULL || k->is_klass(), "must be");
assert(k == NULL || k->oop_is_instance(), "cast to InstanceKlass");
return (InstanceKlass*) k;
}
InstanceKlass* java_super() const {
return (super() == NULL) ? NULL : cast(super());
}
static int header_size() { return align_object_offset(sizeof(InstanceKlass)/HeapWordSize); }
static int size(int vtable_length, int itable_length,
int nonstatic_oop_map_size,
bool is_interface, bool is_anonymous) {
return align_object_size(header_size() +
align_object_offset(vtable_length) +
align_object_offset(itable_length) +
((is_interface || is_anonymous) ?
align_object_offset(nonstatic_oop_map_size) :
nonstatic_oop_map_size) +
(is_interface ? (int)sizeof(Klass*)/HeapWordSize : 0) +
(is_anonymous ? (int)sizeof(Klass*)/HeapWordSize : 0));
}
int size() const { return size(vtable_length(),
itable_length(),
nonstatic_oop_map_size(),
is_interface(),
is_anonymous());
}
#if INCLUDE_SERVICES
virtual void collect_statistics(KlassSizeStats *sz) const;
#endif
static int vtable_start_offset() { return header_size(); }
static int vtable_length_offset() { return offset_of(InstanceKlass, _vtable_len) / HeapWordSize; }
intptr_t* start_of_vtable() const { return ((intptr_t*)this) + vtable_start_offset(); }
intptr_t* start_of_itable() const { return start_of_vtable() + align_object_offset(vtable_length()); }
int itable_offset_in_words() const { return start_of_itable() - (intptr_t*)this; }
intptr_t* end_of_itable() const { return start_of_itable() + itable_length(); }
address static_field_addr(int offset);
OopMapBlock* start_of_nonstatic_oop_maps() const {
return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length()));
}
Klass** end_of_nonstatic_oop_maps() const {
return (Klass**)(start_of_nonstatic_oop_maps() +
nonstatic_oop_map_count());
}
Klass** adr_implementor() const {
if (is_interface()) {
return (Klass**)end_of_nonstatic_oop_maps();
} else {
return NULL;
}
};
Klass** adr_host_klass() const {
if (is_anonymous()) {
Klass** adr_impl = adr_implementor();
if (adr_impl != NULL) {
return adr_impl + 1;
} else {
return end_of_nonstatic_oop_maps();
}
} else {
return NULL;
}
}
int size_helper() const {
return layout_helper_to_size_helper(layout_helper());
}
bool can_be_fastpath_allocated() const {
return !layout_helper_needs_slow_path(layout_helper());
}
klassVtable* vtable() const; // return new klassVtable wrapper
inline Method* method_at_vtable(int index);
klassItable* itable() const; // return new klassItable wrapper
Method* method_at_itable(Klass* holder, int index, TRAPS);
#if INCLUDE_JVMTI
void adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed);
#endif // INCLUDE_JVMTI
void oop_follow_contents(oop obj);
int oop_adjust_pointers(oop obj);
void clean_weak_instanceklass_links(BoolObjectClosure* is_alive);
void clean_implementors_list(BoolObjectClosure* is_alive);
void clean_method_data(BoolObjectClosure* is_alive);
void clean_dependent_nmethods();
void deallocate_contents(ClassLoaderData* loader_data);
static void deallocate_methods(ClassLoaderData* loader_data,
Array<Method*>* methods);
void static deallocate_interfaces(ClassLoaderData* loader_data,
Klass* super_klass,
Array<Klass*>* local_interfaces,
Array<Klass*>* transitive_interfaces);
bool on_stack() const { return _constants->on_stack(); }
static void notify_unload_class(InstanceKlass* ik);
static void release_C_heap_structures(InstanceKlass* ik);
PARALLEL_GC_DECLS
const char* signature_name() const;
int oop_oop_iterate(oop obj, ExtendedOopClosure* blk) {
return oop_oop_iterate_v(obj, blk);
}
int oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) {
return oop_oop_iterate_v_m(obj, blk, mr);
}
#define InstanceKlass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
int oop_oop_iterate##nv_suffix(oop obj, OopClosureType* blk); \
int oop_oop_iterate##nv_suffix##_m(oop obj, OopClosureType* blk, \
MemRegion mr);
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DECL)
#if INCLUDE_ALL_GCS
#define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \
int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk);
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
#endif // INCLUDE_ALL_GCS
u2 idnum_allocated_count() const { return _idnum_allocated_count; }
public:
void set_in_error_state() {
assert(DumpSharedSpaces, "only call this when dumping archive");
_init_state = initialization_error;
}
bool check_sharing_error_state();
private:
#ifdef ASSERT
void set_init_state(ClassState state);
#else
void set_init_state(ClassState state) { _init_state = (u1)state; }
#endif
void set_rewritten() { _misc_flags |= _misc_rewritten; }
void set_init_thread(Thread *thread) { _init_thread = thread; }
bool idnum_can_increment() const { return has_been_redefined(); }
jmethodID* methods_jmethod_ids_acquire() const
{ return (jmethodID*)OrderAccess::load_ptr_acquire(&_methods_jmethod_ids); }
void release_set_methods_jmethod_ids(jmethodID* jmeths)
{ OrderAccess::release_store_ptr(&_methods_jmethod_ids, jmeths); }
public:
oop init_lock() const;
private:
void fence_and_clear_init_lock();
static bool link_class_impl (instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS);
static bool verify_code (instanceKlassHandle this_oop, bool throw_verifyerror, TRAPS);
static void initialize_impl (instanceKlassHandle this_oop, TRAPS);
static void initialize_super_interfaces (instanceKlassHandle this_oop, TRAPS);
static void eager_initialize_impl (instanceKlassHandle this_oop);
static void set_initialization_state_and_notify_impl (instanceKlassHandle this_oop, ClassState state, TRAPS);
static void call_class_initializer_impl (instanceKlassHandle this_oop, TRAPS);
static Klass* array_klass_impl (instanceKlassHandle this_oop, bool or_null, int n, TRAPS);
static void do_local_static_fields_impl (instanceKlassHandle this_oop, void f(fieldDescriptor* fd, Handle, TRAPS), Handle, TRAPS);
static JNIid* jni_id_for_impl (instanceKlassHandle this_oop, int offset);
Klass* array_klass_impl(bool or_null, int n, TRAPS);
Klass* array_klass_impl(bool or_null, TRAPS);
Method* find_method_impl(Symbol* name, Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode) const;
static Method* find_method_impl(Array<Method*>* methods,
Symbol* name, Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode);
void release_C_heap_structures();
void link_previous_versions(InstanceKlass* pv) { _previous_versions = pv; }
void mark_newly_obsolete_methods(Array<Method*>* old_methods, int emcp_method_count);
public:
virtual void remove_unshareable_info();
virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS);
jint compute_modifier_flags(TRAPS) const;
MemberNameTable* member_names() { return _member_names; }
void set_member_names(MemberNameTable* member_names) { _member_names = member_names; }
oop add_member_name(Handle member_name, bool intern);
public:
jint jvmti_class_status() const;
public:
#ifndef PRODUCT
void print_on(outputStream* st) const;
#endif
void print_value_on(outputStream* st) const;
void oop_print_value_on(oop obj, outputStream* st);
#ifndef PRODUCT
void oop_print_on (oop obj, outputStream* st);
void print_dependent_nmethods(bool verbose = false);
bool is_dependent_nmethod(nmethod* nm);
#endif
const char* internal_name() const;
void verify_on(outputStream* st);
void oop_verify_on(oop obj, outputStream* st);
};
inline Method* InstanceKlass::method_at_vtable(int index) {
#ifndef PRODUCT
assert(index >= 0, "valid vtable index");
if (DebugVtables) {
verify_vtable_index(index);
}
#endif
vtableEntry* ve = (vtableEntry*)start_of_vtable();
return ve[index].method();
}
inline u2 InstanceKlass::next_method_idnum() {
if (_idnum_allocated_count == ConstMethod::MAX_IDNUM) {
return ConstMethod::UNSET_IDNUM; // no more ids available
} else {
return _idnum_allocated_count++;
}
}
class JNIid: public CHeapObj<mtClass> {
friend class VMStructs;
private:
Klass* _holder;
JNIid* _next;
int _offset;
#ifdef ASSERT
bool _is_static_field_id;
#endif
public:
Klass* holder() const { return _holder; }
int offset() const { return _offset; }
JNIid* next() { return _next; }
JNIid(Klass* holder, int offset, JNIid* next);
JNIid* find(int offset);
bool find_local_field(fieldDescriptor* fd) {
return InstanceKlass::cast(holder())->find_local_field_from_offset(offset(), true, fd);
}
static void deallocate(JNIid* id);
#ifdef ASSERT
bool is_static_field_id() const { return _is_static_field_id; }
void set_is_static_field_id() { _is_static_field_id = true; }
#endif
void verify(Klass* holder);
};
class nmethodBucket: public CHeapObj<mtClass> {
friend class VMStructs;
private:
nmethod* _nmethod;
int _count;
nmethodBucket* _next;
public:
nmethodBucket(nmethod* nmethod, nmethodBucket* next) {
_nmethod = nmethod;
_next = next;
_count = 1;
}
int count() { return _count; }
int increment() { _count += 1; return _count; }
int decrement();
nmethodBucket* next() { return _next; }
void set_next(nmethodBucket* b) { _next = b; }
nmethod* get_nmethod() { return _nmethod; }
};
class InnerClassesIterator : public StackObj {
private:
Array<jushort>* _inner_classes;
int _length;
int _idx;
public:
InnerClassesIterator(instanceKlassHandle k) {
_inner_classes = k->inner_classes();
if (k->inner_classes() != NULL) {
_length = _inner_classes->length();
assert((_length % InstanceKlass::inner_class_next_offset == 0 ||
_length % InstanceKlass::inner_class_next_offset == InstanceKlass::enclosing_method_attribute_size),
"just checking");
if (_length % InstanceKlass::inner_class_next_offset == InstanceKlass::enclosing_method_attribute_size) {
_length -= InstanceKlass::enclosing_method_attribute_size;
}
} else {
_length = 0;
}
_idx = 0;
}
int length() const {
return _length;
}
void next() {
_idx += InstanceKlass::inner_class_next_offset;
}
bool done() const {
return (_idx >= _length);
}
u2 inner_class_info_index() const {
return _inner_classes->at(
_idx + InstanceKlass::inner_class_inner_class_info_offset);
}
void set_inner_class_info_index(u2 index) {
_inner_classes->at_put(
_idx + InstanceKlass::inner_class_inner_class_info_offset, index);
}
u2 outer_class_info_index() const {
return _inner_classes->at(
_idx + InstanceKlass::inner_class_outer_class_info_offset);
}
void set_outer_class_info_index(u2 index) {
_inner_classes->at_put(
_idx + InstanceKlass::inner_class_outer_class_info_offset, index);
}
u2 inner_name_index() const {
return _inner_classes->at(
_idx + InstanceKlass::inner_class_inner_name_offset);
}
void set_inner_name_index(u2 index) {
_inner_classes->at_put(
_idx + InstanceKlass::inner_class_inner_name_offset, index);
}
u2 inner_access_flags() const {
return _inner_classes->at(
_idx + InstanceKlass::inner_class_access_flags_offset);
}
};
#endif // SHARE_VM_OOPS_INSTANCEKLASS_HPP
C:\hotspot-69087d08d473\src\share\vm/oops/instanceMirrorKlass.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc_implementation/shared/markSweep.inline.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "memory/genOopClosures.inline.hpp"
#include "memory/iterator.inline.hpp"
#include "memory/oopFactory.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/instanceOop.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/handles.inline.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
#include "gc_implementation/g1/g1RemSet.inline.hpp"
#include "gc_implementation/g1/heapRegionManager.inline.hpp"
#include "gc_implementation/parNew/parOopClosures.inline.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
#include "oops/oop.pcgc.inline.hpp"
#endif // INCLUDE_ALL_GCS
int InstanceMirrorKlass::_offset_of_static_fields = 0;
#ifdef ASSERT
template <class T> void assert_is_in(T *p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop o = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(Universe::heap()->is_in(o), "should be in heap");
}
}
template <class T> void assert_is_in_closed_subset(T *p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop o = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(Universe::heap()->is_in_closed_subset(o), "should be in closed");
}
}
template <class T> void assert_is_in_reserved(T *p) {
T heap_oop = oopDesc::load_heap_oop(p);
if (!oopDesc::is_null(heap_oop)) {
oop o = oopDesc::decode_heap_oop_not_null(heap_oop);
assert(Universe::heap()->is_in_reserved(o), "should be in reserved");
}
}
template <class T> void assert_nothing(T *p) {}
#else
template <class T> void assert_is_in(T *p) {}
template <class T> void assert_is_in_closed_subset(T *p) {}
template <class T> void assert_is_in_reserved(T *p) {}
template <class T> void assert_nothing(T *p) {}
#endif // ASSERT
#define InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE( \
T, start_p, count, do_oop, \
assert_fn) \
{ \
T* p = (T*)(start_p); \
T* const end = p + (count); \
while (p < end) { \
(assert_fn)(p); \
do_oop; \
++p; \
} \
}
#define InstanceMirrorKlass_SPECIALIZED_BOUNDED_OOP_ITERATE( \
T, start_p, count, low, high, \
do_oop, assert_fn) \
{ \
T* const l = (T*)(low); \
T* const h = (T*)(high); \
assert(mask_bits((intptr_t)l, sizeof(T)-1) == 0 && \
mask_bits((intptr_t)h, sizeof(T)-1) == 0, \
"bounded region must be properly aligned"); \
T* p = (T*)(start_p); \
T* end = p + (count); \
if (p < l) p = l; \
if (end > h) end = h; \
while (p < end) { \
(assert_fn)(p); \
do_oop; \
++p; \
} \
}
#define InstanceMirrorKlass_OOP_ITERATE(start_p, count, \
do_oop, assert_fn) \
{ \
if (UseCompressedOops) { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE(narrowOop, \
start_p, count, \
do_oop, assert_fn) \
} else { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE(oop, \
start_p, count, \
do_oop, assert_fn) \
} \
}
#define InstanceMirrorKlass_BOUNDED_OOP_ITERATE(start_p, count, low, high, \
do_oop, assert_fn) \
{ \
if (UseCompressedOops) { \
InstanceMirrorKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(narrowOop, \
start_p, count, \
low, high, \
do_oop, assert_fn) \
} else { \
InstanceMirrorKlass_SPECIALIZED_BOUNDED_OOP_ITERATE(oop, \
start_p, count, \
low, high, \
do_oop, assert_fn) \
} \
}
void InstanceMirrorKlass::oop_follow_contents(oop obj) {
InstanceKlass::oop_follow_contents(obj);
Klass* klass = java_lang_Class::as_Klass(obj);
if (klass != NULL) {
if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
MarkSweep::follow_class_loader(klass->class_loader_data());
} else {
MarkSweep::follow_klass(klass);
}
} else {
assert(java_lang_Class::is_primitive(obj), "Sanity check");
}
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
MarkSweep::mark_and_push(p), \
assert_is_in_closed_subset)
}
#if INCLUDE_ALL_GCS
void InstanceMirrorKlass::oop_follow_contents(ParCompactionManager* cm,
oop obj) {
InstanceKlass::oop_follow_contents(cm, obj);
Klass* klass = java_lang_Class::as_Klass(obj);
if (klass != NULL) {
if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) {
PSParallelCompact::follow_class_loader(cm, klass->class_loader_data());
} else {
PSParallelCompact::follow_klass(cm, klass);
}
} else {
assert(java_lang_Class::is_primitive(obj), "Sanity check");
}
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
PSParallelCompact::mark_and_push(cm, p), \
assert_is_in)
}
#endif // INCLUDE_ALL_GCS
int InstanceMirrorKlass::oop_adjust_pointers(oop obj) {
int size = oop_size(obj);
InstanceKlass::oop_adjust_pointers(obj);
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
MarkSweep::adjust_pointer(p), \
assert_nothing)
return size;
}
#define InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(T, nv_suffix) \
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
(closure)->do_oop##nv_suffix(p), \
assert_is_in_closed_subset) \
return oop_size(obj); \
#define InstanceMirrorKlass_BOUNDED_SPECIALIZED_OOP_ITERATE(T, nv_suffix, mr) \
InstanceMirrorKlass_BOUNDED_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj), \
mr.start(), mr.end(), \
(closure)->do_oop##nv_suffix(p), \
assert_is_in_closed_subset) \
return oop_size(obj); \
#define InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
\
int InstanceMirrorKlass:: \
oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk); \
\
InstanceKlass::oop_oop_iterate##nv_suffix(obj, closure); \
\
if_do_metadata_checked(closure, nv_suffix) { \
Klass* klass = java_lang_Class::as_Klass(obj); \
if (klass != NULL) { \
closure->do_klass##nv_suffix(klass); \
} \
} \
\
if (UseCompressedOops) { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(narrowOop, nv_suffix); \
} else { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(oop, nv_suffix); \
} \
}
#if INCLUDE_ALL_GCS
#define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
\
int InstanceMirrorKlass:: \
oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk); \
\
InstanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \
\
if (UseCompressedOops) { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(narrowOop, nv_suffix); \
} else { \
InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(oop, nv_suffix); \
} \
}
#endif // INCLUDE_ALL_GCS
#define InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \
\
int InstanceMirrorKlass:: \
oop_oop_iterate##nv_suffix##_m(oop obj, \
OopClosureType* closure, \
MemRegion mr) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk); \
\
InstanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr); \
\
if_do_metadata_checked(closure, nv_suffix) { \
if (mr.contains(obj)) { \
Klass* klass = java_lang_Class::as_Klass(obj); \
if (klass != NULL) { \
closure->do_klass##nv_suffix(klass); \
} \
} \
} \
\
if (UseCompressedOops) { \
InstanceMirrorKlass_BOUNDED_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, mr); \
} else { \
InstanceMirrorKlass_BOUNDED_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, mr); \
} \
}
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN)
#if INCLUDE_ALL_GCS
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
#endif // INCLUDE_ALL_GCS
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m)
#if INCLUDE_ALL_GCS
void InstanceMirrorKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
InstanceKlass::oop_push_contents(pm, obj);
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj),\
if (PSScavenge::should_scavenge(p)) { \
pm->claim_or_forward_depth(p); \
}, \
assert_nothing )
}
int InstanceMirrorKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
int size = oop_size(obj);
InstanceKlass::oop_update_pointers(cm, obj);
InstanceMirrorKlass_OOP_ITERATE( \
start_of_static_fields(obj), java_lang_Class::static_oop_field_count(obj),\
PSParallelCompact::adjust_pointer(p), \
assert_nothing)
return size;
}
#endif // INCLUDE_ALL_GCS
int InstanceMirrorKlass::instance_size(KlassHandle k) {
if (k() != NULL && k->oop_is_instance()) {
return align_object_size(size_helper() + InstanceKlass::cast(k())->static_field_size());
}
return size_helper();
}
instanceOop InstanceMirrorKlass::allocate_instance(KlassHandle k, TRAPS) {
int size = instance_size(k);
KlassHandle h_k(THREAD, this);
instanceOop i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL);
java_lang_Class::set_oop_size(i, size);
return i;
}
int InstanceMirrorKlass::oop_size(oop obj) const {
return java_lang_Class::oop_size(obj);
}
int InstanceMirrorKlass::compute_static_oop_field_count(oop obj) {
Klass* k = java_lang_Class::as_Klass(obj);
if (k != NULL && k->oop_is_instance()) {
return InstanceKlass::cast(k)->static_oop_field_count();
}
return 0;
}
C:\hotspot-69087d08d473\src\share\vm/oops/instanceMirrorKlass.hpp
#ifndef SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP
#define SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP
#include "classfile/systemDictionary.hpp"
#include "oops/instanceKlass.hpp"
#include "runtime/handles.hpp"
#include "utilities/macros.hpp"
class InstanceMirrorKlass: public InstanceKlass {
friend class VMStructs;
friend class InstanceKlass;
private:
static int _offset_of_static_fields;
InstanceMirrorKlass(int vtable_len, int itable_len, int static_field_size, int nonstatic_oop_map_size, ReferenceType rt, AccessFlags access_flags, bool is_anonymous)
: InstanceKlass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt, access_flags, is_anonymous) {}
public:
InstanceMirrorKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
bool oop_is_instanceMirror() const { return true; }
static InstanceMirrorKlass* cast(Klass* k) {
assert(k->oop_is_instanceMirror(), "cast to InstanceMirrorKlass");
return (InstanceMirrorKlass*) k;
}
virtual int oop_size(oop obj) const;
static HeapWord* start_of_static_fields(oop obj) {
return (HeapWord*)(cast_from_oop<intptr_t>(obj) + offset_of_static_fields());
}
static void init_offset_of_static_fields() {
assert(_offset_of_static_fields == 0, "once");
_offset_of_static_fields = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->size_helper() << LogHeapWordSize;
}
static int offset_of_static_fields() {
return _offset_of_static_fields;
}
int compute_static_oop_field_count(oop obj);
int instance_size(KlassHandle k);
instanceOop allocate_instance(KlassHandle k, TRAPS);
int oop_adjust_pointers(oop obj);
void oop_follow_contents(oop obj);
PARALLEL_GC_DECLS
int oop_oop_iterate(oop obj, ExtendedOopClosure* blk) {
return oop_oop_iterate_v(obj, blk);
}
int oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) {
return oop_oop_iterate_v_m(obj, blk, mr);
}
#define InstanceMirrorKlass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
int oop_oop_iterate##nv_suffix(oop obj, OopClosureType* blk); \
int oop_oop_iterate##nv_suffix##_m(oop obj, OopClosureType* blk, MemRegion mr);
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL)
#if INCLUDE_ALL_GCS
#define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \
int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk);
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
#endif // INCLUDE_ALL_GCS
};
#endif // SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP
C:\hotspot-69087d08d473\src\share\vm/oops/instanceOop.cpp
#include "precompiled.hpp"
#include "oops/instanceOop.hpp"
C:\hotspot-69087d08d473\src\share\vm/oops/instanceOop.hpp
#ifndef SHARE_VM_OOPS_INSTANCEOOP_HPP
#define SHARE_VM_OOPS_INSTANCEOOP_HPP
#include "oops/oop.hpp"
class instanceOopDesc : public oopDesc {
public:
static int header_size() { return sizeof(instanceOopDesc)/HeapWordSize; }
static int base_offset_in_bytes() {
return (UseCompressedOops && UseCompressedClassPointers) ?
klass_gap_offset_in_bytes() :
sizeof(instanceOopDesc);
}
static bool contains_field_offset(int offset, int nonstatic_field_size) {
int base_in_bytes = base_offset_in_bytes();
return (offset >= base_in_bytes &&
(offset-base_in_bytes) < nonstatic_field_size * heapOopSize);
}
};
#endif // SHARE_VM_OOPS_INSTANCEOOP_HPP
C:\hotspot-69087d08d473\src\share\vm/oops/instanceRefKlass.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc_implementation/shared/markSweep.inline.hpp"
#include "gc_interface/collectedHeap.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "memory/genCollectedHeap.hpp"
#include "memory/genOopClosures.inline.hpp"
#include "oops/instanceRefKlass.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/preserveException.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/g1/g1OopClosures.inline.hpp"
#include "gc_implementation/g1/g1RemSet.inline.hpp"
#include "gc_implementation/g1/heapRegionManager.inline.hpp"
#include "gc_implementation/parNew/parOopClosures.inline.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.inline.hpp"
#include "oops/oop.pcgc.inline.hpp"
#endif // INCLUDE_ALL_GCS
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
template <class T>
void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) {
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
T heap_oop = oopDesc::load_heap_oop(referent_addr);
debug_only(
if(TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr("InstanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (void *)obj);
}
)
if (!oopDesc::is_null(heap_oop)) {
oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);
if (!referent->is_gc_marked() &&
MarkSweep::ref_processor()->discover_reference(obj, ref->reference_type())) {
ref->InstanceKlass::oop_follow_contents(obj);
debug_only(
if(TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr(" Non NULL enqueued " INTPTR_FORMAT, (void *)obj);
}
)
return;
} else {
debug_only(
if(TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr(" Non NULL normal " INTPTR_FORMAT, (void *)obj);
}
)
MarkSweep::mark_and_push(referent_addr);
}
}
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
if (ReferenceProcessor::pending_list_uses_discovered_field()) {
T next_oop = oopDesc::load_heap_oop(next_addr);
if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
debug_only(
if(TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr(" Process discovered as normal "
INTPTR_FORMAT, discovered_addr);
}
)
MarkSweep::mark_and_push(discovered_addr);
}
} else {
#ifdef ASSERT
oop next = oopDesc::load_decode_heap_oop(next_addr);
oop discovered = java_lang_ref_Reference::discovered(obj);
assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
(oopDesc*)obj));
#endif
}
debug_only(
if(TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr(" Process next as normal " INTPTR_FORMAT, next_addr);
}
)
MarkSweep::mark_and_push(next_addr);
ref->InstanceKlass::oop_follow_contents(obj);
}
void InstanceRefKlass::oop_follow_contents(oop obj) {
if (UseCompressedOops) {
specialized_oop_follow_contents<narrowOop>(this, obj);
} else {
specialized_oop_follow_contents<oop>(this, obj);
}
}
#if INCLUDE_ALL_GCS
template <class T>
void specialized_oop_follow_contents(InstanceRefKlass* ref,
ParCompactionManager* cm,
oop obj) {
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
T heap_oop = oopDesc::load_heap_oop(referent_addr);
debug_only(
if(TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr("InstanceRefKlass::oop_follow_contents " INTPTR_FORMAT, (void *)obj);
}
)
if (!oopDesc::is_null(heap_oop)) {
oop referent = oopDesc::decode_heap_oop_not_null(heap_oop);
if (PSParallelCompact::mark_bitmap()->is_unmarked(referent) &&
PSParallelCompact::ref_processor()->
discover_reference(obj, ref->reference_type())) {
ref->InstanceKlass::oop_follow_contents(cm, obj);
debug_only(
if(TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr(" Non NULL enqueued " INTPTR_FORMAT, (void *)obj);
}
)
return;
} else {
debug_only(
if(TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr(" Non NULL normal " INTPTR_FORMAT, (void *)obj);
}
)
PSParallelCompact::mark_and_push(cm, referent_addr);
}
}
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
if (ReferenceProcessor::pending_list_uses_discovered_field()) {
T next_oop = oopDesc::load_heap_oop(next_addr);
if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
debug_only(
if(TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr(" Process discovered as normal "
INTPTR_FORMAT, discovered_addr);
}
)
PSParallelCompact::mark_and_push(cm, discovered_addr);
}
} else {
#ifdef ASSERT
T next = oopDesc::load_heap_oop(next_addr);
oop discovered = java_lang_ref_Reference::discovered(obj);
assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
(oopDesc*)obj));
#endif
}
PSParallelCompact::mark_and_push(cm, next_addr);
ref->InstanceKlass::oop_follow_contents(cm, obj);
}
void InstanceRefKlass::oop_follow_contents(ParCompactionManager* cm,
oop obj) {
if (UseCompressedOops) {
specialized_oop_follow_contents<narrowOop>(this, cm, obj);
} else {
specialized_oop_follow_contents<oop>(this, cm, obj);
}
}
#endif // INCLUDE_ALL_GCS
#ifdef ASSERT
template <class T> void trace_reference_gc(const char *s, oop obj,
T* referent_addr,
T* next_addr,
T* discovered_addr) {
if(TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr("%s obj " INTPTR_FORMAT, s, (address)obj);
gclog_or_tty->print_cr(" referent_addr/* " INTPTR_FORMAT " / "
INTPTR_FORMAT, referent_addr,
referent_addr ?
(address)oopDesc::load_decode_heap_oop(referent_addr) : NULL);
gclog_or_tty->print_cr(" next_addr/* " INTPTR_FORMAT " / "
INTPTR_FORMAT, next_addr,
next_addr ? (address)oopDesc::load_decode_heap_oop(next_addr) : NULL);
gclog_or_tty->print_cr(" discovered_addr/* " INTPTR_FORMAT " / "
INTPTR_FORMAT, discovered_addr,
discovered_addr ?
(address)oopDesc::load_decode_heap_oop(discovered_addr) : NULL);
}
}
#endif
template <class T> void specialized_oop_adjust_pointers(InstanceRefKlass *ref, oop obj) {
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
MarkSweep::adjust_pointer(referent_addr);
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
MarkSweep::adjust_pointer(next_addr);
T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
MarkSweep::adjust_pointer(discovered_addr);
debug_only(trace_reference_gc("InstanceRefKlass::oop_adjust_pointers", obj,
referent_addr, next_addr, discovered_addr);)
}
int InstanceRefKlass::oop_adjust_pointers(oop obj) {
int size = size_helper();
InstanceKlass::oop_adjust_pointers(obj);
if (UseCompressedOops) {
specialized_oop_adjust_pointers<narrowOop>(this, obj);
} else {
specialized_oop_adjust_pointers<oop>(this, obj);
}
return size;
}
#define InstanceRefKlass_SPECIALIZED_OOP_ITERATE(T, nv_suffix, contains) \
T* disc_addr = (T*)java_lang_ref_Reference::discovered_addr(obj); \
if (closure->apply_to_weak_ref_discovered_field()) { \
closure->do_oop##nv_suffix(disc_addr); \
} \
\
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj); \
T heap_oop = oopDesc::load_heap_oop(referent_addr); \
ReferenceProcessor* rp = closure->_ref_processor; \
if (!oopDesc::is_null(heap_oop)) { \
oop referent = oopDesc::decode_heap_oop_not_null(heap_oop); \
if (!referent->is_gc_marked() && (rp != NULL) && \
rp->discover_reference(obj, reference_type())) { \
return size; \
} else if (contains(referent_addr)) { \
SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
closure->do_oop##nv_suffix(referent_addr); \
} \
} \
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj); \
if (ReferenceProcessor::pending_list_uses_discovered_field()) { \
T next_oop = oopDesc::load_heap_oop(next_addr); \
if (!oopDesc::is_null(next_oop) && contains(disc_addr)) { \
debug_only( \
if(TraceReferenceGC && PrintGCDetails) { \
gclog_or_tty->print_cr(" Process discovered as normal " \
INTPTR_FORMAT, disc_addr); \
} \
) \
SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk);\
closure->do_oop##nv_suffix(disc_addr); \
} \
} else { \
debug_only( \
T next_oop = oopDesc::load_heap_oop(next_addr); \
T disc_oop = oopDesc::load_heap_oop(disc_addr); \
assert(oopDesc::is_null(next_oop) || oopDesc::is_null(disc_oop), \
err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL" \
"discovered field", (oopDesc*)obj)); \
) \
} \
if (contains(next_addr)) { \
SpecializationStats::record_do_oop_call##nv_suffix(SpecializationStats::irk); \
closure->do_oop##nv_suffix(next_addr); \
} \
return size; \
template <class T> bool contains(T *t) { return true; }
#define InstanceRefKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \
\
int InstanceRefKlass:: \
oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
\
int size = InstanceKlass::oop_oop_iterate##nv_suffix(obj, closure); \
\
if (UseCompressedOops) { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, contains); \
} else { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains); \
} \
}
#if INCLUDE_ALL_GCS
#define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \
\
int InstanceRefKlass:: \
oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* closure) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
\
int size = InstanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \
\
if (UseCompressedOops) { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, contains); \
} else { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains); \
} \
}
#endif // INCLUDE_ALL_GCS
#define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \
\
int InstanceRefKlass:: \
oop_oop_iterate##nv_suffix##_m(oop obj, \
OopClosureType* closure, \
MemRegion mr) { \
SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::irk);\
\
int size = InstanceKlass::oop_oop_iterate##nv_suffix##_m(obj, closure, mr); \
if (UseCompressedOops) { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(narrowOop, nv_suffix, mr.contains); \
} else { \
InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, mr.contains); \
} \
}
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN)
#if INCLUDE_ALL_GCS
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN)
#endif // INCLUDE_ALL_GCS
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m)
#if INCLUDE_ALL_GCS
template <class T>
void specialized_oop_push_contents(InstanceRefKlass *ref,
PSPromotionManager* pm, oop obj) {
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
if (PSScavenge::should_scavenge(referent_addr)) {
ReferenceProcessor* rp = PSScavenge::reference_processor();
if (rp->discover_reference(obj, ref->reference_type())) {
ref->InstanceKlass::oop_push_contents(pm, obj);
return;
} else {
pm->claim_or_forward_depth(referent_addr);
}
}
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
if (ReferenceProcessor::pending_list_uses_discovered_field()) {
T next_oop = oopDesc::load_heap_oop(next_addr);
if (!oopDesc::is_null(next_oop)) { // i.e. ref is not "active"
T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
debug_only(
if(TraceReferenceGC && PrintGCDetails) {
gclog_or_tty->print_cr(" Process discovered as normal "
INTPTR_FORMAT, discovered_addr);
}
)
if (PSScavenge::should_scavenge(discovered_addr)) {
pm->claim_or_forward_depth(discovered_addr);
}
}
} else {
#ifdef ASSERT
oop next = oopDesc::load_decode_heap_oop(next_addr);
oop discovered = java_lang_ref_Reference::discovered(obj);
assert(oopDesc::is_null(next) || oopDesc::is_null(discovered),
err_msg("Found an inactive reference " PTR_FORMAT " with a non-NULL discovered field",
(oopDesc*)obj));
#endif
}
if (PSScavenge::should_scavenge(next_addr)) {
pm->claim_or_forward_depth(next_addr);
}
ref->InstanceKlass::oop_push_contents(pm, obj);
}
void InstanceRefKlass::oop_push_contents(PSPromotionManager* pm, oop obj) {
if (UseCompressedOops) {
specialized_oop_push_contents<narrowOop>(this, pm, obj);
} else {
specialized_oop_push_contents<oop>(this, pm, obj);
}
}
template <class T>
void specialized_oop_update_pointers(InstanceRefKlass *ref,
ParCompactionManager* cm, oop obj) {
T* referent_addr = (T*)java_lang_ref_Reference::referent_addr(obj);
PSParallelCompact::adjust_pointer(referent_addr);
T* next_addr = (T*)java_lang_ref_Reference::next_addr(obj);
PSParallelCompact::adjust_pointer(next_addr);
T* discovered_addr = (T*)java_lang_ref_Reference::discovered_addr(obj);
PSParallelCompact::adjust_pointer(discovered_addr);
debug_only(trace_reference_gc("InstanceRefKlass::oop_update_ptrs", obj,
referent_addr, next_addr, discovered_addr);)
}
int InstanceRefKlass::oop_update_pointers(ParCompactionManager* cm, oop obj) {
InstanceKlass::oop_update_pointers(cm, obj);
if (UseCompressedOops) {
specialized_oop_update_pointers<narrowOop>(this, cm, obj);
} else {
specialized_oop_update_pointers<oop>(this, cm, obj);
}
return size_helper();
}
#endif // INCLUDE_ALL_GCS
void InstanceRefKlass::update_nonstatic_oop_maps(Klass* k) {
InstanceKlass* ik = InstanceKlass::cast(k);
debug_only(static bool first_time = true);
assert(k == SystemDictionary::Reference_klass() && first_time,
"Invalid update of maps");
debug_only(first_time = false);
assert(ik->nonstatic_oop_map_count() == 1, "just checking");
OopMapBlock* map = ik->start_of_nonstatic_oop_maps();
debug_only(int offset = java_lang_ref_Reference::referent_offset);
debug_only(unsigned int count = ((java_lang_ref_Reference::discovered_offset -
java_lang_ref_Reference::referent_offset)/heapOopSize) + 1);
if (UseSharedSpaces) {
assert(map->offset() == java_lang_ref_Reference::queue_offset &&
map->count() == 1, "just checking");
} else {
assert(map->offset() == offset && map->count() == count,
"just checking");
map->set_offset(java_lang_ref_Reference::queue_offset);
map->set_count(1);
}
}
void InstanceRefKlass::oop_verify_on(oop obj, outputStream* st) {
InstanceKlass::oop_verify_on(obj, st);
oop referent = java_lang_ref_Reference::referent(obj);
GenCollectedHeap* gch = NULL;
if (Universe::heap()->kind() == CollectedHeap::GenCollectedHeap)
gch = GenCollectedHeap::heap();
if (referent != NULL) {
guarantee(referent->is_oop(), "referent field heap failed");
}
oop next = java_lang_ref_Reference::next(obj);
if (next != NULL) {
guarantee(next->is_oop(), "next field verify failed");
guarantee(next->is_instanceRef(), "next field verify failed");
}
}
bool InstanceRefKlass::owns_pending_list_lock(JavaThread* thread) {
if (java_lang_ref_Reference::pending_list_lock() == NULL) return false;
Handle h_lock(thread, java_lang_ref_Reference::pending_list_lock());
return ObjectSynchronizer::current_thread_holds_lock(thread, h_lock);
}
void InstanceRefKlass::acquire_pending_list_lock(BasicLock *pending_list_basic_lock) {
PRESERVE_EXCEPTION_MARK; // exceptions are never thrown, needed for TRAPS argument
HandleMark hm;
Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
ObjectSynchronizer::fast_enter(h_lock, pending_list_basic_lock, false, THREAD);
assert(ObjectSynchronizer::current_thread_holds_lock(
JavaThread::current(), h_lock),
"Locking should have succeeded");
if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
}
void InstanceRefKlass::release_and_notify_pending_list_lock(
BasicLock *pending_list_basic_lock) {
PRESERVE_EXCEPTION_MARK; // exceptions are never thrown, needed for TRAPS argument
HandleMark hm;
Handle h_lock(THREAD, java_lang_ref_Reference::pending_list_lock());
assert(ObjectSynchronizer::current_thread_holds_lock(
JavaThread::current(), h_lock),
"Lock should be held");
if (java_lang_ref_Reference::pending_list() != NULL) {
ObjectSynchronizer::notifyall(h_lock, THREAD);
}
ObjectSynchronizer::fast_exit(h_lock(), pending_list_basic_lock, THREAD);
if (HAS_PENDING_EXCEPTION) CLEAR_PENDING_EXCEPTION;
}
C:\hotspot-69087d08d473\src\share\vm/oops/instanceRefKlass.hpp
#ifndef SHARE_VM_OOPS_INSTANCEREFKLASS_HPP
#define SHARE_VM_OOPS_INSTANCEREFKLASS_HPP
#include "oops/instanceKlass.hpp"
#include "utilities/macros.hpp"
class InstanceRefKlass: public InstanceKlass {
friend class InstanceKlass;
InstanceRefKlass(int vtable_len, int itable_len, int static_field_size, int nonstatic_oop_map_size, ReferenceType rt, AccessFlags access_flags, bool is_anonymous)
: InstanceKlass(vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt, access_flags, is_anonymous) {}
public:
InstanceRefKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
bool oop_is_instanceRef() const { return true; }
static InstanceRefKlass* cast(Klass* k) {
assert(k->oop_is_instanceRef(), "cast to InstanceRefKlass");
return (InstanceRefKlass*) k;
}
int oop_adjust_pointers(oop obj);
void oop_follow_contents(oop obj);
PARALLEL_GC_DECLS
int oop_oop_iterate(oop obj, ExtendedOopClosure* blk) {
return oop_oop_iterate_v(obj, blk);
}
int oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) {
return oop_oop_iterate_v_m(obj, blk, mr);
}
#define InstanceRefKlass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
int oop_oop_iterate##nv_suffix(oop obj, OopClosureType* blk); \
int oop_oop_iterate##nv_suffix##_m(oop obj, OopClosureType* blk, MemRegion mr);
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DECL)
#if INCLUDE_ALL_GCS
#define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \
int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk);
ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL)
#endif // INCLUDE_ALL_GCS
static void release_and_notify_pending_list_lock(BasicLock *pending_list_basic_lock);
static void acquire_pending_list_lock(BasicLock *pending_list_basic_lock);
static bool owns_pending_list_lock(JavaThread* thread);
static void update_nonstatic_oop_maps(Klass* k);
public:
void oop_verify_on(oop obj, outputStream* st);
};
#endif // SHARE_VM_OOPS_INSTANCEREFKLASS_HPP
C:\hotspot-69087d08d473\src\share\vm/oops/klass.cpp
#include "precompiled.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "gc_implementation/shared/markSweep.inline.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "memory/heapInspection.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/oop.inline2.hpp"
#include "runtime/atomic.inline.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "utilities/stack.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
#include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
#include "gc_implementation/parallelScavenge/psScavenge.hpp"
#endif // INCLUDE_ALL_GCS
#if INCLUDE_JFR
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
bool Klass::is_cloneable() const {
return _access_flags.is_cloneable() ||
is_subtype_of(SystemDictionary::Cloneable_klass());
}
void Klass::set_is_cloneable() {
if (oop_is_instance() && InstanceKlass::cast(this)->reference_type() != REF_NONE) {
} else {
_access_flags.set_is_cloneable();
}
}
void Klass::set_name(Symbol* n) {
_name = n;
if (_name != NULL) _name->increment_refcount();
}
bool Klass::is_subclass_of(const Klass* k) const {
if (this == k) return true;
Klass* t = const_cast<Klass*>(this)->super();
while (t != NULL) {
if (t == k) return true;
t = t->super();
}
return false;
}
bool Klass::search_secondary_supers(Klass* k) const {
if (this == k)
return true;
int cnt = secondary_supers()->length();
for (int i = 0; i < cnt; i++) {
if (secondary_supers()->at(i) == k) {
((Klass*)this)->set_secondary_super_cache(k);
return true;
}
}
return false;
}
Klass *Klass::up_cast_abstract() {
Klass *r = this;
while( r->is_abstract() ) { // Receiver is abstract?
Klass *s = r->subklass(); // Check for exactly 1 subklass
if( !s || s->next_sibling() ) // Oops; wrong count; give up
return this; // Return 'this' as a no-progress flag
r = s; // Loop till find concrete class
}
return r; // Return the 1 concrete class
}
Klass *Klass::LCA( Klass *k2 ) {
Klass *k1 = this;
while( 1 ) {
if( k1->is_subtype_of(k2) ) return k2;
if( k2->is_subtype_of(k1) ) return k1;
k1 = k1->super();
k2 = k2->super();
}
}
void Klass::check_valid_for_instantiation(bool throwError, TRAPS) {
ResourceMark rm(THREAD);
THROW_MSG(throwError ? vmSymbols::java_lang_InstantiationError()
: vmSymbols::java_lang_InstantiationException(), external_name());
}
void Klass::copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) {
THROW(vmSymbols::java_lang_ArrayStoreException());
}
void Klass::initialize(TRAPS) {
ShouldNotReachHere();
}
bool Klass::compute_is_subtype_of(Klass* k) {
assert(k->is_klass(), "argument must be a class");
return is_subclass_of(k);
}
Klass* Klass::find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
#ifdef ASSERT
tty->print_cr("Error: find_field called on a klass oop."
" Likely error: reflection method does not correctly"
" wrap return value in a mirror object.");
#endif
ShouldNotReachHere();
return NULL;
}
Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const {
#ifdef ASSERT
tty->print_cr("Error: uncached_lookup_method called on a klass oop."
" Likely error: reflection method does not correctly"
" wrap return value in a mirror object.");
#endif
ShouldNotReachHere();
return NULL;
}
void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw() {
return Metaspace::allocate(loader_data, word_size, /*read_only*/false,
MetaspaceObj::ClassType, THREAD);
}
Klass::Klass() {
Klass* k = this;
set_super(NULL);
for (juint i = 0; i < Klass::primary_super_limit(); i++) {
_primary_supers[i] = NULL;
}
set_secondary_supers(NULL);
set_secondary_super_cache(NULL);
_primary_supers[0] = k;
set_super_check_offset(in_bytes(primary_supers_offset()));
_java_mirror = NULL;
set_modifier_flags(0);
set_layout_helper(Klass::_lh_neutral_value);
set_name(NULL);
AccessFlags af;
af.set_flags(0);
set_access_flags(af);
set_subklass(NULL);
set_next_sibling(NULL);
set_next_link(NULL);
set_prototype_header(markOopDesc::prototype());
set_biased_lock_revocation_count(0);
set_last_biased_lock_bulk_revocation_time(0);
clear_modified_oops();
clear_accumulated_modified_oops();
_shared_class_path_index = -1;
}
jint Klass::array_layout_helper(BasicType etype) {
assert(etype >= T_BOOLEAN && etype <= T_OBJECT, "valid etype");
int hsize = arrayOopDesc::base_offset_in_bytes(etype);
int esize = type2aelembytes(etype);
bool isobj = (etype == T_OBJECT);
int tag = isobj ? _lh_array_tag_obj_value : _lh_array_tag_type_value;
int lh = array_layout_helper(tag, hsize, etype, exact_log2(esize));
assert(lh < (int)_lh_neutral_value, "must look like an array layout");
assert(layout_helper_is_array(lh), "correct kind");
assert(layout_helper_is_objArray(lh) == isobj, "correct kind");
assert(layout_helper_is_typeArray(lh) == !isobj, "correct kind");
assert(layout_helper_header_size(lh) == hsize, "correct decode");
assert(layout_helper_element_type(lh) == etype, "correct decode");
assert(1 << layout_helper_log2_element_size(lh) == esize, "correct decode");
return lh;
}
bool Klass::can_be_primary_super_slow() const {
if (super() == NULL)
return true;
else if (super()->super_depth() >= primary_super_limit()-1)
return false;
else
return true;
}
void Klass::initialize_supers(Klass* k, TRAPS) {
if (FastSuperclassLimit == 0) {
set_super(k);
return;
}
if (k == NULL) {
set_super(NULL);
_primary_supers[0] = this;
assert(super_depth() == 0, "Object must already be initialized properly");
} else if (k != super() || k == SystemDictionary::Object_klass()) {
assert(super() == NULL || super() == SystemDictionary::Object_klass(),
"initialize this only once to a non-trivial value");
set_super(k);
Klass* sup = k;
int sup_depth = sup->super_depth();
juint my_depth = MIN2(sup_depth + 1, (int)primary_super_limit());
if (!can_be_primary_super_slow())
my_depth = primary_super_limit();
for (juint i = 0; i < my_depth; i++) {
_primary_supers[i] = sup->_primary_supers[i];
}
Klass* *super_check_cell;
if (my_depth < primary_super_limit()) {
_primary_supers[my_depth] = this;
super_check_cell = &_primary_supers[my_depth];
} else {
super_check_cell = &_secondary_super_cache;
}
set_super_check_offset((address)super_check_cell - (address) this);
#ifdef ASSERT
{
juint j = super_depth();
assert(j == my_depth, "computed accessor gets right answer");
Klass* t = this;
while (!t->can_be_primary_super()) {
t = t->super();
j = t->super_depth();
}
for (juint j1 = j+1; j1 < primary_super_limit(); j1++) {
assert(primary_super_of_depth(j1) == NULL, "super list padding");
}
while (t != NULL) {
assert(primary_super_of_depth(j) == t, "super list initialization");
t = t->super();
--j;
}
assert(j == (juint)-1, "correct depth count");
}
#endif
}
if (secondary_supers() == NULL) {
KlassHandle this_kh (THREAD, this);
int extras = 0;
Klass* p;
for (p = super(); !(p == NULL || p->can_be_primary_super()); p = p->super()) {
++extras;
}
ResourceMark rm(THREAD); // need to reclaim GrowableArrays allocated below
GrowableArray<Klass*>* secondaries = compute_secondary_supers(extras);
if (secondaries == NULL) {
return;
}
GrowableArray<Klass*>* primaries = new GrowableArray<Klass*>(extras);
for (p = this_kh->super(); !(p == NULL || p->can_be_primary_super()); p = p->super()) {
int i; // Scan for overflow primaries being duplicates of 2nd'arys
for( i = 0; i < secondaries->length(); i++ ) {
if( secondaries->at(i) == p )
break;
}
if( i < secondaries->length() )
continue; // It's a dup, don't put it in
primaries->push(p);
}
int new_length = primaries->length() + secondaries->length();
Array<Klass*>* s2 = MetadataFactory::new_array<Klass*>(
class_loader_data(), new_length, CHECK);
int fill_p = primaries->length();
for (int j = 0; j < fill_p; j++) {
s2->at_put(j, primaries->pop()); // add primaries in reverse order.
}
for( int j = 0; j < secondaries->length(); j++ ) {
s2->at_put(j+fill_p, secondaries->at(j)); // add secondaries on the end.
}
#ifdef ASSERT
for (int j = 0; j < s2->length(); j++) {
assert(s2->at(j) != NULL, "correct bootstrapping order");
}
#endif
this_kh->set_secondary_supers(s2);
}
}
GrowableArray<Klass*>* Klass::compute_secondary_supers(int num_extra_slots) {
assert(num_extra_slots == 0, "override for complex klasses");
set_secondary_supers(Universe::the_empty_klass_array());
return NULL;
}
Klass* Klass::subklass() const {
return _subklass == NULL ? NULL : _subklass;
}
InstanceKlass* Klass::superklass() const {
assert(super() == NULL || super()->oop_is_instance(), "must be instance klass");
return _super == NULL ? NULL : InstanceKlass::cast(_super);
}
Klass* Klass::next_sibling() const {
return _next_sibling == NULL ? NULL : _next_sibling;
}
void Klass::set_subklass(Klass* s) {
assert(s != this, "sanity check");
_subklass = s;
}
void Klass::set_next_sibling(Klass* s) {
assert(s != this, "sanity check");
_next_sibling = s;
}
void Klass::append_to_sibling_list() {
debug_only(verify();)
InstanceKlass* super = superklass();
if (super == NULL) return; // special case: class Object
assert((!super->is_interface() // interfaces cannot be supers
&& (super->superklass() == NULL || !is_interface())),
"an interface can only be a subklass of Object");
Klass* prev_first_subklass = super->subklass_oop();
if (prev_first_subklass != NULL) {
set_next_sibling(prev_first_subklass);
}
super->set_subklass(this);
debug_only(verify();)
}
bool Klass::is_loader_alive(BoolObjectClosure* is_alive) {
#ifdef ASSERT
oop loader = class_loader();
bool loader_alive = (loader == NULL) || is_alive->do_object_b(loader);
#endif // ASSERT
bool mirror_alive = is_alive->do_object_b(java_mirror());
assert(!mirror_alive || loader_alive, "loader must be alive if the mirror is"
" but not the other way around with anonymous classes");
return mirror_alive;
}
void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive_klasses) {
if (!ClassUnloading) {
return;
}
Klass* root = SystemDictionary::Object_klass();
Stack<Klass*, mtGC> stack;
stack.push(root);
while (!stack.is_empty()) {
Klass* current = stack.pop();
assert(current->is_loader_alive(is_alive), "just checking, this should be live");
Klass* sub = current->subklass_oop();
while (sub != NULL && !sub->is_loader_alive(is_alive)) {
#ifndef PRODUCT
if (TraceClassUnloading && WizardMode) {
ResourceMark rm;
tty->print_cr("[Unlinking class (subclass) %s]", sub->external_name());
}
#endif
sub = sub->next_sibling_oop();
}
current->set_subklass(sub);
if (sub != NULL) {
stack.push(sub);
}
Klass* sibling = current->next_sibling_oop();
while (sibling != NULL && !sibling->is_loader_alive(is_alive)) {
if (TraceClassUnloading && WizardMode) {
ResourceMark rm;
tty->print_cr("[Unlinking class (sibling) %s]", sibling->external_name());
}
sibling = sibling->next_sibling_oop();
}
current->set_next_sibling(sibling);
if (sibling != NULL) {
stack.push(sibling);
}
if (clean_alive_klasses && current->oop_is_instance()) {
InstanceKlass* ik = InstanceKlass::cast(current);
ik->clean_weak_instanceklass_links(is_alive);
while ((ik = ik->previous_versions()) != NULL) {
ik->clean_weak_instanceklass_links(is_alive);
}
}
}
}
void Klass::klass_update_barrier_set(oop v) {
record_modified_oops();
}
void Klass::klass_update_barrier_set_pre(oop* p, oop v) {
#if INCLUDE_ALL_GCS
if (UseG1GC) {
oop obj = *p;
if (obj != NULL) {
G1SATBCardTableModRefBS::enqueue(obj);
}
}
#endif
}
void Klass::klass_oop_store(oop* p, oop v) {
assert(!Universe::heap()->is_in_reserved((void*)p), "Should store pointer into metadata");
assert(v == NULL || Universe::heap()->is_in_reserved((void*)v), "Should store pointer to an object");
if (always_do_update_barrier) {
klass_oop_store((volatile oop*)p, v);
} else {
klass_update_barrier_set_pre(p, v);
klass_update_barrier_set(v);
}
}
void Klass::klass_oop_store(volatile oop* p, oop v) {
assert(!Universe::heap()->is_in_reserved((void*)p), "Should store pointer into metadata");
assert(v == NULL || Universe::heap()->is_in_reserved((void*)v), "Should store pointer to an object");
klass_update_barrier_set_pre((oop*)p, v); // Cast away volatile.
OrderAccess::release_store_ptr(p, v);
klass_update_barrier_set(v);
}
void Klass::oops_do(OopClosure* cl) {
cl->do_oop(&_java_mirror);
}
void Klass::remove_unshareable_info() {
assert (DumpSharedSpaces, "only called for DumpSharedSpaces");
JFR_ONLY(REMOVE_ID(this);)
set_subklass(NULL);
set_next_sibling(NULL);
set_java_mirror(NULL);
set_next_link(NULL);
set_class_loader_data(NULL);
}
void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
JFR_ONLY(RESTORE_ID(this);)
if (class_loader_data() == NULL) {
set_class_loader_data(loader_data);
loader_data->add_class(this);
}
if (java_mirror() == NULL) {
java_lang_Class::create_mirror(this, class_loader(), protection_domain, CHECK);
}
}
Klass* Klass::array_klass_or_null(int rank) {
EXCEPTION_MARK;
return array_klass_impl(true, rank, THREAD);
}
Klass* Klass::array_klass_or_null() {
EXCEPTION_MARK;
return array_klass_impl(true, THREAD);
}
Klass* Klass::array_klass_impl(bool or_null, int rank, TRAPS) {
fatal("array_klass should be dispatched to InstanceKlass, ObjArrayKlass or TypeArrayKlass");
return NULL;
}
Klass* Klass::array_klass_impl(bool or_null, TRAPS) {
fatal("array_klass should be dispatched to InstanceKlass, ObjArrayKlass or TypeArrayKlass");
return NULL;
}
oop Klass::class_loader() const { return class_loader_data()->class_loader(); }
const char* Klass::external_name() const {
if (oop_is_instance()) {
InstanceKlass* ik = (InstanceKlass*) this;
if (ik->is_anonymous()) {
assert(EnableInvokeDynamic, "");
intptr_t hash = 0;
if (ik->java_mirror() != NULL) {
hash = ik->java_mirror()->identity_hash();
}
char hash_buf[40];
sprintf(hash_buf, "/" UINTX_FORMAT, (uintx)hash);
size_t hash_len = strlen(hash_buf);
size_t result_len = name()->utf8_length();
char* result = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1);
name()->as_klass_external_name(result, (int) result_len + 1);
assert(strlen(result) == result_len, "");
strcpy(result + result_len, hash_buf);
assert(strlen(result) == result_len + hash_len, "");
return result;
}
}
if (name() == NULL) return "<unknown>";
return name()->as_klass_external_name();
}
const char* Klass::signature_name() const {
if (name() == NULL) return "<unknown>";
return name()->as_C_string();
}
jint Klass::compute_modifier_flags(TRAPS) const {
return 0;
}
int Klass::atomic_incr_biased_lock_revocation_count() {
return (int) Atomic::add(1, &_biased_lock_revocation_count);
}
jint Klass::jvmti_class_status() const {
return 0;
}
void Klass::print_on(outputStream* st) const {
ResourceMark rm;
st->print("%s", internal_name());
print_address_on(st);
st->cr();
}
void Klass::oop_print_on(oop obj, outputStream* st) {
ResourceMark rm;
st->print_cr("%s ", internal_name());
obj->print_address_on(st);
if (WizardMode) {
obj->mark()->print_on(st);
}
st->print(" - klass: ");
obj->klass()->print_value_on(st);
st->cr();
}
void Klass::oop_print_value_on(oop obj, outputStream* st) {
ResourceMark rm; // Cannot print in debug mode without this
st->print("%s", internal_name());
obj->print_address_on(st);
}
#if INCLUDE_SERVICES
void Klass::collect_statistics(KlassSizeStats *sz) const {
sz->_klass_bytes = sz->count(this);
sz->_mirror_bytes = sz->count(java_mirror());
sz->_secondary_supers_bytes = sz->count_array(secondary_supers());
sz->_ro_bytes += sz->_secondary_supers_bytes;
sz->_rw_bytes += sz->_klass_bytes + sz->_mirror_bytes;
}
#endif // INCLUDE_SERVICES
void Klass::verify_on(outputStream* st) {
assert(Metaspace::contains((address)this), "Should be");
guarantee(this->is_klass(),"should be klass");
if (super() != NULL) {
guarantee(super()->is_klass(), "should be klass");
}
if (secondary_super_cache() != NULL) {
Klass* ko = secondary_super_cache();
guarantee(ko->is_klass(), "should be klass");
}
for ( uint i = 0; i < primary_super_limit(); i++ ) {
Klass* ko = _primary_supers[i];
if (ko != NULL) {
guarantee(ko->is_klass(), "should be klass");
}
}
if (java_mirror() != NULL) {
guarantee(java_mirror()->is_oop(), "should be instance");
}
}
void Klass::oop_verify_on(oop obj, outputStream* st) {
guarantee(obj->is_oop(), "should be oop");
guarantee(obj->klass()->is_klass(), "klass field is not a klass");
}
#ifndef PRODUCT
bool Klass::verify_vtable_index(int i) {
if (oop_is_instance()) {
int limit = ((InstanceKlass*)this)->vtable_length()/vtableEntry::size();
assert(i >= 0 && i < limit, err_msg("index %d out of bounds %d", i, limit));
} else {
assert(oop_is_array(), "Must be");
int limit = ((ArrayKlass*)this)->vtable_length()/vtableEntry::size();
assert(i >= 0 && i < limit, err_msg("index %d out of bounds %d", i, limit));
}
return true;
}
bool Klass::verify_itable_index(int i) {
assert(oop_is_instance(), "");
int method_count = klassItable::method_count_for_interface(this);
assert(i >= 0 && i < method_count, "index out of bounds");
return true;
}
#endif
#ifndef PRODUCT
class TestKlass {
public:
static void test_oop_is_instanceClassLoader() {
assert(SystemDictionary::ClassLoader_klass()->oop_is_instanceClassLoader(), "assert");
assert(!SystemDictionary::String_klass()->oop_is_instanceClassLoader(), "assert");
}
};
void TestKlass_test() {
TestKlass::test_oop_is_instanceClassLoader();
}
#endif
C:\hotspot-69087d08d473\src\share\vm/oops/klass.hpp
#ifndef SHARE_VM_OOPS_KLASS_HPP
#define SHARE_VM_OOPS_KLASS_HPP
#include "memory/genOopClosures.hpp"
#include "memory/iterator.hpp"
#include "memory/memRegion.hpp"
#include "memory/specialized_oop_closures.hpp"
#include "oops/klassPS.hpp"
#include "oops/metadata.hpp"
#include "oops/oop.hpp"
#include "utilities/accessFlags.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp"
#include "gc_implementation/g1/g1OopClosures.hpp"
#include "gc_implementation/parNew/parOopClosures.hpp"
#endif // INCLUDE_ALL_GCS
#if INCLUDE_JFR
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
template <class T> class Array;
template <class T> class GrowableArray;
class ClassLoaderData;
class klassVtable;
class ParCompactionManager;
class KlassSizeStats;
class fieldDescriptor;
class Klass : public Metadata {
friend class VMStructs;
protected:
enum { _primary_super_limit = 8 };
jint _layout_helper;
juint _super_check_offset;
Symbol* _name;
Klass* _secondary_super_cache;
Array<Klass*>* _secondary_supers;
Klass* _primary_supers[_primary_super_limit];
oop _java_mirror;
Klass* _super;
Klass* _subklass;
Klass* _next_sibling;
Klass* _next_link;
ClassLoaderData* _class_loader_data;
jint _modifier_flags; // Processed access flags, for use by Class.getModifiers.
AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here.
jlong _last_biased_lock_bulk_revocation_time;
markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type
jint _biased_lock_revocation_count;
JFR_ONLY(DEFINE_TRACE_ID_FIELD;)
jbyte _modified_oops; // Card Table Equivalent (YC/CMS support)
jbyte _accumulated_modified_oops; // Mod Union Equivalent (CMS support)
private:
jshort _shared_class_path_index;
friend class SharedClassUtil;
protected:
Klass();
void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw();
public:
enum DefaultsLookupMode { find_defaults, skip_defaults };
enum OverpassLookupMode { find_overpass, skip_overpass };
enum StaticLookupMode { find_static, skip_static };
enum PrivateLookupMode { find_private, skip_private };
bool is_klass() const volatile { return true; }
Klass* super() const { return _super; }
void set_super(Klass* k) { _super = k; }
void initialize_supers(Klass* k, TRAPS);
void initialize_supers_impl1(Klass* k);
void initialize_supers_impl2(Klass* k);
virtual GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots);
virtual Klass* java_super() const { return NULL; }
juint super_check_offset() const { return _super_check_offset; }
void set_super_check_offset(juint o) { _super_check_offset = o; }
Klass* secondary_super_cache() const { return _secondary_super_cache; }
void set_secondary_super_cache(Klass* k) { _secondary_super_cache = k; }
Array<Klass*>* secondary_supers() const { return _secondary_supers; }
void set_secondary_supers(Array<Klass*>* k) { _secondary_supers = k; }
Klass* primary_super_of_depth(juint i) const {
assert(i < primary_super_limit(), "oob");
Klass* super = _primary_supers[i];
assert(super == NULL || super->super_depth() == i, "correct display");
return super;
}
bool can_be_primary_super() const {
const juint secondary_offset = in_bytes(secondary_super_cache_offset());
return super_check_offset() != secondary_offset;
}
virtual bool can_be_primary_super_slow() const;
juint super_depth() const {
if (!can_be_primary_super()) {
return primary_super_limit();
} else {
juint d = (super_check_offset() - in_bytes(primary_supers_offset())) / sizeof(Klass*);
assert(d < primary_super_limit(), "oob");
assert(_primary_supers[d] == this, "proper init");
return d;
}
}
void klass_oop_store(oop* p, oop v);
void klass_oop_store(volatile oop* p, oop v);
oop java_mirror() const { return _java_mirror; }
void set_java_mirror(oop m) { klass_oop_store(&_java_mirror, m); }
jint modifier_flags() const { return _modifier_flags; }
void set_modifier_flags(jint flags) { _modifier_flags = flags; }
int layout_helper() const { return _layout_helper; }
void set_layout_helper(int lh) { _layout_helper = lh; }
InstanceKlass* superklass() const;
Klass* subklass() const;
Klass* next_sibling() const;
void append_to_sibling_list(); // add newly created receiver to superklass' subklass list
void set_next_link(Klass* k) { _next_link = k; }
Klass* next_link() const { return _next_link; } // The next klass defined by the class loader.
ClassLoaderData* class_loader_data() const { return _class_loader_data; }
void set_class_loader_data(ClassLoaderData* loader_data) { _class_loader_data = loader_data; }
void record_modified_oops() { _modified_oops = 1; }
void clear_modified_oops() { _modified_oops = 0; }
bool has_modified_oops() { return _modified_oops == 1; }
void accumulate_modified_oops() { if (has_modified_oops()) _accumulated_modified_oops = 1; }
void clear_accumulated_modified_oops() { _accumulated_modified_oops = 0; }
bool has_accumulated_modified_oops() { return _accumulated_modified_oops == 1; }
int shared_classpath_index() const {
return _shared_class_path_index;
};
void set_shared_classpath_index(int index) {
_shared_class_path_index = index;
};
protected: // internal accessors
Klass* subklass_oop() const { return _subklass; }
Klass* next_sibling_oop() const { return _next_sibling; }
void set_subklass(Klass* s);
void set_next_sibling(Klass* s);
public:
static ByteSize super_offset() { return in_ByteSize(offset_of(Klass, _super)); }
static ByteSize super_check_offset_offset() { return in_ByteSize(offset_of(Klass, _super_check_offset)); }
static ByteSize primary_supers_offset() { return in_ByteSize(offset_of(Klass, _primary_supers)); }
static ByteSize secondary_super_cache_offset() { return in_ByteSize(offset_of(Klass, _secondary_super_cache)); }
static ByteSize secondary_supers_offset() { return in_ByteSize(offset_of(Klass, _secondary_supers)); }
static ByteSize java_mirror_offset() { return in_ByteSize(offset_of(Klass, _java_mirror)); }
static ByteSize modifier_flags_offset() { return in_ByteSize(offset_of(Klass, _modifier_flags)); }
static ByteSize layout_helper_offset() { return in_ByteSize(offset_of(Klass, _layout_helper)); }
static ByteSize access_flags_offset() { return in_ByteSize(offset_of(Klass, _access_flags)); }
enum {
_lh_neutral_value = 0, // neutral non-array non-instance value
_lh_instance_slow_path_bit = 0x01,
_lh_log2_element_size_shift = BitsPerByte*0,
_lh_log2_element_size_mask = BitsPerLong-1,
_lh_element_type_shift = BitsPerByte*1,
_lh_element_type_mask = right_n_bits(BitsPerByte), // shifted mask
_lh_header_size_shift = BitsPerByte*2,
_lh_header_size_mask = right_n_bits(BitsPerByte), // shifted mask
_lh_array_tag_bits = 2,
_lh_array_tag_shift = BitsPerInt - _lh_array_tag_bits,
_lh_array_tag_obj_value = ~0x01 // 0x80000000 >> 30
};
static const unsigned int _lh_array_tag_type_value = 0Xffffffff; // ~0x00, // 0xC0000000 >> 30
static int layout_helper_size_in_bytes(jint lh) {
assert(lh > (jint)_lh_neutral_value, "must be instance");
return (int) lh & ~_lh_instance_slow_path_bit;
}
static bool layout_helper_needs_slow_path(jint lh) {
assert(lh > (jint)_lh_neutral_value, "must be instance");
return (lh & _lh_instance_slow_path_bit) != 0;
}
static bool layout_helper_is_instance(jint lh) {
return (jint)lh > (jint)_lh_neutral_value;
}
static bool layout_helper_is_array(jint lh) {
return (jint)lh < (jint)_lh_neutral_value;
}
static bool layout_helper_is_typeArray(jint lh) {
return (juint)lh >= (juint)(_lh_array_tag_type_value << _lh_array_tag_shift);
}
static bool layout_helper_is_objArray(jint lh) {
return (jint)lh < (jint)(_lh_array_tag_type_value << _lh_array_tag_shift);
}
static int layout_helper_header_size(jint lh) {
assert(lh < (jint)_lh_neutral_value, "must be array");
int hsize = (lh >> _lh_header_size_shift) & _lh_header_size_mask;
assert(hsize > 0 && hsize < (int)sizeof(oopDesc)*3, "sanity");
return hsize;
}
static BasicType layout_helper_element_type(jint lh) {
assert(lh < (jint)_lh_neutral_value, "must be array");
int btvalue = (lh >> _lh_element_type_shift) & _lh_element_type_mask;
assert(btvalue >= T_BOOLEAN && btvalue <= T_OBJECT, "sanity");
return (BasicType) btvalue;
}
static int layout_helper_boolean_diffbit() {
jint zlh = array_layout_helper(T_BOOLEAN);
jint blh = array_layout_helper(T_BYTE);
assert(zlh != blh, "array layout helpers must differ");
int diffbit = 1;
while ((diffbit & (zlh ^ blh)) == 0 && (diffbit & zlh) == 0) {
diffbit <<= 1;
assert(diffbit != 0, "make sure T_BOOLEAN has a different bit than T_BYTE");
}
return diffbit;
}
static int layout_helper_log2_element_size(jint lh) {
assert(lh < (jint)_lh_neutral_value, "must be array");
int l2esz = (lh >> _lh_log2_element_size_shift) & _lh_log2_element_size_mask;
assert(l2esz <= LogBitsPerLong,
err_msg("sanity. l2esz: 0x%x for lh: 0x%x", (uint)l2esz, (uint)lh));
return l2esz;
}
static jint array_layout_helper(jint tag, int hsize, BasicType etype, int log2_esize) {
return (tag << _lh_array_tag_shift)
| (hsize << _lh_header_size_shift)
| ((int)etype << _lh_element_type_shift)
| (log2_esize << _lh_log2_element_size_shift);
}
static jint instance_layout_helper(jint size, bool slow_path_flag) {
return (size << LogHeapWordSize)
| (slow_path_flag ? _lh_instance_slow_path_bit : 0);
}
static int layout_helper_to_size_helper(jint lh) {
assert(lh > (jint)_lh_neutral_value, "must be instance");
return lh >> LogHeapWordSize;
}
static jint array_layout_helper(BasicType etype);
#ifdef PRODUCT
static juint primary_super_limit() { return _primary_super_limit; }
#else
static juint primary_super_limit() {
assert(FastSuperclassLimit <= _primary_super_limit, "parameter oob");
return FastSuperclassLimit;
}
#endif
virtual klassVtable* vtable() const { return NULL; }
virtual int vtable_length() const { return 0; }
bool is_subclass_of(const Klass* k) const;
bool is_subtype_of(Klass* k) const {
juint off = k->super_check_offset();
Klass* sup = *(Klass**)( (address)this + off );
const juint secondary_offset = in_bytes(secondary_super_cache_offset());
if (sup == k) {
return true;
} else if (off != secondary_offset) {
return false;
} else {
return search_secondary_supers(k);
}
}
bool search_secondary_supers(Klass* k) const;
Klass *LCA( Klass *k );
virtual void check_valid_for_instantiation(bool throwError, TRAPS);
virtual void copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS);
virtual bool should_be_initialized() const { return false; }
virtual void initialize(TRAPS);
friend class MethodLookupCache;
virtual Klass* find_field(Symbol* name, Symbol* signature, fieldDescriptor* fd) const;
virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const;
public:
Method* lookup_method(Symbol* name, Symbol* signature) const {
return uncached_lookup_method(name, signature, find_overpass);
}
Klass* array_klass(int rank, TRAPS) { return array_klass_impl(false, rank, THREAD); }
Klass* array_klass(TRAPS) { return array_klass_impl(false, THREAD); }
Klass* array_klass_or_null(int rank);
Klass* array_klass_or_null();
virtual oop protection_domain() const = 0;
oop class_loader() const;
virtual oop klass_holder() const { return class_loader(); }
protected:
virtual Klass* array_klass_impl(bool or_null, int rank, TRAPS);
virtual Klass* array_klass_impl(bool or_null, TRAPS);
public:
virtual void remove_unshareable_info();
virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS);
protected:
virtual bool compute_is_subtype_of(Klass* k);
public:
virtual bool is_leaf_class() const { fatal("not a class"); return false; }
public:
virtual int oop_size(oop obj) const = 0;
virtual int size() const = 0;
#if INCLUDE_SERVICES
virtual void collect_statistics(KlassSizeStats *sz) const;
#endif
const char* external_name() const;
virtual const char* signature_name() const;
virtual void oop_follow_contents(oop obj) = 0;
virtual int oop_adjust_pointers(oop obj) = 0;
PARALLEL_GC_DECLS_PV
protected:
virtual bool oop_is_instance_slow() const { return false; }
virtual bool oop_is_array_slow() const { return false; }
virtual bool oop_is_objArray_slow() const { return false; }
virtual bool oop_is_typeArray_slow() const { return false; }
public:
virtual bool oop_is_instanceClassLoader() const { return false; }
virtual bool oop_is_instanceMirror() const { return false; }
virtual bool oop_is_instanceRef() const { return false; }
#ifndef ASSERT
#define assert_same_query(xval, xcheck) xval
#else
private:
static bool assert_same_query(bool xval, bool xslow) {
assert(xval == xslow, "slow and fast queries agree");
return xval;
}
public:
#endif
inline bool oop_is_instance() const { return assert_same_query(
layout_helper_is_instance(layout_helper()),
oop_is_instance_slow()); }
inline bool oop_is_array() const { return assert_same_query(
layout_helper_is_array(layout_helper()),
oop_is_array_slow()); }
inline bool oop_is_objArray() const { return assert_same_query(
layout_helper_is_objArray(layout_helper()),
oop_is_objArray_slow()); }
inline bool oop_is_typeArray() const { return assert_same_query(
layout_helper_is_typeArray(layout_helper()),
oop_is_typeArray_slow()); }
#undef assert_same_query
AccessFlags access_flags() const { return _access_flags; }
void set_access_flags(AccessFlags flags) { _access_flags = flags; }
bool is_public() const { return _access_flags.is_public(); }
bool is_final() const { return _access_flags.is_final(); }
bool is_interface() const { return _access_flags.is_interface(); }
bool is_abstract() const { return _access_flags.is_abstract(); }
bool is_super() const { return _access_flags.is_super(); }
bool is_synthetic() const { return _access_flags.is_synthetic(); }
void set_is_synthetic() { _access_flags.set_is_synthetic(); }
bool has_finalizer() const { return _access_flags.has_finalizer(); }
bool has_final_method() const { return _access_flags.has_final_method(); }
void set_has_finalizer() { _access_flags.set_has_finalizer(); }
void set_has_final_method() { _access_flags.set_has_final_method(); }
bool is_cloneable() const;
void set_is_cloneable();
bool has_vanilla_constructor() const { return _access_flags.has_vanilla_constructor(); }
void set_has_vanilla_constructor() { _access_flags.set_has_vanilla_constructor(); }
bool has_miranda_methods () const { return access_flags().has_miranda_methods(); }
void set_has_miranda_methods() { _access_flags.set_has_miranda_methods(); }
markOop prototype_header() const { return _prototype_header; }
inline void set_prototype_header(markOop header);
static ByteSize prototype_header_offset() { return in_ByteSize(offset_of(Klass, _prototype_header)); }
int biased_lock_revocation_count() const { return (int) _biased_lock_revocation_count; }
int atomic_incr_biased_lock_revocation_count();
void set_biased_lock_revocation_count(int val) { _biased_lock_revocation_count = (jint) val; }
jlong last_biased_lock_bulk_revocation_time() { return _last_biased_lock_bulk_revocation_time; }
void set_last_biased_lock_bulk_revocation_time(jlong cur_time) { _last_biased_lock_bulk_revocation_time = cur_time; }
JFR_ONLY(DEFINE_TRACE_ID_METHODS;)
virtual void oops_do(OopClosure* cl);
bool is_loader_alive(BoolObjectClosure* is_alive);
static void clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive_klasses = true);
static void clean_subklass_tree(BoolObjectClosure* is_alive) {
clean_weak_klass_links(is_alive, false /* clean_alive_klasses */);
}
virtual int oop_oop_iterate(oop obj, ExtendedOopClosure* blk) = 0;
virtual int oop_oop_iterate_v(oop obj, ExtendedOopClosure* blk) {
return oop_oop_iterate(obj, blk);
}
#if INCLUDE_ALL_GCS
virtual int oop_oop_iterate_backwards_v(oop obj, ExtendedOopClosure* blk) {
return oop_oop_iterate_v(obj, blk);
}
#endif // INCLUDE_ALL_GCS
virtual int oop_oop_iterate_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) = 0;
virtual int oop_oop_iterate_v_m(oop obj, ExtendedOopClosure* blk, MemRegion mr) {
return oop_oop_iterate_m(obj, blk, mr);
}
#define Klass_OOP_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \
virtual int oop_oop_iterate##nv_suffix(oop obj, OopClosureType* blk) { \
return oop_oop_iterate(obj, blk); \
} \
\
(I don't see why the _m should be required, but without it the Solaris \
C++ gives warning messages about overridings of the "oop_oop_iterate" \
defined above "hiding" this virtual function. (DLD, 6/20/00)) */ \
virtual int oop_oop_iterate##nv_suffix##_m(oop obj, \
OopClosureType* blk, \
MemRegion mr) { \
return oop_oop_iterate_m(obj, blk, mr); \
}
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_DECL)
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_DECL)
#if INCLUDE_ALL_GCS
#define Klass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \
virtual int oop_oop_iterate_backwards##nv_suffix(oop obj, \
OopClosureType* blk) { \
return oop_oop_iterate_backwards_v(obj, blk); \
}
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL)
SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL)
#endif // INCLUDE_ALL_GCS
virtual void array_klasses_do(void f(Klass* k)) {}
Klass *up_cast_abstract();
Symbol* name() const { return _name; }
void set_name(Symbol* n);
public:
virtual jint compute_modifier_flags(TRAPS) const;
virtual jint jvmti_class_status() const;
virtual void print_on(outputStream* st) const;
virtual void oop_print_value_on(oop obj, outputStream* st);
virtual void oop_print_on (oop obj, outputStream* st);
virtual const char* internal_name() const = 0;
virtual void verify_on(outputStream* st);
void verify() { verify_on(tty); }
#ifndef PRODUCT
bool verify_vtable_index(int index);
bool verify_itable_index(int index);
#endif
virtual void oop_verify_on(oop obj, outputStream* st);
static bool is_null(narrowKlass obj);
static bool is_null(Klass* obj);
static narrowKlass encode_klass_not_null(Klass* v);
static narrowKlass encode_klass(Klass* v);
static Klass* decode_klass_not_null(narrowKlass v);
static Klass* decode_klass(narrowKlass v);
private:
void klass_update_barrier_set(oop v);
void klass_update_barrier_set_pre(oop* p, oop v);
};
#endif // SHARE_VM_OOPS_KLASS_HPP
C:\hotspot-69087d08d473\src\share\vm/oops/klass.inline.hpp
#ifndef SHARE_VM_OOPS_KLASS_INLINE_HPP
#define SHARE_VM_OOPS_KLASS_INLINE_HPP
#include "memory/universe.hpp"
#include "oops/klass.hpp"
#include "oops/markOop.hpp"
inline void Klass::set_prototype_header(markOop header) {
assert(!header->has_bias_pattern() || oop_is_instance(), "biased locking currently only supported for Java instances");
_prototype_header = header;
}
inline bool Klass::is_null(Klass* obj) { return obj == NULL; }
inline bool Klass::is_null(narrowKlass obj) { return obj == 0; }
inline bool check_klass_alignment(Klass* obj) {
return (intptr_t)obj % KlassAlignmentInBytes == 0;
}
inline narrowKlass Klass::encode_klass_not_null(Klass* v) {
assert(!is_null(v), "klass value can never be zero");
assert(check_klass_alignment(v), "Address not aligned");
int shift = Universe::narrow_klass_shift();
uint64_t pd = (uint64_t)(pointer_delta((void*)v, Universe::narrow_klass_base(), 1));
assert(KlassEncodingMetaspaceMax > pd, "change encoding max if new encoding");
uint64_t result = pd >> shift;
assert((result & CONST64(0xffffffff00000000)) == 0, "narrow klass pointer overflow");
assert(decode_klass(result) == v, "reversibility");
return (narrowKlass)result;
}
inline narrowKlass Klass::encode_klass(Klass* v) {
return is_null(v) ? (narrowKlass)0 : encode_klass_not_null(v);
}
inline Klass* Klass::decode_klass_not_null(narrowKlass v) {
assert(!is_null(v), "narrow klass value can never be zero");
int shift = Universe::narrow_klass_shift();
Klass* result = (Klass*)(void*)((uintptr_t)Universe::narrow_klass_base() + ((uintptr_t)v << shift));
assert(check_klass_alignment(result), err_msg("address not aligned: " INTPTR_FORMAT, p2i((void*) result)));
return result;
}
inline Klass* Klass::decode_klass(narrowKlass v) {
return is_null(v) ? (Klass*)NULL : decode_klass_not_null(v);
}
#endif // SHARE_VM_OOPS_KLASS_INLINE_HPP
C:\hotspot-69087d08d473\src\share\vm/oops/klassPS.hpp
#ifndef SHARE_VM_OOPS_KLASSPS_HPP
#define SHARE_VM_OOPS_KLASSPS_HPP
#include "utilities/macros.hpp"
#if INCLUDE_ALL_GCS
#define PARALLEL_GC_DECLS \
virtual void oop_push_contents(PSPromotionManager* pm, oop obj); \
\
The 2-arg version of oop_update_pointers is for objects that are \
known not to cross chunk boundaries. The 4-arg version is for \
objects that do (or may) cross chunk boundaries; it updates only those \
oops that are in the region [beg_addr, end_addr). */ \
virtual void oop_follow_contents(ParCompactionManager* cm, oop obj); \
virtual int oop_update_pointers(ParCompactionManager* cm, oop obj);
#define PARALLEL_GC_DECLS_PV \
virtual void oop_push_contents(PSPromotionManager* pm, oop obj) = 0; \
virtual void oop_follow_contents(ParCompactionManager* cm, oop obj) = 0; \
virtual int oop_update_pointers(ParCompactionManager* cm, oop obj) = 0;
#else // INCLUDE_ALL_GCS
#define PARALLEL_GC_DECLS
#define PARALLEL_GC_DECLS_PV
#endif // INCLUDE_ALL_GCS
#endif // SHARE_VM_OOPS_KLASSPS_HPP
C:\hotspot-69087d08d473\src\share\vm/oops/klassVtable.cpp
#include "precompiled.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "gc_implementation/shared/markSweep.inline.hpp"
#include "memory/gcLocker.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "oops/method.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "runtime/arguments.hpp"
#include "runtime/handles.inline.hpp"
#include "utilities/copy.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
ssssssss46
最新推荐文章于 2024-07-08 00:01:13 发布