void javaVFrame::print_value() const { Method* m = method(); InstanceKlass* k = m->method_holder(); tty->print_cr("frame( sp=" INTPTR_FORMAT ", unextended_sp=" INTPTR_FORMAT ", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT ")", _fr.sp(), _fr.unextended_sp(), _fr.fp(), _fr.pc()); tty->print("%s.%s", k->internal_name(), m->name()->as_C_string()); if (!m->is_native()) { Symbol* source_name = k->source_file_name(); int line_number = m->line_number_from_bci(bci()); if (source_name != NULL && (line_number != -1)) { tty->print("(%s:%d)", source_name->as_C_string(), line_number); } } else { tty->print("(Native Method)"); } // Check frame size and print warning if it looks suspiciously large if (fr().sp() != NULL) { RegisterMap map = *register_map(); uint size = fr().frame_size(&map); #ifdef _LP64 if (size > 8*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size); #else if (size > 4*K) warning("SUSPICIOUSLY LARGE FRAME (%d)", size); #endif } }
bool Exceptions::special_exception(Thread* thread, const char* file, int line, Handle h_exception) { // bootstrapping check if (!Universe::is_fully_initialized()) { vm_exit_during_initialization(h_exception); ShouldNotReachHere(); } #ifdef ASSERT // Check for trying to throw stack overflow before initialization is complete // to prevent infinite recursion trying to initialize stack overflow without // adequate stack space. // This can happen with stress testing a large value of StackShadowPages if (h_exception()->klass() == SystemDictionary::StackOverflowError_klass()) { InstanceKlass* ik = InstanceKlass::cast(h_exception->klass()); assert(ik->is_initialized(), "need to increase min_stack_allowed calculation"); } #endif // ASSERT if (thread->is_VM_thread() || thread->is_Compiler_thread() ) { // We do not care what kind of exception we get for the vm-thread or a thread which // is compiling. We just install a dummy exception object thread->set_pending_exception(Universe::vm_exception(), file, line); return true; } return false; }
// Find all methods on this hierarchy that match this // method's erased (name, signature) bool visit() { PseudoScope* scope = PseudoScope::cast(current_data()); InstanceKlass* iklass = current_class(); Method* m = iklass->find_method(_method_name, _method_signature); // private interface methods are not candidates for default methods // invokespecial to private interface methods doesn't use default method logic // The overpasses are your supertypes' errors, we do not include them // future: take access controls into account for superclass methods if (m != NULL && !m->is_static() && !m->is_overpass() && (!iklass->is_interface() || m->is_public())) { if (_family == NULL) { _family = new StatefulMethodFamily(); } if (iklass->is_interface()) { StateRestorer* restorer = _family->record_method_and_dq_further(m); scope->add_mark(restorer); } else { // This is the rule that methods in classes "win" (bad word) over // methods in interfaces. This works because of single inheritance _family->set_target_if_empty(m); } } return true; }
static void collect_classes(Klass* k) { _global_klass_objects->append_if_missing(k); if (k->oop_is_instance()) { // Add in the array classes too InstanceKlass* ik = InstanceKlass::cast(k); ik->array_klasses_do(collect_classes); } }
void StackFrameInfo::print_on(outputStream* st) const { ResourceMark rm; java_lang_Throwable::print_stack_element(st, method(), bci()); int len = (_locked_monitors != NULL ? _locked_monitors->length() : 0); for (int i = 0; i < len; i++) { oop o = _locked_monitors->at(i); InstanceKlass* ik = InstanceKlass::cast(o->klass()); st->print_cr("\t- locked <" INTPTR_FORMAT "> (a %s)", (address)o, ik->external_name()); } }
extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index) { ResourceMark rm; HandleMark hm; Klass* klass = receiver->klass(); InstanceKlass* ik = InstanceKlass::cast(klass); klassVtable* vt = ik->vtable(); ik->print(); fatal(err_msg("bad compiled vtable dispatch: receiver " INTPTR_FORMAT ", " "index %d (vtable length %d)", (address)receiver, index, vt->length())); }
void JavaCalls::call_default_constructor(JavaThread* thread, methodHandle method, Handle receiver, TRAPS) { assert(method->name() == vmSymbols::object_initializer_name(), "Should only be called for default constructor"); assert(method->signature() == vmSymbols::void_method_signature(), "Should only be called for default constructor"); InstanceKlass* ik = method->method_holder(); if (ik->is_initialized() && ik->has_vanilla_constructor()) { // safe to skip constructor call } else { static JavaValue result(T_VOID); JavaCallArguments args(receiver); call(&result, method, &args, CHECK); } }
void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, methodHandle method, int index) { assert(method->method_holder()->verify_itable_index(index), ""); assert(invoke_code == Bytecodes::_invokeinterface, ""); InstanceKlass* interf = method->method_holder(); assert(interf->is_interface(), "must be an interface"); assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here"); set_f1(interf); set_f2(index); set_method_flags(as_TosState(method->result_type()), 0, // no option bits method()->size_of_parameters()); set_bytecode_1(Bytecodes::_invokeinterface); }
// Walk all methods in the class list and assign a fingerprint. // so that this part of the ConstMethod* is read only. static void calculate_fingerprints() { for (int i = 0; i < _global_klass_objects->length(); i++) { Klass* k = _global_klass_objects->at(i); if (k->oop_is_instance()) { InstanceKlass* ik = InstanceKlass::cast(k); for (int i = 0; i < ik->methods()->length(); i++) { Method* m = ik->methods()->at(i); Fingerprinter fp(m); // The side effect of this call sets method's fingerprint field. fp.fingerprint(); } } } }
bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS) { assert(CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), ""); assert(!is_optimized(), "cannot set an optimized virtual call to megamorphic"); assert(is_call_to_compiled() || is_call_to_interpreted(), "going directly to megamorphic?"); address entry; if (call_info->call_kind() == CallInfo::itable_call) { assert(bytecode == Bytecodes::_invokeinterface, ""); int itable_index = call_info->itable_index(); entry = VtableStubs::find_itable_stub(itable_index); if (entry == false) { return false; } #ifdef ASSERT int index = call_info->resolved_method()->itable_index(); assert(index == itable_index, "CallInfo pre-computes this"); InstanceKlass* k = call_info->resolved_method()->method_holder(); assert(k->verify_itable_index(itable_index), "sanity check"); #endif //ASSERT CompiledICHolder* holder = new CompiledICHolder(call_info->resolved_method()->method_holder(), call_info->resolved_klass()(), false); holder->claim(); InlineCacheBuffer::create_transition_stub(this, holder, entry); } else { assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable"); // Can be different than selected_method->vtable_index(), due to package-private etc. int vtable_index = call_info->vtable_index(); assert(call_info->resolved_klass()->verify_vtable_index(vtable_index), "sanity check"); entry = VtableStubs::find_vtable_stub(vtable_index); if (entry == NULL) { return false; } InlineCacheBuffer::create_transition_stub(this, NULL, entry); } if (TraceICs) { ResourceMark rm; tty->print_cr ("IC@" INTPTR_FORMAT ": to megamorphic %s entry: " INTPTR_FORMAT, p2i(instruction_address()), call_info->selected_method()->print_value_string(), p2i(entry)); } // We can't check this anymore. With lazy deopt we could have already // cleaned this IC entry before we even return. This is possible if // we ran out of space in the inline cache buffer trying to do the // set_next and we safepointed to free up space. This is a benign // race because the IC entry was complete when we safepointed so // cleaning it immediately is harmless. // assert(is_megamorphic(), "sanity check"); return true; }
void FinalizerInfoDCmd::execute(DCmdSource source, TRAPS) { ResourceMark rm; Klass* k = SystemDictionary::resolve_or_null( vmSymbols::finalizer_histogram_klass(), THREAD); assert(k != NULL, "FinalizerHistogram class is not accessible"); instanceKlassHandle klass(THREAD, k); JavaValue result(T_ARRAY); // We are calling lang.ref.FinalizerHistogram.getFinalizerHistogram() method // and expect it to return array of FinalizerHistogramEntry as Object[] JavaCalls::call_static(&result, klass, vmSymbols::get_finalizer_histogram_name(), vmSymbols::void_finalizer_histogram_entry_array_signature(), CHECK); objArrayOop result_oop = (objArrayOop) result.get_jobject(); if (result_oop->length() == 0) { output()->print_cr("No instances waiting for finalization found"); return; } oop foop = result_oop->obj_at(0); InstanceKlass* ik = InstanceKlass::cast(foop->klass()); fieldDescriptor count_fd, name_fd; Klass* count_res = ik->find_field( vmSymbols::finalizer_histogram_entry_count_field(), vmSymbols::int_signature(), &count_fd); Klass* name_res = ik->find_field( vmSymbols::finalizer_histogram_entry_name_field(), vmSymbols::string_signature(), &name_fd); assert(count_res != NULL && name_res != NULL, "Unexpected layout of FinalizerHistogramEntry"); output()->print_cr("Unreachable instances waiting for finalization"); output()->print_cr("#instances class name"); output()->print_cr("-----------------------"); for (int i = 0; i < result_oop->length(); ++i) { oop element_oop = result_oop->obj_at(i); oop str_oop = element_oop->obj_field(name_fd.offset()); char *name = java_lang_String::as_utf8_string(str_oop); int count = element_oop->int_field(count_fd.offset()); output()->print_cr("%10d %s", count, name); } }
void compute_offset(int &dest_offset, Klass* klass, const char* name, const char* signature, bool static_field) { Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name)); Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature)); if (name_symbol == NULL || signature_symbol == NULL) { guarantee(false, err_msg("symbol with name %s and signature %s was not found in symbol table (klass=%s)", name, signature, klass->name()->as_C_string())); } InstanceKlass* ik = InstanceKlass::cast(klass); fieldDescriptor fd; if (!ik->find_field(name_symbol, signature_symbol, &fd)) { ResourceMark rm; fatal(err_msg("Invalid layout of %s at %s", name_symbol->as_C_string(), ik->external_name())); } guarantee(fd.is_static() == static_field, "static/instance mismatch"); dest_offset = fd.offset(); }
void ConcurrentLocksDump::print_locks_on(JavaThread* t, outputStream* st) { st->print_cr(" Locked ownable synchronizers:"); ThreadConcurrentLocks* tcl = thread_concurrent_locks(t); GrowableArray<instanceOop>* locks = (tcl != NULL ? tcl->owned_locks() : NULL); if (locks == NULL || locks->is_empty()) { st->print_cr("\t- None"); st->cr(); return; } for (int i = 0; i < locks->length(); i++) { instanceOop obj = locks->at(i); InstanceKlass* ik = InstanceKlass::cast(obj->klass()); st->print_cr("\t- <" INTPTR_FORMAT "> (a %s)", (address)obj, ik->external_name()); } st->cr(); }
// Assumes the vtable is in first slot in object. static void patch_klass_vtables(void** vtbl_list, void* new_vtable_start) { int n = _global_klass_objects->length(); for (int i = 0; i < n; i++) { Klass* obj = _global_klass_objects->at(i); // Note oop_is_instance() is a virtual call. After patching vtables // all virtual calls on the dummy vtables will restore the original! if (obj->oop_is_instance()) { InstanceKlass* ik = InstanceKlass::cast(obj); *(void**)ik = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, ik); ConstantPool* cp = ik->constants(); *(void**)cp = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, cp); for (int j = 0; j < ik->methods()->length(); j++) { Method* m = ik->methods()->at(j); *(void**)m = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, m); } } else { // Array klasses Klass* k = obj; *(void**)k = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, k); } } }
void KlassHierarchy::print_class(outputStream* st, KlassInfoEntry* cie, bool print_interfaces) { ResourceMark rm; InstanceKlass* klass = (InstanceKlass*)cie->klass(); int indent = 0; // Print indentation with proper indicators of superclass. Klass* super = klass->super(); while (super != NULL) { super = super->super(); indent++; } print_indent(st, indent); if (indent != 0) st->print("--"); // Print the class name, its unique ClassLoader identifer, and if it is an interface. print_classname(st, klass); if (klass->is_interface()) { st->print(" (intf)"); } st->print("\n"); // Print any interfaces the class has. if (print_interfaces) { Array<Klass*>* local_intfs = klass->local_interfaces(); Array<Klass*>* trans_intfs = klass->transitive_interfaces(); for (int i = 0; i < local_intfs->length(); i++) { print_interface(st, local_intfs->at(i), "declared", indent); } for (int i = 0; i < trans_intfs->length(); i++) { Klass* trans_interface = trans_intfs->at(i); // Only print transitive interfaces if they are not also declared. if (!local_intfs->contains(trans_interface)) { print_interface(st, trans_interface, "inherited", indent); } } } }
void CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS) { methodHandle method = call_info->selected_method(); bool is_invoke_interface = (bytecode == Bytecodes::_invokeinterface && !call_info->has_vtable_index()); assert(CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), ""); assert(!is_optimized(), "cannot set an optimized virtual call to megamorphic"); assert(is_call_to_compiled() || is_call_to_interpreted(), "going directly to megamorphic?"); address entry; if (is_invoke_interface) { int index = klassItable::compute_itable_index(call_info->resolved_method()()); entry = VtableStubs::create_stub(false, index, method()); assert(entry != NULL, "entry not computed"); InstanceKlass* k = call_info->resolved_method()->method_holder(); assert(k->is_interface(), "sanity check"); InlineCacheBuffer::create_transition_stub(this, k, entry); } else { // Can be different than method->vtable_index(), due to package-private etc. int vtable_index = call_info->vtable_index(); entry = VtableStubs::create_stub(true, vtable_index, method()); InlineCacheBuffer::create_transition_stub(this, method(), entry); } if (TraceICs) { ResourceMark rm; tty->print_cr ("IC@" INTPTR_FORMAT ": to megamorphic %s entry: " INTPTR_FORMAT, instruction_address(), method->print_value_string(), entry); } // We can't check this anymore. With lazy deopt we could have already // cleaned this IC entry before we even return. This is possible if // we ran out of space in the inline cache buffer trying to do the // set_next and we safepointed to free up space. This is a benign // race because the IC entry was complete when we safepointed so // cleaning it immediately is harmless. // assert(is_megamorphic(), "sanity check"); }
oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream, jlong mode, int skip_frames, int frame_count, int start_index, objArrayHandle frames_array, TRAPS) { methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method()); { Klass* stackWalker_klass = SystemDictionary::StackWalker_klass(); Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass(); while (!stream.at_end()) { InstanceKlass* ik = stream.method()->method_holder(); if (ik != stackWalker_klass && ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) { break; } if (log_is_enabled(Debug, stackwalk)) { ResourceMark rm(THREAD); outputStream* st = Log(stackwalk)::debug_stream(); st->print(" skip "); stream.method()->print_short_name(st); st->cr(); } stream.next(); } // stack frame has been traversed individually and resume stack walk // from the stack frame at depth == skip_frames. for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) { if (log_is_enabled(Debug, stackwalk)) { ResourceMark rm(THREAD); outputStream* st = Log(stackwalk)::debug_stream(); st->print(" skip "); stream.method()->print_short_name(st); st->cr(); } } } int end_index = start_index; int numFrames = 0; if (!stream.at_end()) { numFrames = fill_in_frames(mode, stream, frame_count, start_index, frames_array, end_index, CHECK_NULL); if (numFrames < 1) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL); } } // JVM_CallStackWalk walks the stack and fills in stack frames, then calls to // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk // which calls the implementation to consume the stack frames. // When JVM_CallStackWalk returns, it invalidates the stack stream. JavaValue result(T_OBJECT); JavaCallArguments args(stackStream); args.push_long(stream.address_value()); args.push_int(skip_frames); args.push_int(frame_count); args.push_int(start_index); args.push_int(end_index); // Link the thread and vframe stream into the callee-visible object stream.setup_magic_on_entry(frames_array); JavaCalls::call(&result, m_doStackWalk, &args, THREAD); // Do this before anything else happens, to disable any lingering stream objects bool ok = stream.cleanup_magic_on_exit(frames_array); // Throw pending exception if we must (void) (CHECK_NULL); if (!ok) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", NULL); } // Return normally return (oop)result.get_jobject(); }
// Begins stack walking. // // Parameters: // stackStream StackStream object // mode Stack walking mode. // skip_frames Number of frames to be skipped. // frame_count Number of frames to be traversed. // start_index Start index to the user-supplied buffers. // classes_array Buffer to store classes in, starting at start_index. // frames_array Buffer to store StackFrame in, starting at start_index. // NULL if not used. // // Returns Object returned from AbstractStackWalker::doStackWalk call. // oop StackWalk::walk(Handle stackStream, jlong mode, int skip_frames, int frame_count, int start_index, objArrayHandle classes_array, objArrayHandle frames_array, TRAPS) { JavaThread* jt = (JavaThread*)THREAD; if (TraceStackWalk) { tty->print_cr("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d", mode, skip_frames, frame_count); } if (need_method_info(mode)) { if (frames_array.is_null()) { THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL); } } Klass* stackWalker_klass = SystemDictionary::StackWalker_klass(); Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass(); methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method()); // Open up a traversable stream onto my stack. // This stream will be made available by *reference* to the inner Java call. StackWalkAnchor anchor(jt); vframeStream& vfst = anchor.vframe_stream(); { // Skip all methods from AbstractStackWalker and StackWalk (enclosing method) if (!fill_in_stacktrace(mode)) { while (!vfst.at_end()) { InstanceKlass* ik = vfst.method()->method_holder(); if (ik != stackWalker_klass && ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) { break; } if (TraceStackWalk) { tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n"); } vfst.next(); } } // For exceptions, skip Throwable::fillInStackTrace and <init> methods // of the exception class and superclasses if (fill_in_stacktrace(mode)) { bool skip_to_fillInStackTrace = false; bool skip_throwableInit_check = false; while (!vfst.at_end() && !skip_throwableInit_check) { InstanceKlass* ik = vfst.method()->method_holder(); Method* method = vfst.method(); if (!skip_to_fillInStackTrace) { if (ik == SystemDictionary::Throwable_klass() && method->name() == vmSymbols::fillInStackTrace_name()) { // this frame will be skipped skip_to_fillInStackTrace = true; } } else if (!(ik->is_subclass_of(SystemDictionary::Throwable_klass()) && method->name() == vmSymbols::object_initializer_name())) { // there are none or we've seen them all - either way stop checking skip_throwableInit_check = true; break; } if (TraceStackWalk) { tty->print("stack walk: skip "); vfst.method()->print_short_name(); tty->print("\n"); } vfst.next(); } } // stack frame has been traversed individually and resume stack walk // from the stack frame at depth == skip_frames. for (int n=0; n < skip_frames && !vfst.at_end(); vfst.next(), n++) { if (TraceStackWalk) { tty->print(" skip "); vfst.method()->print_short_name(); tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT, p2i(vfst.frame_id()), p2i(vfst.frame_pc())); } } } // The Method* pointer in the vfst has a very short shelf life. Grab it now. int end_index = start_index; int numFrames = 0; if (!vfst.at_end()) { numFrames = fill_in_frames(mode, vfst, frame_count, start_index, classes_array, frames_array, end_index, CHECK_NULL); if (numFrames < 1) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL); } } // JVM_CallStackWalk walks the stack and fills in stack frames, then calls to // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk // which calls the implementation to consume the stack frames. // When JVM_CallStackWalk returns, it invalidates the stack stream. JavaValue result(T_OBJECT); JavaCallArguments args(stackStream); args.push_long(anchor.address_value()); args.push_int(skip_frames); args.push_int(frame_count); args.push_int(start_index); args.push_int(end_index); // Link the thread and vframe stream into the callee-visible object anchor.setup_magic_on_entry(classes_array); JavaCalls::call(&result, m_doStackWalk, &args, THREAD); // Do this before anything else happens, to disable any lingering stream objects bool ok = anchor.cleanup_magic_on_exit(classes_array); // Throw pending exception if we must (void) (CHECK_NULL); if (!ok) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", NULL); } // Return normally return (oop)result.get_jobject(); }
bool Dictionary::do_unloading() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); bool class_was_unloaded = false; int index = 0; // Defined here for portability! Do not move // Remove unloadable entries and classes from system dictionary // The placeholder array has been handled in always_strong_oops_do. DictionaryEntry* probe = NULL; for (index = 0; index < table_size(); index++) { for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) { probe = *p; Klass* e = probe->klass(); ClassLoaderData* loader_data = probe->loader_data(); InstanceKlass* ik = InstanceKlass::cast(e); // Non-unloadable classes were handled in always_strong_oops_do if (!is_strongly_reachable(loader_data, e)) { // Entry was not visited in phase1 (negated test from phase1) assert(!loader_data->is_the_null_class_loader_data(), "unloading entry with null class loader"); ClassLoaderData* k_def_class_loader_data = ik->class_loader_data(); // Do we need to delete this system dictionary entry? bool purge_entry = false; // Do we need to delete this system dictionary entry? if (loader_data->is_unloading()) { // If the loader is not live this entry should always be // removed (will never be looked up again). Note that this is // not the same as unloading the referred class. if (k_def_class_loader_data == loader_data) { // This is the defining entry, so the referred class is about // to be unloaded. class_was_unloaded = true; } // Also remove this system dictionary entry. purge_entry = true; } else { // The loader in this entry is alive. If the klass is dead, // (determined by checking the defining class loader) // the loader must be an initiating loader (rather than the // defining loader). Remove this entry. if (k_def_class_loader_data->is_unloading()) { // If we get here, the class_loader_data must not be the defining // loader, it must be an initiating one. assert(k_def_class_loader_data != loader_data, "cannot have live defining loader and unreachable klass"); // Loader is live, but class and its defining loader are dead. // Remove the entry. The class is going away. purge_entry = true; } } if (purge_entry) { *p = probe->next(); if (probe == _current_class_entry) { _current_class_entry = NULL; } free_entry(probe); continue; } } p = probe->next_addr(); } } return class_was_unloaded; }
InstanceKlass* interface_at(int index) { return InstanceKlass::cast(_class->local_interfaces()->at(index)); }
int number_of_interfaces() { return _class->local_interfaces()->length(); }
// Begins stack walking. // // Parameters: // stackStream StackStream object // mode Stack walking mode. // skip_frames Number of frames to be skipped. // frame_count Number of frames to be traversed. // start_index Start index to the user-supplied buffers. // frames_array Buffer to store StackFrame in, starting at start_index. // frames array is a Class<?>[] array when only getting caller // reference, and a StackFrameInfo[] array (or derivative) // otherwise. It should never be null. // // Returns Object returned from AbstractStackWalker::doStackWalk call. // oop StackWalk::walk(Handle stackStream, jlong mode, int skip_frames, int frame_count, int start_index, objArrayHandle frames_array, TRAPS) { ResourceMark rm(THREAD); JavaThread* jt = (JavaThread*)THREAD; if (TraceStackWalk) { tty->print_cr("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d", mode, skip_frames, frame_count); } if (frames_array.is_null()) { THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL); } Klass* stackWalker_klass = SystemDictionary::StackWalker_klass(); Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass(); methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method()); // Setup traversal onto my stack. RegisterMap regMap(jt, true); JavaFrameStream stream(jt, ®Map); { while (!stream.at_end()) { InstanceKlass* ik = stream.method()->method_holder(); if (ik != stackWalker_klass && ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) { break; } if (TraceStackWalk) { tty->print(" skip "); stream.method()->print_short_name(); tty->print("\n"); } stream.next(); } // stack frame has been traversed individually and resume stack walk // from the stack frame at depth == skip_frames. for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) { if (TraceStackWalk) { tty->print(" skip "); stream.method()->print_short_name(); tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT, p2i(stream.java_frame()->fr().id()), p2i(stream.java_frame()->fr().pc())); } } } int end_index = start_index; int numFrames = 0; if (!stream.at_end()) { numFrames = fill_in_frames(mode, stream, frame_count, start_index, frames_array, end_index, CHECK_NULL); if (numFrames < 1) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL); } } // JVM_CallStackWalk walks the stack and fills in stack frames, then calls to // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk // which calls the implementation to consume the stack frames. // When JVM_CallStackWalk returns, it invalidates the stack stream. JavaValue result(T_OBJECT); JavaCallArguments args(stackStream); args.push_long(stream.address_value()); args.push_int(skip_frames); args.push_int(frame_count); args.push_int(start_index); args.push_int(end_index); // Link the thread and vframe stream into the callee-visible object stream.setup_magic_on_entry(frames_array); JavaCalls::call(&result, m_doStackWalk, &args, THREAD); // Do this before anything else happens, to disable any lingering stream objects bool ok = stream.cleanup_magic_on_exit(frames_array); // Throw pending exception if we must (void) (CHECK_NULL); if (!ok) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", NULL); } // Return normally return (oop)result.get_jobject(); }
InstanceKlass* next_super() { return _class->java_super(); }
bool visit() { InstanceKlass* cls = current_class(); streamIndentor si(tty, current_depth() * 2); tty->indent().print_cr("%s", cls->name()->as_C_string()); return true; }
static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots( InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS) { assert(klass != NULL, "Must be valid class"); GrowableArray<EmptyVtableSlot*>* slots = new GrowableArray<EmptyVtableSlot*>(); // All miranda methods are obvious candidates for (int i = 0; i < mirandas->length(); ++i) { Method* m = mirandas->at(i); if (!already_in_vtable_slots(slots, m)) { slots->append(new EmptyVtableSlot(m)); } } // Also any overpasses in our superclasses, that we haven't implemented. // (can't use the vtable because it is not guaranteed to be initialized yet) InstanceKlass* super = klass->java_super(); while (super != NULL) { for (int i = 0; i < super->methods()->length(); ++i) { Method* m = super->methods()->at(i); if (m->is_overpass() || m->is_static()) { // m is a method that would have been a miranda if not for the // default method processing that occurred on behalf of our superclass, // so it's a method we want to re-examine in this new context. That is, // unless we have a real implementation of it in the current class. Method* impl = klass->lookup_method(m->name(), m->signature()); if (impl == NULL || impl->is_overpass() || impl->is_static()) { if (!already_in_vtable_slots(slots, m)) { slots->append(new EmptyVtableSlot(m)); } } } } // also any default methods in our superclasses if (super->default_methods() != NULL) { for (int i = 0; i < super->default_methods()->length(); ++i) { Method* m = super->default_methods()->at(i); // m is a method that would have been a miranda if not for the // default method processing that occurred on behalf of our superclass, // so it's a method we want to re-examine in this new context. That is, // unless we have a real implementation of it in the current class. Method* impl = klass->lookup_method(m->name(), m->signature()); if (impl == NULL || impl->is_overpass() || impl->is_static()) { if (!already_in_vtable_slots(slots, m)) { slots->append(new EmptyVtableSlot(m)); } } } } super = super->java_super(); } #ifndef PRODUCT if (TraceDefaultMethods) { tty->print_cr("Slots that need filling:"); streamIndentor si(tty); for (int i = 0; i < slots->length(); ++i) { tty->indent(); slots->at(i)->print_on(tty); tty->cr(); } } #endif // ndef PRODUCT return slots; }
// ------------------------------------------------------------------ // ciInstanceKlass::ciInstanceKlass // // Loaded instance klass. ciInstanceKlass::ciInstanceKlass(KlassHandle h_k) : ciKlass(h_k) { assert(get_Klass()->oop_is_instance(), "wrong type"); assert(get_instanceKlass()->is_loaded(), "must be at least loaded"); InstanceKlass* ik = get_instanceKlass(); AccessFlags access_flags = ik->access_flags(); _flags = ciFlags(access_flags); _has_finalizer = access_flags.has_finalizer(); _has_subklass = ik->subklass() != NULL; _init_state = ik->init_state(); _nonstatic_field_size = ik->nonstatic_field_size(); _has_nonstatic_fields = ik->has_nonstatic_fields(); _has_default_methods = ik->has_default_methods(); _nonstatic_fields = NULL; // initialized lazily by compute_nonstatic_fields: _has_injected_fields = -1; _implementor = NULL; // we will fill these lazily Thread *thread = Thread::current(); if (ciObjectFactory::is_initialized()) { _loader = JNIHandles::make_local(thread, ik->class_loader()); _protection_domain = JNIHandles::make_local(thread, ik->protection_domain()); _is_shared = false; } else { Handle h_loader(thread, ik->class_loader()); Handle h_protection_domain(thread, ik->protection_domain()); _loader = JNIHandles::make_global(h_loader); _protection_domain = JNIHandles::make_global(h_protection_domain); _is_shared = true; } // Lazy fields get filled in only upon request. _super = NULL; _java_mirror = NULL; if (is_shared()) { if (h_k() != SystemDictionary::Object_klass()) { super(); } //compute_nonstatic_fields(); // done outside of constructor } _field_cache = NULL; }