8349088: De-virtualize Codeblob and nmethod

Co-authored-by: Stefan Karlsson <stefank@openjdk.org>
Co-authored-by: Chris Plummer <cjplummer@openjdk.org>
Reviewed-by: cjplummer, aboldtch, dlong
This commit is contained in:
Vladimir Kozlov 2025-02-18 20:08:08 +00:00
parent 62d93f2a22
commit 46d4a601e0
23 changed files with 377 additions and 267 deletions

View File

@ -53,6 +53,53 @@
#include "c1/c1_Runtime1.hpp"
#endif
#include <type_traits>
// Virtual methods are not allowed in code blobs to simplify caching compiled code.
// Check all "leaf" subclasses of CodeBlob class.
static_assert(!std::is_polymorphic<nmethod>::value, "no virtual methods are allowed in nmethod");
static_assert(!std::is_polymorphic<AdapterBlob>::value, "no virtual methods are allowed in code blobs");
static_assert(!std::is_polymorphic<VtableBlob>::value, "no virtual methods are allowed in code blobs");
static_assert(!std::is_polymorphic<MethodHandlesAdapterBlob>::value, "no virtual methods are allowed in code blobs");
static_assert(!std::is_polymorphic<RuntimeStub>::value, "no virtual methods are allowed in code blobs");
static_assert(!std::is_polymorphic<DeoptimizationBlob>::value, "no virtual methods are allowed in code blobs");
static_assert(!std::is_polymorphic<SafepointBlob>::value, "no virtual methods are allowed in code blobs");
static_assert(!std::is_polymorphic<UpcallStub>::value, "no virtual methods are allowed in code blobs");
#ifdef COMPILER2
static_assert(!std::is_polymorphic<ExceptionBlob>::value, "no virtual methods are allowed in code blobs");
static_assert(!std::is_polymorphic<UncommonTrapBlob>::value, "no virtual methods are allowed in code blobs");
#endif
// Add proxy vtables.
// We need only few for now - they are used only from prints.
const nmethod::Vptr nmethod::_vptr;
const BufferBlob::Vptr BufferBlob::_vptr;
const RuntimeStub::Vptr RuntimeStub::_vptr;
const SingletonBlob::Vptr SingletonBlob::_vptr;
const DeoptimizationBlob::Vptr DeoptimizationBlob::_vptr;
const UpcallStub::Vptr UpcallStub::_vptr;
const CodeBlob::Vptr* CodeBlob::vptr() const {
constexpr const CodeBlob::Vptr* array[(size_t)CodeBlobKind::Number_Of_Kinds] = {
nullptr/* None */,
&nmethod::_vptr,
&BufferBlob::_vptr,
&AdapterBlob::_vptr,
&VtableBlob::_vptr,
&MethodHandlesAdapterBlob::_vptr,
&RuntimeStub::_vptr,
&DeoptimizationBlob::_vptr,
&SafepointBlob::_vptr,
#ifdef COMPILER2
&ExceptionBlob::_vptr,
&UncommonTrapBlob::_vptr,
#endif
&UpcallStub::_vptr
};
return array[(size_t)_kind];
}
unsigned int CodeBlob::align_code_offset(int offset) {
// align the size to CodeEntryAlignment
@ -386,7 +433,7 @@ RuntimeStub::RuntimeStub(
OopMapSet* oop_maps,
bool caller_must_gc_arguments
)
: RuntimeBlob(name, CodeBlobKind::Runtime_Stub, cb, size, sizeof(RuntimeStub),
: RuntimeBlob(name, CodeBlobKind::RuntimeStub, cb, size, sizeof(RuntimeStub),
frame_complete, frame_size, oop_maps, caller_must_gc_arguments)
{
}
@ -482,18 +529,18 @@ DeoptimizationBlob* DeoptimizationBlob::create(
return blob;
}
#ifdef COMPILER2
//----------------------------------------------------------------------------------------------------
// Implementation of UncommonTrapBlob
#ifdef COMPILER2
UncommonTrapBlob::UncommonTrapBlob(
CodeBuffer* cb,
int size,
OopMapSet* oop_maps,
int frame_size
)
: SingletonBlob("UncommonTrapBlob", CodeBlobKind::Uncommon_Trap, cb,
: SingletonBlob("UncommonTrapBlob", CodeBlobKind::UncommonTrap, cb,
size, sizeof(UncommonTrapBlob), frame_size, oop_maps)
{}
@ -516,14 +563,9 @@ UncommonTrapBlob* UncommonTrapBlob::create(
return blob;
}
#endif // COMPILER2
//----------------------------------------------------------------------------------------------------
// Implementation of ExceptionBlob
#ifdef COMPILER2
ExceptionBlob::ExceptionBlob(
CodeBuffer* cb,
int size,
@ -553,10 +595,8 @@ ExceptionBlob* ExceptionBlob::create(
return blob;
}
#endif // COMPILER2
//----------------------------------------------------------------------------------------------------
// Implementation of SafepointBlob
@ -644,17 +684,45 @@ void UpcallStub::free(UpcallStub* blob) {
//----------------------------------------------------------------------------------------------------
// Verification and printing
void CodeBlob::verify() {
if (is_nmethod()) {
as_nmethod()->verify();
}
}
void CodeBlob::print_on(outputStream* st) const {
st->print_cr("[CodeBlob (" INTPTR_FORMAT ")]", p2i(this));
st->print_cr("Framesize: %d", _frame_size);
vptr()->print_on(this, st);
}
void CodeBlob::print() const { print_on(tty); }
void CodeBlob::print_value_on(outputStream* st) const {
vptr()->print_value_on(this, st);
}
void CodeBlob::print_on_impl(outputStream* st) const {
st->print_cr("[CodeBlob (" INTPTR_FORMAT ")]", p2i(this));
st->print_cr("Framesize: %d", _frame_size);
}
void CodeBlob::print_value_on_impl(outputStream* st) const {
st->print_cr("[CodeBlob]");
}
void CodeBlob::print_block_comment(outputStream* stream, address block_begin) const {
#if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY)
if (is_nmethod()) {
as_nmethod()->print_nmethod_labels(stream, block_begin);
}
#endif
#ifndef PRODUCT
ptrdiff_t offset = block_begin - code_begin();
assert(offset >= 0, "Expecting non-negative offset!");
_asm_remarks.print(uint(offset), stream);
#endif
}
void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const {
if (is_buffer_blob() || is_adapter_blob() || is_vtable_blob() || is_method_handles_adapter_blob()) {
// the interpreter is generated into a buffer blob
@ -708,7 +776,7 @@ void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const
// verbose is only ever true when called from findpc in debug.cpp
nm->print_nmethod(true);
} else {
nm->print(st);
nm->print_on(st);
}
return;
}
@ -716,61 +784,45 @@ void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const
print_on(st);
}
void BufferBlob::verify() {
// unimplemented
void BufferBlob::print_on_impl(outputStream* st) const {
RuntimeBlob::print_on_impl(st);
print_value_on_impl(st);
}
void BufferBlob::print_on(outputStream* st) const {
RuntimeBlob::print_on(st);
print_value_on(st);
}
void BufferBlob::print_value_on(outputStream* st) const {
void BufferBlob::print_value_on_impl(outputStream* st) const {
st->print_cr("BufferBlob (" INTPTR_FORMAT ") used for %s", p2i(this), name());
}
void RuntimeStub::verify() {
// unimplemented
}
void RuntimeStub::print_on(outputStream* st) const {
void RuntimeStub::print_on_impl(outputStream* st) const {
ttyLocker ttyl;
RuntimeBlob::print_on(st);
RuntimeBlob::print_on_impl(st);
st->print("Runtime Stub (" INTPTR_FORMAT "): ", p2i(this));
st->print_cr("%s", name());
Disassembler::decode((RuntimeBlob*)this, st);
}
void RuntimeStub::print_value_on(outputStream* st) const {
void RuntimeStub::print_value_on_impl(outputStream* st) const {
st->print("RuntimeStub (" INTPTR_FORMAT "): ", p2i(this)); st->print("%s", name());
}
void SingletonBlob::verify() {
// unimplemented
}
void SingletonBlob::print_on(outputStream* st) const {
void SingletonBlob::print_on_impl(outputStream* st) const {
ttyLocker ttyl;
RuntimeBlob::print_on(st);
RuntimeBlob::print_on_impl(st);
st->print_cr("%s", name());
Disassembler::decode((RuntimeBlob*)this, st);
}
void SingletonBlob::print_value_on(outputStream* st) const {
void SingletonBlob::print_value_on_impl(outputStream* st) const {
st->print_cr("%s", name());
}
void DeoptimizationBlob::print_value_on(outputStream* st) const {
void DeoptimizationBlob::print_value_on_impl(outputStream* st) const {
st->print_cr("Deoptimization (frame not available)");
}
void UpcallStub::verify() {
// unimplemented
}
void UpcallStub::print_on(outputStream* st) const {
RuntimeBlob::print_on(st);
print_value_on(st);
void UpcallStub::print_on_impl(outputStream* st) const {
RuntimeBlob::print_on_impl(st);
print_value_on_impl(st);
st->print_cr("Frame data offset: %d", (int) _frame_data_offset);
oop recv = JNIHandles::resolve(_receiver);
st->print("Receiver MH=");
@ -778,6 +830,6 @@ void UpcallStub::print_on(outputStream* st) const {
Disassembler::decode((RuntimeBlob*)this, st);
}
void UpcallStub::print_value_on(outputStream* st) const {
void UpcallStub::print_value_on_impl(outputStream* st) const {
st->print_cr("UpcallStub (" INTPTR_FORMAT ") used for %s", p2i(this), name());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -61,8 +61,8 @@ enum class CodeBlobType {
// RuntimeStub : Call to VM runtime methods
// SingletonBlob : Super-class for all blobs that exist in only one instance
// DeoptimizationBlob : Used for deoptimization
// ExceptionBlob : Used for stack unrolling
// SafepointBlob : Used to handle illegal instruction exceptions
// ExceptionBlob : Used for stack unrolling
// UncommonTrapBlob : Used to handle uncommon traps
// UpcallStub : Used for upcalls from native code
//
@ -80,12 +80,14 @@ enum class CodeBlobKind : u1 {
Buffer,
Adapter,
Vtable,
MH_Adapter,
Runtime_Stub,
MHAdapter,
RuntimeStub,
Deoptimization,
Exception,
Safepoint,
Uncommon_Trap,
#ifdef COMPILER2
Exception,
UncommonTrap,
#endif
Upcall,
Number_Of_Kinds
};
@ -128,6 +130,17 @@ protected:
DbgStrings _dbg_strings;
#endif
void print_on_impl(outputStream* st) const;
void print_value_on_impl(outputStream* st) const;
class Vptr {
public:
virtual void print_on(const CodeBlob* instance, outputStream* st) const = 0;
virtual void print_value_on(const CodeBlob* instance, outputStream* st) const = 0;
};
const Vptr* vptr() const;
CodeBlob(const char* name, CodeBlobKind kind, CodeBuffer* cb, int size, uint16_t header_size,
int16_t frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments);
@ -138,7 +151,7 @@ protected:
public:
virtual ~CodeBlob() {
~CodeBlob() {
assert(_oop_maps == nullptr, "Not flushed");
}
@ -152,20 +165,25 @@ public:
// Typing
bool is_nmethod() const { return _kind == CodeBlobKind::Nmethod; }
bool is_buffer_blob() const { return _kind == CodeBlobKind::Buffer; }
bool is_runtime_stub() const { return _kind == CodeBlobKind::Runtime_Stub; }
bool is_runtime_stub() const { return _kind == CodeBlobKind::RuntimeStub; }
bool is_deoptimization_stub() const { return _kind == CodeBlobKind::Deoptimization; }
bool is_uncommon_trap_stub() const { return _kind == CodeBlobKind::Uncommon_Trap; }
#ifdef COMPILER2
bool is_uncommon_trap_stub() const { return _kind == CodeBlobKind::UncommonTrap; }
bool is_exception_stub() const { return _kind == CodeBlobKind::Exception; }
#else
bool is_uncommon_trap_stub() const { return false; }
bool is_exception_stub() const { return false; }
#endif
bool is_safepoint_stub() const { return _kind == CodeBlobKind::Safepoint; }
bool is_adapter_blob() const { return _kind == CodeBlobKind::Adapter; }
bool is_vtable_blob() const { return _kind == CodeBlobKind::Vtable; }
bool is_method_handles_adapter_blob() const { return _kind == CodeBlobKind::MH_Adapter; }
bool is_method_handles_adapter_blob() const { return _kind == CodeBlobKind::MHAdapter; }
bool is_upcall_stub() const { return _kind == CodeBlobKind::Upcall; }
// Casting
nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : nullptr; }
nmethod* as_nmethod() { assert(is_nmethod(), "must be nmethod"); return (nmethod*) this; }
CodeBlob* as_codeblob_or_null() const { return (CodeBlob*) this; }
nmethod* as_nmethod_or_null() const { return is_nmethod() ? (nmethod*) this : nullptr; }
nmethod* as_nmethod() const { assert(is_nmethod(), "must be nmethod"); return (nmethod*) this; }
CodeBlob* as_codeblob() const { return (CodeBlob*) this; }
UpcallStub* as_upcall_stub() const { assert(is_upcall_stub(), "must be upcall stub"); return (UpcallStub*) this; }
RuntimeStub* as_runtime_stub() const { assert(is_runtime_stub(), "must be runtime blob"); return (RuntimeStub*) this; }
@ -233,21 +251,16 @@ public:
void set_name(const char* name) { _name = name; }
// Debugging
virtual void verify() = 0;
virtual void print() const;
virtual void print_on(outputStream* st) const;
virtual void print_value_on(outputStream* st) const;
void verify();
void print() const;
void print_on(outputStream* st) const;
void print_value_on(outputStream* st) const;
void dump_for_addr(address addr, outputStream* st, bool verbose) const;
void print_code_on(outputStream* st);
// Print to stream, any comments associated with offset.
virtual void print_block_comment(outputStream* stream, address block_begin) const {
#ifndef PRODUCT
ptrdiff_t offset = block_begin - code_begin();
assert(offset >= 0, "Expecting non-negative offset!");
_asm_remarks.print(uint(offset), stream);
#endif
}
void print_block_comment(outputStream* stream, address block_begin) const;
#ifndef PRODUCT
AsmRemarks &asm_remarks() { return _asm_remarks; }
@ -290,6 +303,9 @@ class RuntimeBlob : public CodeBlob {
// Deal with Disassembler, VTune, Forte, JvmtiExport, MemoryService.
static void trace_new_stub(RuntimeBlob* blob, const char* name1, const char* name2 = "");
class Vptr : public CodeBlob::Vptr {
};
};
class WhiteBox;
@ -318,11 +334,19 @@ class BufferBlob: public RuntimeBlob {
static void free(BufferBlob* buf);
// Verification support
void verify() override;
void print_on_impl(outputStream* st) const;
void print_value_on_impl(outputStream* st) const;
void print_on(outputStream* st) const override;
void print_value_on(outputStream* st) const override;
class Vptr : public RuntimeBlob::Vptr {
void print_on(const CodeBlob* instance, outputStream* st) const override {
((const BufferBlob*)instance)->print_on_impl(st);
}
void print_value_on(const CodeBlob* instance, outputStream* st) const override {
((const BufferBlob*)instance)->print_value_on_impl(st);
}
};
static const Vptr _vptr;
};
@ -355,7 +379,7 @@ public:
class MethodHandlesAdapterBlob: public BufferBlob {
private:
MethodHandlesAdapterBlob(int size): BufferBlob("MethodHandles adapters", CodeBlobKind::MH_Adapter, size) {}
MethodHandlesAdapterBlob(int size): BufferBlob("MethodHandles adapters", CodeBlobKind::MHAdapter, size) {}
public:
// Creation
@ -396,13 +420,21 @@ class RuntimeStub: public RuntimeBlob {
static void free(RuntimeStub* stub) { RuntimeBlob::free(stub); }
address entry_point() const { return code_begin(); }
address entry_point() const { return code_begin(); }
// Verification support
void verify() override;
void print_on_impl(outputStream* st) const;
void print_value_on_impl(outputStream* st) const;
void print_on(outputStream* st) const override;
void print_value_on(outputStream* st) const override;
class Vptr : public RuntimeBlob::Vptr {
void print_on(const CodeBlob* instance, outputStream* st) const override {
instance->as_runtime_stub()->print_on_impl(st);
}
void print_value_on(const CodeBlob* instance, outputStream* st) const override {
instance->as_runtime_stub()->print_value_on_impl(st);
}
};
static const Vptr _vptr;
};
@ -430,11 +462,19 @@ class SingletonBlob: public RuntimeBlob {
address entry_point() { return code_begin(); }
// Verification support
void verify() override; // does nothing
void print_on_impl(outputStream* st) const;
void print_value_on_impl(outputStream* st) const;
void print_on(outputStream* st) const override;
void print_value_on(outputStream* st) const override;
class Vptr : public RuntimeBlob::Vptr {
void print_on(const CodeBlob* instance, outputStream* st) const override {
((const SingletonBlob*)instance)->print_on_impl(st);
}
void print_value_on(const CodeBlob* instance, outputStream* st) const override {
((const SingletonBlob*)instance)->print_value_on_impl(st);
}
};
static const Vptr _vptr;
};
@ -479,9 +519,6 @@ class DeoptimizationBlob: public SingletonBlob {
int frame_size
);
// Printing
void print_value_on(outputStream* st) const override;
address unpack() const { return code_begin() + _unpack_offset; }
address unpack_with_exception() const { return code_begin() + _unpack_with_exception; }
address unpack_with_reexecution() const { return code_begin() + _unpack_with_reexecution; }
@ -511,6 +548,16 @@ class DeoptimizationBlob: public SingletonBlob {
}
address implicit_exception_uncommon_trap() const { return code_begin() + _implicit_exception_uncommon_trap_offset; }
#endif // INCLUDE_JVMCI
void print_value_on_impl(outputStream* st) const;
class Vptr : public SingletonBlob::Vptr {
void print_value_on(const CodeBlob* instance, outputStream* st) const override {
((const DeoptimizationBlob*)instance)->print_value_on_impl(st);
}
};
static const Vptr _vptr;
};
@ -623,13 +670,22 @@ class UpcallStub: public RuntimeBlob {
JavaFrameAnchor* jfa_for_frame(const frame& frame) const;
// GC/Verification support
// GC support
void oops_do(OopClosure* f, const frame& frame);
void verify() override;
// Misc.
void print_on(outputStream* st) const override;
void print_value_on(outputStream* st) const override;
void print_on_impl(outputStream* st) const;
void print_value_on_impl(outputStream* st) const;
class Vptr : public RuntimeBlob::Vptr {
void print_on(const CodeBlob* instance, outputStream* st) const override {
instance->as_upcall_stub()->print_on_impl(st);
}
void print_value_on(const CodeBlob* instance, outputStream* st) const override {
instance->as_upcall_stub()->print_value_on_impl(st);
}
};
static const Vptr _vptr;
};
#endif // SHARE_CODE_CODEBLOB_HPP

View File

@ -218,7 +218,7 @@ void DependencyContext::print_dependent_nmethods(bool verbose) {
nmethod* nm = b->get_nmethod();
tty->print("[%d] { ", idx++);
if (!verbose) {
nm->print_on(tty, "nmethod");
nm->print_on_with_msg(tty, "nmethod");
tty->print_cr(" } ");
} else {
nm->print();

View File

@ -1619,7 +1619,7 @@ void nmethod::log_new_nmethod() const {
// Print out more verbose output usually for a newly created nmethod.
void nmethod::print_on(outputStream* st, const char* msg) const {
void nmethod::print_on_with_msg(outputStream* st, const char* msg) const {
if (st != nullptr) {
ttyLocker ttyl;
if (WizardMode) {
@ -1971,7 +1971,7 @@ void nmethod::log_state_change() const {
CompileTask::print_ul(this, "made not entrant");
if (PrintCompilation) {
print_on(tty, "made not entrant");
print_on_with_msg(tty, "made not entrant");
}
}
@ -3033,12 +3033,7 @@ void nmethod::verify_scopes() {
// -----------------------------------------------------------------------------
// Printing operations
void nmethod::print() const {
ttyLocker ttyl; // keep the following output all in one block
print(tty);
}
void nmethod::print(outputStream* st) const {
void nmethod::print_on_impl(outputStream* st) const {
ResourceMark rm;
st->print("Compiled method ");
@ -3053,7 +3048,7 @@ void nmethod::print(outputStream* st) const {
st->print("(n/a) ");
}
print_on(st, nullptr);
print_on_with_msg(st, nullptr);
if (WizardMode) {
st->print("((nmethod*) " INTPTR_FORMAT ") ", p2i(this));
@ -3404,7 +3399,7 @@ void nmethod::decode2(outputStream* ost) const {
#endif
st->cr();
this->print(st);
this->print_on(st);
st->cr();
#if defined(SUPPORT_ASSEMBLY)
@ -3953,12 +3948,12 @@ address nmethod::call_instruction_address(address pc) const {
return nullptr;
}
void nmethod::print_value_on_impl(outputStream* st) const {
st->print_cr("nmethod");
#if defined(SUPPORT_DATA_STRUCTS)
void nmethod::print_value_on(outputStream* st) const {
st->print("nmethod");
print_on(st, nullptr);
}
print_on_with_msg(st, nullptr);
#endif
}
#ifndef PRODUCT

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -900,7 +900,7 @@ public:
void post_compiled_method_load_event(JvmtiThreadState* state = nullptr);
// verify operations
void verify() override;
void verify();
void verify_scopes();
void verify_interrupt_point(address interrupt_point, bool is_inline_cache);
@ -912,9 +912,9 @@ public:
void decode(outputStream* st) const { decode2(st); } // just delegate here.
// printing support
void print() const override;
void print(outputStream* st) const;
void print_on_impl(outputStream* st) const;
void print_code();
void print_value_on_impl(outputStream* st) const;
#if defined(SUPPORT_DATA_STRUCTS)
// print output in opt build for disassembler library
@ -922,7 +922,6 @@ public:
void print_pcs_on(outputStream* st);
void print_scopes() { print_scopes_on(tty); }
void print_scopes_on(outputStream* st) PRODUCT_RETURN;
void print_value_on(outputStream* st) const override;
void print_handler_table();
void print_nul_chk_table();
void print_recorded_oop(int log_n, int index);
@ -941,9 +940,7 @@ public:
void maybe_print_nmethod(const DirectiveSet* directive);
void print_nmethod(bool print_code);
// need to re-define this from CodeBlob else the overload hides it
void print_on(outputStream* st) const override { CodeBlob::print_on(st); }
void print_on(outputStream* st, const char* msg) const;
void print_on_with_msg(outputStream* st, const char* msg) const;
// Logging
void log_identity(xmlStream* log) const;
@ -951,13 +948,6 @@ public:
void log_state_change() const;
// Prints block-level comments, including nmethod specific block labels:
void print_block_comment(outputStream* stream, address block_begin) const override {
#if defined(SUPPORT_ASSEMBLY) || defined(SUPPORT_ABSTRACT_ASSEMBLY)
print_nmethod_labels(stream, block_begin);
CodeBlob::print_block_comment(stream, block_begin);
#endif
}
void print_nmethod_labels(outputStream* stream, address block_begin, bool print_section_labels=true) const;
const char* nmethod_section_label(address pos) const;
@ -995,6 +985,18 @@ public:
void make_deoptimized();
void finalize_relocations();
class Vptr : public CodeBlob::Vptr {
void print_on(const CodeBlob* instance, outputStream* st) const override {
ttyLocker ttyl;
instance->as_nmethod()->print_on_impl(st);
}
void print_value_on(const CodeBlob* instance, outputStream* st) const override {
instance->as_nmethod()->print_value_on_impl(st);
}
};
static const Vptr _vptr;
};
#endif // SHARE_CODE_NMETHOD_HPP

View File

@ -549,6 +549,7 @@
\
nonstatic_field(CodeBlob, _name, const char*) \
nonstatic_field(CodeBlob, _size, int) \
nonstatic_field(CodeBlob, _kind, CodeBlobKind) \
nonstatic_field(CodeBlob, _header_size, u2) \
nonstatic_field(CodeBlob, _relocation_size, int) \
nonstatic_field(CodeBlob, _content_offset, int) \
@ -1916,6 +1917,7 @@
\
declare_integer_type(CompLevel) \
declare_integer_type(ByteSize) \
declare_integer_type(CodeBlobKind) \
JVMTI_ONLY(declare_toplevel_type(BreakpointInfo)) \
JVMTI_ONLY(declare_toplevel_type(BreakpointInfo*)) \
declare_toplevel_type(CodeBlob*) \
@ -2373,6 +2375,23 @@
declare_constant(CompLevel_full_profile) \
declare_constant(CompLevel_full_optimization) \
\
/****************/ \
/* CodeBlobKind */ \
/****************/ \
\
declare_constant(CodeBlobKind::Nmethod) \
declare_constant(CodeBlobKind::Buffer) \
declare_constant(CodeBlobKind::Adapter) \
declare_constant(CodeBlobKind::Vtable) \
declare_constant(CodeBlobKind::MHAdapter) \
declare_constant(CodeBlobKind::RuntimeStub) \
declare_constant(CodeBlobKind::Deoptimization) \
declare_constant(CodeBlobKind::Safepoint) \
COMPILER2_PRESENT(declare_constant(CodeBlobKind::Exception)) \
COMPILER2_PRESENT(declare_constant(CodeBlobKind::UncommonTrap)) \
declare_constant(CodeBlobKind::Upcall) \
declare_constant(CodeBlobKind::Number_Of_Kinds) \
\
/***************/ \
/* OopMapValue */ \
/***************/ \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -62,6 +62,6 @@ public class Runtime1 {
/** FIXME: consider making argument "type-safe" in Java port */
public CodeBlob blobFor(int id) {
Address blobAddr = blobsField.getStaticFieldAddress().getAddressAt(id * VM.getVM().getAddressSize());
return VM.getVM().getCodeCache().createCodeBlobWrapper(blobAddr);
return VM.getVM().getCodeCache().createCodeBlobWrapper(blobAddr, blobAddr);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -50,10 +50,6 @@ public class AdapterBlob extends RuntimeBlob {
super(addr);
}
public boolean isAdapterBlob() {
return true;
}
public String getName() {
return "AdapterBlob: " + super.getName();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -49,8 +49,4 @@ public class BufferBlob extends RuntimeBlob {
public BufferBlob(Address addr) {
super(addr);
}
public boolean isBufferBlob() {
return true;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,6 +43,7 @@ import sun.jvm.hotspot.utilities.Observer;
public class CodeBlob extends VMObject {
private static AddressField nameField;
private static CIntegerField sizeField;
private static CIntegerField kindField;
private static CIntegerField relocationSizeField;
private static CIntField headerSizeField;
private static CIntegerField contentOffsetField;
@ -52,6 +53,22 @@ public class CodeBlob extends VMObject {
private static CIntegerField frameSizeField;
private static AddressField oopMapsField;
// Kinds of Codeblob
private static int NMethodKind;
private static int BufferKind;
private static int AdapterKind;
private static int VtableKind;
private static int MHAdapterKind;
private static int RuntimeStubKind;
private static int DeoptimizationKind;
private static int ExceptionKind;
private static int SafepointKind;
private static int UncommonTrapKind;
private static int UpcallKind;
private static int NumberOfKinds;
private static Class[] wrapperClasses;
public CodeBlob(Address addr) {
super(addr);
}
@ -63,6 +80,7 @@ public class CodeBlob extends VMObject {
nameField = type.getAddressField("_name");
sizeField = type.getCIntegerField("_size");
kindField = type.getCIntegerField("_kind");
relocationSizeField = type.getCIntegerField("_relocation_size");
headerSizeField = new CIntField(type.getCIntegerField("_header_size"), 0);
contentOffsetField = type.getCIntegerField("_content_offset");
@ -76,6 +94,40 @@ public class CodeBlob extends VMObject {
matcherInterpreterFramePointerReg =
db.lookupIntConstant("Matcher::interpreter_frame_pointer_reg").intValue();
}
NMethodKind = db.lookupIntConstant("CodeBlobKind::Nmethod").intValue();
BufferKind = db.lookupIntConstant("CodeBlobKind::Buffer").intValue();
AdapterKind = db.lookupIntConstant("CodeBlobKind::Adapter").intValue();
VtableKind = db.lookupIntConstant("CodeBlobKind::Vtable").intValue();
MHAdapterKind = db.lookupIntConstant("CodeBlobKind::MHAdapter").intValue();
RuntimeStubKind = db.lookupIntConstant("CodeBlobKind::RuntimeStub").intValue();
DeoptimizationKind = db.lookupIntConstant("CodeBlobKind::Deoptimization").intValue();
SafepointKind = db.lookupIntConstant("CodeBlobKind::Safepoint").intValue();
UpcallKind = db.lookupIntConstant("CodeBlobKind::Upcall").intValue();
NumberOfKinds = db.lookupIntConstant("CodeBlobKind::Number_Of_Kinds").intValue();
if (VM.getVM().isServerCompiler()) {
ExceptionKind = db.lookupIntConstant("CodeBlobKind::Exception").intValue();
UncommonTrapKind = db.lookupIntConstant("CodeBlobKind::UncommonTrap").intValue();
} else {
// Set invalid value to not match default.
ExceptionKind = NumberOfKinds + 1;
UncommonTrapKind = NumberOfKinds + 1;
}
wrapperClasses = new Class[NumberOfKinds];
wrapperClasses[NMethodKind] = NMethod.class;
wrapperClasses[BufferKind] = BufferBlob.class;
wrapperClasses[AdapterKind] = AdapterBlob.class;
wrapperClasses[VtableKind] = VtableBlob.class;
wrapperClasses[MHAdapterKind] = MethodHandlesAdapterBlob.class;
wrapperClasses[RuntimeStubKind] = RuntimeStub.class;
wrapperClasses[DeoptimizationKind] = DeoptimizationBlob.class;
wrapperClasses[SafepointKind] = SafepointBlob.class;
wrapperClasses[UpcallKind] = UpcallStub.class;
if (VM.getVM().isServerCompiler()) {
wrapperClasses[ExceptionKind] = ExceptionBlob.class;
wrapperClasses[UncommonTrapKind] = UncommonTrapBlob.class;
}
}
static {
@ -86,6 +138,11 @@ public class CodeBlob extends VMObject {
});
}
public static Class<?> getClassFor(Address addr) {
CodeBlob cb = new CodeBlob(addr);
return wrapperClasses[cb.getKind()];
}
public Address headerBegin() { return getAddress(); }
public Address headerEnd() { return getAddress().addOffsetTo(getHeaderSize()); }
@ -124,6 +181,10 @@ public class CodeBlob extends VMObject {
return CStringUtilities.getString(nameField.getValue(addr));
}
public int getKind() {
return (int) kindField.getValue(addr);
}
/** OopMap for frame; can return null if none available */
public ImmutableOopMapSet getOopMaps() {
Address value = oopMapsField.getValue(addr);
@ -135,27 +196,29 @@ public class CodeBlob extends VMObject {
// Typing
public boolean isBufferBlob() { return false; }
public boolean isBufferBlob() { return getKind() == BufferKind; }
public boolean isCompiled() { return false; }
public boolean isNMethod() { return getKind() == NMethodKind; }
public boolean isNMethod() { return false; }
public boolean isRuntimeStub() { return getKind() == RuntimeStubKind; }
public boolean isRuntimeStub() { return false; }
public boolean isUpcallStub() { return getKind() == UpcallKind; }
public boolean isUpcallStub() { return false; }
public boolean isDeoptimizationBlob() { return getKind() == DeoptimizationKind; }
public boolean isDeoptimizationStub() { return false; }
public boolean isUncommonTrapBlob() { return getKind() == UncommonTrapKind; }
public boolean isUncommonTrapStub() { return false; }
public boolean isExceptionBlob() { return getKind() == ExceptionKind; }
public boolean isExceptionStub() { return false; }
public boolean isSafepointBlob() { return getKind() == SafepointKind; }
public boolean isSafepointStub() { return false; }
public boolean isAdapterBlob() { return getKind() == AdapterKind; }
public boolean isAdapterBlob() { return false; }
public boolean isMHAdapterBlob() { return getKind() == MHAdapterKind; }
// Fine grain nmethod support: isNmethod() == isJavaMethod() || isNativeMethod() || isOSRMethod()
public boolean isVtableBlob() { return getKind() == VtableKind; }
// Fine grain nmethod support: isNMethod() == isJavaMethod() || isNativeMethod() || isOSRMethod()
public boolean isJavaMethod() { return false; }
public boolean isNativeMethod() { return false; }

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,7 +35,6 @@ import sun.jvm.hotspot.utilities.Observer;
public class CodeCache {
private static GrowableArray<CodeHeap> heapArray;
private static VirtualConstructor virtualConstructor;
static {
VM.registerVMInitializedObserver(new Observer() {
@ -51,22 +50,6 @@ public class CodeCache {
// Get array of CodeHeaps
AddressField heapsField = type.getAddressField("_heaps");
heapArray = GrowableArray.create(heapsField.getValue(), new StaticBaseConstructor<>(CodeHeap.class));
virtualConstructor = new VirtualConstructor(db);
// Add mappings for all possible CodeBlob subclasses
virtualConstructor.addMapping("BufferBlob", BufferBlob.class);
virtualConstructor.addMapping("nmethod", NMethod.class);
virtualConstructor.addMapping("RuntimeStub", RuntimeStub.class);
virtualConstructor.addMapping("AdapterBlob", AdapterBlob.class);
virtualConstructor.addMapping("MethodHandlesAdapterBlob", MethodHandlesAdapterBlob.class);
virtualConstructor.addMapping("VtableBlob", VtableBlob.class);
virtualConstructor.addMapping("UpcallStub", UpcallStub.class);
virtualConstructor.addMapping("SafepointBlob", SafepointBlob.class);
virtualConstructor.addMapping("DeoptimizationBlob", DeoptimizationBlob.class);
if (VM.getVM().isServerCompiler()) {
virtualConstructor.addMapping("ExceptionBlob", ExceptionBlob.class);
virtualConstructor.addMapping("UncommonTrapBlob", UncommonTrapBlob.class);
}
}
public boolean contains(Address p) {
@ -80,8 +63,8 @@ public class CodeCache {
/** When VM.getVM().isDebugging() returns true, this behaves like
findBlobUnsafe */
public CodeBlob findBlob(Address start) {
CodeBlob result = findBlobUnsafe(start);
public CodeBlob findBlob(Address addr) {
CodeBlob result = findBlobUnsafe(addr);
if (result == null) return null;
if (VM.getVM().isDebugging()) {
return result;
@ -91,11 +74,10 @@ public class CodeCache {
return result;
}
public CodeBlob findBlobUnsafe(Address start) {
CodeBlob result = null;
public CodeBlob findBlobUnsafe(Address addr) {
CodeHeap containing_heap = null;
for (int i = 0; i < heapArray.length(); ++i) {
if (heapArray.at(i).contains(start)) {
if (heapArray.at(i).contains(addr)) {
containing_heap = heapArray.at(i);
break;
}
@ -104,76 +86,52 @@ public class CodeCache {
return null;
}
try {
result = (CodeBlob) virtualConstructor.instantiateWrapperFor(containing_heap.findStart(start));
}
catch (WrongTypeException wte) {
Address cbAddr = null;
try {
cbAddr = containing_heap.findStart(start);
}
catch (Exception findEx) {
findEx.printStackTrace();
}
Address cbStart = containing_heap.findStart(addr);
if (cbStart == null) return null;
return createCodeBlobWrapper(cbStart, addr);
}
// cbStart - address of a code blob
// addr - address inside of a code blob
public CodeBlob createCodeBlobWrapper(Address cbStart, Address addr) {
Class<?> cbClass = CodeBlob.getClassFor(cbStart);
if (cbClass == null) {
String message = "Couldn't deduce type of CodeBlob ";
if (cbAddr != null) {
message = message + "@" + cbAddr + " ";
}
message = message + "for PC=" + start;
message = message + "@" + cbStart + " ";
message = message + "for PC=" + addr;
throw new RuntimeException(message, wte);
throw new RuntimeException(message);
}
if (result == null) return null;
CodeBlob result = (CodeBlob) VMObjectFactory.newObject(cbClass, cbStart);
if (Assert.ASSERTS_ENABLED) {
// The pointer to the HeapBlock that contains this blob is outside of the blob,
// but it shouldn't be an error to find a blob based on the pointer to the HeapBlock.
// The heap block header is padded out to an 8-byte boundary. See heap.hpp. The
// simplest way to compute the header size is just 2 * addressSize.
Assert.that(result.blobContains(start) ||
result.blobContains(start.addOffsetTo(2 * VM.getVM().getAddressSize())),
Assert.that(result.blobContains(addr) ||
result.blobContains(addr.addOffsetTo(2 * VM.getVM().getAddressSize())),
"found wrong CodeBlob");
}
return result;
}
public NMethod findNMethod(Address start) {
CodeBlob cb = findBlob(start);
public NMethod findNMethod(Address addr) {
CodeBlob cb = findBlob(addr);
if (Assert.ASSERTS_ENABLED) {
Assert.that(cb == null || cb.isNMethod(), "did not find an nmethod");
}
return (NMethod) cb;
}
public NMethod findNMethodUnsafe(Address start) {
CodeBlob cb = findBlobUnsafe(start);
public NMethod findNMethodUnsafe(Address addr) {
CodeBlob cb = findBlobUnsafe(addr);
if (Assert.ASSERTS_ENABLED) {
Assert.that(cb == null || cb.isNMethod(), "did not find an nmethod");
}
return (NMethod) cb;
}
/** Routine for instantiating appropriately-typed wrapper for a
CodeBlob. Used by CodeCache, Runtime1, etc. */
public CodeBlob createCodeBlobWrapper(Address codeBlobAddr) {
try {
return (CodeBlob) virtualConstructor.instantiateWrapperFor(codeBlobAddr);
}
catch (Exception e) {
String message = "Unable to deduce type of CodeBlob from address " + codeBlobAddr +
" (expected type nmethod, RuntimeStub, VtableBlob, ";
if (VM.getVM().isClientCompiler()) {
message = message + " or ";
}
message = message + "SafepointBlob";
if (VM.getVM().isServerCompiler()) {
message = message + ", DeoptimizationBlob, or ExceptionBlob";
}
message = message + ")";
throw new RuntimeException(message);
}
}
public void iterate(CodeCacheVisitor visitor) {
visitor.prologue(lowBound(), highBound());
for (int i = 0; i < heapArray.length(); ++i) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -49,8 +49,4 @@ public class DeoptimizationBlob extends SingletonBlob {
public DeoptimizationBlob(Address addr) {
super(addr);
}
public boolean isDeoptimizationStub() {
return true;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -52,8 +52,4 @@ public class ExceptionBlob extends SingletonBlob {
public ExceptionBlob(Address addr) {
super(addr);
}
public boolean isExceptionStub() {
return true;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -50,10 +50,6 @@ public class MethodHandlesAdapterBlob extends AdapterBlob {
super(addr);
}
public boolean isMethodHandlesAdapterBlob() {
return true;
}
public String getName() {
return "MethodHandlesAdapterBlob: " + super.getName();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -117,7 +117,6 @@ public class NMethod extends CodeBlob {
}
// Type info
public boolean isNMethod() { return true; }
public boolean isJavaMethod() { return !getMethod().isNative(); }
public boolean isNativeMethod() { return getMethod().isNative(); }
public boolean isOSRMethod() { return getEntryBCI() != VM.getVM().getInvocationEntryBCI(); }

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -53,10 +53,6 @@ public class RuntimeStub extends RuntimeBlob {
super(addr);
}
public boolean isRuntimeStub() {
return true;
}
public boolean callerMustGCArguments() {
return callerMustGCArgumentsField.getValue(addr) != 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -51,8 +51,4 @@ public class SafepointBlob extends SingletonBlob {
public SafepointBlob(Address addr) {
super(addr);
}
public boolean isSafepointStub() {
return true;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -49,6 +49,4 @@ public class SingletonBlob extends RuntimeBlob {
public SingletonBlob(Address addr) {
super(addr);
}
public boolean isSingletonBlob() { return true; }
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -51,8 +51,4 @@ public class UncommonTrapBlob extends SingletonBlob {
public UncommonTrapBlob(Address addr) {
super(addr);
}
public boolean isUncommonTrapStub() {
return true;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -85,10 +85,6 @@ public class UpcallStub extends RuntimeBlob {
return lastJavaPCField.getValue(getJavaFrameAnchor(frame));
}
public boolean isUpcallStub() {
return true;
}
public static class FrameData extends VMObject {
private static AddressField jfaField;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, NTT DATA.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -33,10 +33,6 @@ public class VtableBlob extends BufferBlob {
super(addr);
}
public boolean isVtableBlob() {
return true;
}
public String getName() {
return "VtableBlob: " + super.getName();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -108,7 +108,7 @@ public class CodeHeap extends VMObject {
while (ptr != null && ptr.lessThan(end())) {
try {
// Use findStart to get a pointer inside blob other findBlob asserts
CodeBlob blob = cache.createCodeBlobWrapper(findStart(ptr));
CodeBlob blob = cache.createCodeBlobWrapper(findStart(ptr), ptr);
if (blob != null) {
visitor.visit(blob);
if (blob == lastBlob) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -162,16 +162,24 @@ public class PStack extends Tool {
}
} else if (cb.isBufferBlob()) {
out.println("<StubRoutines>");
} else if (cb.isAdapterBlob()) {
out.println("<AdapterBlob>");
} else if (cb.isVtableBlob()) {
out.println("<VtableBlob>");
} else if (cb.isMHAdapterBlob()) {
out.println("<MethodHandlesAdapterBlob>");
} else if (cb.isRuntimeStub()) {
out.println("<RuntimeStub>");
} else if (cb.isDeoptimizationStub()) {
out.println("<DeoptimizationStub>");
} else if (cb.isUncommonTrapStub()) {
out.println("<UncommonTrap>");
} else if (cb.isExceptionStub()) {
out.println("<ExceptionStub>");
} else if (cb.isSafepointStub()) {
out.println("<SafepointStub>");
} else if (cb.isUpcallStub()) {
out.println("<UpcallStub>");
} else if (cb.isDeoptimizationBlob()) {
out.println("<DeoptimizationBlob>");
} else if (cb.isUncommonTrapBlob()) {
out.println("<UncommonTrapBlob>");
} else if (cb.isExceptionBlob()) {
out.println("<ExceptionBlob>");
} else if (cb.isSafepointBlob()) {
out.println("<SafepointBlob>");
} else {
out.println("<Unknown code blob>");
}