Path: blob/master/src/hotspot/share/code/codeBlob.hpp
40931 views
/*1* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_CODE_CODEBLOB_HPP25#define SHARE_CODE_CODEBLOB_HPP2627#include "asm/codeBuffer.hpp"28#include "compiler/compilerDefinitions.hpp"29#include "runtime/frame.hpp"30#include "runtime/handles.hpp"31#include "utilities/align.hpp"32#include "utilities/macros.hpp"3334class ImmutableOopMap;35class ImmutableOopMapSet;36class OopMapSet;3738// CodeBlob Types39// Used in the CodeCache to assign CodeBlobs to different CodeHeaps40struct CodeBlobType {41enum {42MethodNonProfiled = 0, // Execution level 1 and 4 (non-profiled) nmethods (including native nmethods)43MethodProfiled = 1, // Execution level 2 and 3 (profiled) nmethods44NonNMethod = 2, // Non-nmethods like Buffers, Adapters and Runtime Stubs45All = 3, // All types (No code cache segmentation)46NumTypes = 4 // Number of CodeBlobTypes47};48};4950// CodeBlob - superclass for all entries in the CodeCache.51//52// Subtypes are:53// CompiledMethod : Compiled Java methods (include method that calls to native code)54// nmethod : JIT Compiled Java methods55// RuntimeBlob : Non-compiled method code; generated glue code56// BufferBlob : Used for non-relocatable code such as interpreter, stubroutines, etc.57// AdapterBlob : Used to hold C2I/I2C adapters58// VtableBlob : Used for holding vtable chunks59// MethodHandlesAdapterBlob : Used to hold MethodHandles adapters60// OptimizedEntryBlob : Used for upcalls from native code61// RuntimeStub : Call to VM runtime methods62// SingletonBlob : Super-class for all blobs that exist in only one instance63// DeoptimizationBlob : Used for deoptimization64// ExceptionBlob : Used for stack unrolling65// SafepointBlob : Used to handle illegal instruction exceptions66// UncommonTrapBlob : Used to handle uncommon traps67//68//69// Layout : continuous in the CodeCache70// - header71// - relocation72// - content space73// - instruction space74// - data space757677class CodeBlobLayout;78class OptimizedEntryBlob; // for as_optimized_entry_blob()79class JavaFrameAnchor; // for EntryBlob::jfa_for_frame8081class CodeBlob {82friend class VMStructs;83friend class JVMCIVMStructs;84friend class CodeCacheDumper;8586protected:8788const CompilerType _type; // CompilerType89int _size; // total size of CodeBlob in bytes90int _header_size; // size of header (depends on subclass)91int _frame_complete_offset; // instruction offsets in [0.._frame_complete_offset) have92// not finished setting up their frame. Beware of pc's in93// that range. There is a similar range(s) on returns94// which we don't detect.95int _data_offset; // offset to where data region begins96int _frame_size; // size of stack frame9798address _code_begin;99address _code_end;100address _content_begin; // address to where content region begins (this includes consts, insts, stubs)101// address _content_end - not required, for all CodeBlobs _code_end == _content_end for now102address _data_end;103address _relocation_begin;104address _relocation_end;105106ImmutableOopMapSet* _oop_maps; // OopMap for this CodeBlob107bool _caller_must_gc_arguments;108109const char* _name;110S390_ONLY(int _ctable_offset;)111112NOT_PRODUCT(CodeStrings _strings;)113114CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, int frame_complete_offset, int frame_size, ImmutableOopMapSet* oop_maps, bool caller_must_gc_arguments);115CodeBlob(const char* name, CompilerType type, const CodeBlobLayout& layout, CodeBuffer* cb, int frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments);116117public:118// Only used by unit test.119CodeBlob()120: _type(compiler_none) {}121122// Returns the space needed for CodeBlob123static unsigned int allocation_size(CodeBuffer* cb, int header_size);124static unsigned int align_code_offset(int offset);125126// Deletion127virtual void flush();128129// Typing130virtual bool is_buffer_blob() const { return false; }131virtual bool is_nmethod() const { return false; }132virtual bool is_runtime_stub() const { return false; }133virtual bool is_deoptimization_stub() const { return false; }134virtual bool is_uncommon_trap_stub() const { return false; }135virtual bool is_exception_stub() const { return false; }136virtual bool is_safepoint_stub() const { return false; }137virtual bool is_adapter_blob() const { return false; }138virtual bool is_vtable_blob() const { return false; }139virtual bool is_method_handles_adapter_blob() const { return false; }140virtual bool is_compiled() const { return false; }141virtual bool is_optimized_entry_blob() const { return false; }142143inline bool is_compiled_by_c1() const { return _type == compiler_c1; };144inline bool is_compiled_by_c2() const { return _type == compiler_c2; };145inline bool is_compiled_by_jvmci() const { return _type == compiler_jvmci; };146const char* compiler_name() const;147CompilerType compiler_type() const { return _type; }148149// Casting150nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; }151nmethod* as_nmethod() { assert(is_nmethod(), "must be nmethod"); return (nmethod*) this; }152CompiledMethod* as_compiled_method_or_null() { return is_compiled() ? (CompiledMethod*) this : NULL; }153CompiledMethod* as_compiled_method() { assert(is_compiled(), "must be compiled"); return (CompiledMethod*) this; }154CodeBlob* as_codeblob_or_null() const { return (CodeBlob*) this; }155OptimizedEntryBlob* as_optimized_entry_blob() const { assert(is_optimized_entry_blob(), "must be entry blob"); return (OptimizedEntryBlob*) this; }156157// Boundaries158address header_begin() const { return (address) this; }159relocInfo* relocation_begin() const { return (relocInfo*) _relocation_begin; };160relocInfo* relocation_end() const { return (relocInfo*) _relocation_end; }161address content_begin() const { return _content_begin; }162address content_end() const { return _code_end; } // _code_end == _content_end is true for all types of blobs for now, it is also checked in the constructor163address code_begin() const { return _code_begin; }164address code_end() const { return _code_end; }165address data_end() const { return _data_end; }166167// This field holds the beginning of the const section in the old code buffer.168// It is needed to fix relocations of pc-relative loads when resizing the169// the constant pool or moving it.170S390_ONLY(address ctable_begin() const { return header_begin() + _ctable_offset; })171void set_ctable_begin(address ctable) { S390_ONLY(_ctable_offset = ctable - header_begin();) }172173// Sizes174int size() const { return _size; }175int header_size() const { return _header_size; }176int relocation_size() const { return (address) relocation_end() - (address) relocation_begin(); }177int content_size() const { return content_end() - content_begin(); }178int code_size() const { return code_end() - code_begin(); }179// Only used from CodeCache::free_unused_tail() after the Interpreter blob was trimmed180void adjust_size(size_t used) {181_size = (int)used;182_data_offset = (int)used;183_code_end = (address)this + used;184_data_end = (address)this + used;185}186187// Containment188bool blob_contains(address addr) const { return header_begin() <= addr && addr < data_end(); }189bool code_contains(address addr) const { return code_begin() <= addr && addr < code_end(); }190bool contains(address addr) const { return content_begin() <= addr && addr < content_end(); }191bool is_frame_complete_at(address addr) const { return _frame_complete_offset != CodeOffsets::frame_never_safe &&192code_contains(addr) && addr >= code_begin() + _frame_complete_offset; }193int frame_complete_offset() const { return _frame_complete_offset; }194195// CodeCache support: really only used by the nmethods, but in order to get196// asserts and certain bookkeeping to work in the CodeCache they are defined197// virtual here.198virtual bool is_zombie() const { return false; }199virtual bool is_locked_by_vm() const { return false; }200201virtual bool is_unloaded() const { return false; }202virtual bool is_not_entrant() const { return false; }203204// GC support205virtual bool is_alive() const = 0;206207// OopMap for frame208ImmutableOopMapSet* oop_maps() const { return _oop_maps; }209void set_oop_maps(OopMapSet* p);210const ImmutableOopMap* oop_map_for_return_address(address return_address);211virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) = 0;212213// Frame support. Sizes are in word units.214int frame_size() const { return _frame_size; }215void set_frame_size(int size) { _frame_size = size; }216217// Returns true, if the next frame is responsible for GC'ing oops passed as arguments218bool caller_must_gc_arguments(JavaThread* thread) const { return _caller_must_gc_arguments; }219220// Naming221const char* name() const { return _name; }222void set_name(const char* name) { _name = name; }223224// Debugging225virtual void verify() = 0;226virtual void print() const;227virtual void print_on(outputStream* st) const;228virtual void print_value_on(outputStream* st) const;229void dump_for_addr(address addr, outputStream* st, bool verbose) const;230void print_code();231232// Print the comment associated with offset on stream, if there is one233virtual void print_block_comment(outputStream* stream, address block_begin) const {234#ifndef PRODUCT235intptr_t offset = (intptr_t)(block_begin - code_begin());236_strings.print_block_comment(stream, offset);237#endif238}239240#ifndef PRODUCT241void set_strings(CodeStrings& strings) {242_strings.copy(strings);243}244#endif245};246247class CodeBlobLayout : public StackObj {248private:249int _size;250int _header_size;251int _relocation_size;252int _content_offset;253int _code_offset;254int _data_offset;255address _code_begin;256address _code_end;257address _content_begin;258address _content_end;259address _data_end;260address _relocation_begin;261address _relocation_end;262263public:264CodeBlobLayout(address code_begin, address code_end, address content_begin, address content_end, address data_end, address relocation_begin, address relocation_end) :265_size(0),266_header_size(0),267_relocation_size(0),268_content_offset(0),269_code_offset(0),270_data_offset(0),271_code_begin(code_begin),272_code_end(code_end),273_content_begin(content_begin),274_content_end(content_end),275_data_end(data_end),276_relocation_begin(relocation_begin),277_relocation_end(relocation_end)278{279}280281CodeBlobLayout(const address start, int size, int header_size, int relocation_size, int data_offset) :282_size(size),283_header_size(header_size),284_relocation_size(relocation_size),285_content_offset(CodeBlob::align_code_offset(_header_size + _relocation_size)),286_code_offset(_content_offset),287_data_offset(data_offset)288{289assert(is_aligned(_relocation_size, oopSize), "unaligned size");290291_code_begin = (address) start + _code_offset;292_code_end = (address) start + _data_offset;293294_content_begin = (address) start + _content_offset;295_content_end = (address) start + _data_offset;296297_data_end = (address) start + _size;298_relocation_begin = (address) start + _header_size;299_relocation_end = _relocation_begin + _relocation_size;300}301302CodeBlobLayout(const address start, int size, int header_size, const CodeBuffer* cb) :303_size(size),304_header_size(header_size),305_relocation_size(align_up(cb->total_relocation_size(), oopSize)),306_content_offset(CodeBlob::align_code_offset(_header_size + _relocation_size)),307_code_offset(_content_offset + cb->total_offset_of(cb->insts())),308_data_offset(_content_offset + align_up(cb->total_content_size(), oopSize))309{310assert(is_aligned(_relocation_size, oopSize), "unaligned size");311312_code_begin = (address) start + _code_offset;313_code_end = (address) start + _data_offset;314315_content_begin = (address) start + _content_offset;316_content_end = (address) start + _data_offset;317318_data_end = (address) start + _size;319_relocation_begin = (address) start + _header_size;320_relocation_end = _relocation_begin + _relocation_size;321}322323int size() const { return _size; }324int header_size() const { return _header_size; }325int relocation_size() const { return _relocation_size; }326int content_offset() const { return _content_offset; }327int code_offset() const { return _code_offset; }328int data_offset() const { return _data_offset; }329address code_begin() const { return _code_begin; }330address code_end() const { return _code_end; }331address data_end() const { return _data_end; }332address relocation_begin() const { return _relocation_begin; }333address relocation_end() const { return _relocation_end; }334address content_begin() const { return _content_begin; }335address content_end() const { return _content_end; }336};337338339class RuntimeBlob : public CodeBlob {340friend class VMStructs;341public:342343// Creation344// a) simple CodeBlob345// frame_complete is the offset from the beginning of the instructions346// to where the frame setup (from stackwalk viewpoint) is complete.347RuntimeBlob(const char* name, int header_size, int size, int frame_complete, int locs_size);348349// b) full CodeBlob350RuntimeBlob(351const char* name,352CodeBuffer* cb,353int header_size,354int size,355int frame_complete,356int frame_size,357OopMapSet* oop_maps,358bool caller_must_gc_arguments = false359);360361// GC support362virtual bool is_alive() const = 0;363364void verify();365366// OopMap for frame367virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { ShouldNotReachHere(); }368369// Debugging370virtual void print_on(outputStream* st) const { CodeBlob::print_on(st); }371virtual void print_value_on(outputStream* st) const { CodeBlob::print_value_on(st); }372373// Deal with Disassembler, VTune, Forte, JvmtiExport, MemoryService.374static void trace_new_stub(RuntimeBlob* blob, const char* name1, const char* name2 = "");375};376377class WhiteBox;378//----------------------------------------------------------------------------------------------------379// BufferBlob: used to hold non-relocatable machine code such as the interpreter, stubroutines, etc.380381class BufferBlob: public RuntimeBlob {382friend class VMStructs;383friend class AdapterBlob;384friend class VtableBlob;385friend class MethodHandlesAdapterBlob;386friend class OptimizedEntryBlob;387friend class WhiteBox;388389private:390// Creation support391BufferBlob(const char* name, int size);392BufferBlob(const char* name, int size, CodeBuffer* cb);393394// This ordinary operator delete is needed even though not used, so the395// below two-argument operator delete will be treated as a placement396// delete rather than an ordinary sized delete; see C++14 3.7.4.2/p2.397void operator delete(void* p);398void* operator new(size_t s, unsigned size) throw();399400public:401// Creation402static BufferBlob* create(const char* name, int buffer_size);403static BufferBlob* create(const char* name, CodeBuffer* cb);404405static void free(BufferBlob* buf);406407// Typing408virtual bool is_buffer_blob() const { return true; }409410// GC/Verification support411void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ }412bool is_alive() const { return true; }413414void verify();415void print_on(outputStream* st) const;416void print_value_on(outputStream* st) const;417};418419420//----------------------------------------------------------------------------------------------------421// AdapterBlob: used to hold C2I/I2C adapters422423class AdapterBlob: public BufferBlob {424private:425AdapterBlob(int size, CodeBuffer* cb);426427public:428// Creation429static AdapterBlob* create(CodeBuffer* cb);430431// Typing432virtual bool is_adapter_blob() const { return true; }433};434435//---------------------------------------------------------------------------------------------------436class VtableBlob: public BufferBlob {437private:438VtableBlob(const char*, int);439440void* operator new(size_t s, unsigned size) throw();441442public:443// Creation444static VtableBlob* create(const char* name, int buffer_size);445446// Typing447virtual bool is_vtable_blob() const { return true; }448};449450//----------------------------------------------------------------------------------------------------451// MethodHandlesAdapterBlob: used to hold MethodHandles adapters452453class MethodHandlesAdapterBlob: public BufferBlob {454private:455MethodHandlesAdapterBlob(int size) : BufferBlob("MethodHandles adapters", size) {}456457public:458// Creation459static MethodHandlesAdapterBlob* create(int buffer_size);460461// Typing462virtual bool is_method_handles_adapter_blob() const { return true; }463};464465466//----------------------------------------------------------------------------------------------------467// RuntimeStub: describes stubs used by compiled code to call a (static) C++ runtime routine468469class RuntimeStub: public RuntimeBlob {470friend class VMStructs;471private:472// Creation support473RuntimeStub(474const char* name,475CodeBuffer* cb,476int size,477int frame_complete,478int frame_size,479OopMapSet* oop_maps,480bool caller_must_gc_arguments481);482483// This ordinary operator delete is needed even though not used, so the484// below two-argument operator delete will be treated as a placement485// delete rather than an ordinary sized delete; see C++14 3.7.4.2/p2.486void operator delete(void* p);487void* operator new(size_t s, unsigned size) throw();488489public:490// Creation491static RuntimeStub* new_runtime_stub(492const char* stub_name,493CodeBuffer* cb,494int frame_complete,495int frame_size,496OopMapSet* oop_maps,497bool caller_must_gc_arguments498);499500// Typing501bool is_runtime_stub() const { return true; }502503address entry_point() const { return code_begin(); }504505// GC/Verification support506void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* nothing to do */ }507bool is_alive() const { return true; }508509void verify();510void print_on(outputStream* st) const;511void print_value_on(outputStream* st) const;512};513514515//----------------------------------------------------------------------------------------------------516// Super-class for all blobs that exist in only one instance. Implements default behaviour.517518class SingletonBlob: public RuntimeBlob {519friend class VMStructs;520521protected:522// This ordinary operator delete is needed even though not used, so the523// below two-argument operator delete will be treated as a placement524// delete rather than an ordinary sized delete; see C++14 3.7.4.2/p2.525void operator delete(void* p);526void* operator new(size_t s, unsigned size) throw();527528public:529SingletonBlob(530const char* name,531CodeBuffer* cb,532int header_size,533int size,534int frame_size,535OopMapSet* oop_maps536)537: RuntimeBlob(name, cb, header_size, size, CodeOffsets::frame_never_safe, frame_size, oop_maps)538{};539540address entry_point() { return code_begin(); }541542bool is_alive() const { return true; }543544// GC/Verification support545void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* nothing to do */ }546void verify(); // does nothing547void print_on(outputStream* st) const;548void print_value_on(outputStream* st) const;549};550551552//----------------------------------------------------------------------------------------------------553// DeoptimizationBlob554555class DeoptimizationBlob: public SingletonBlob {556friend class VMStructs;557friend class JVMCIVMStructs;558private:559int _unpack_offset;560int _unpack_with_exception;561int _unpack_with_reexecution;562563int _unpack_with_exception_in_tls;564565#if INCLUDE_JVMCI566// Offsets when JVMCI calls uncommon_trap.567int _uncommon_trap_offset;568int _implicit_exception_uncommon_trap_offset;569#endif570571// Creation support572DeoptimizationBlob(573CodeBuffer* cb,574int size,575OopMapSet* oop_maps,576int unpack_offset,577int unpack_with_exception_offset,578int unpack_with_reexecution_offset,579int frame_size580);581582public:583// Creation584static DeoptimizationBlob* create(585CodeBuffer* cb,586OopMapSet* oop_maps,587int unpack_offset,588int unpack_with_exception_offset,589int unpack_with_reexecution_offset,590int frame_size591);592593// Typing594bool is_deoptimization_stub() const { return true; }595596// GC for args597void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* Nothing to do */ }598599// Printing600void print_value_on(outputStream* st) const;601602address unpack() const { return code_begin() + _unpack_offset; }603address unpack_with_exception() const { return code_begin() + _unpack_with_exception; }604address unpack_with_reexecution() const { return code_begin() + _unpack_with_reexecution; }605606// Alternate entry point for C1 where the exception and issuing pc607// are in JavaThread::_exception_oop and JavaThread::_exception_pc608// instead of being in registers. This is needed because C1 doesn't609// model exception paths in a way that keeps these registers free so610// there may be live values in those registers during deopt.611void set_unpack_with_exception_in_tls_offset(int offset) {612_unpack_with_exception_in_tls = offset;613assert(code_contains(code_begin() + _unpack_with_exception_in_tls), "must be PC inside codeblob");614}615address unpack_with_exception_in_tls() const { return code_begin() + _unpack_with_exception_in_tls; }616617#if INCLUDE_JVMCI618// Offsets when JVMCI calls uncommon_trap.619void set_uncommon_trap_offset(int offset) {620_uncommon_trap_offset = offset;621assert(contains(code_begin() + _uncommon_trap_offset), "must be PC inside codeblob");622}623address uncommon_trap() const { return code_begin() + _uncommon_trap_offset; }624625void set_implicit_exception_uncommon_trap_offset(int offset) {626_implicit_exception_uncommon_trap_offset = offset;627assert(contains(code_begin() + _implicit_exception_uncommon_trap_offset), "must be PC inside codeblob");628}629address implicit_exception_uncommon_trap() const { return code_begin() + _implicit_exception_uncommon_trap_offset; }630#endif // INCLUDE_JVMCI631};632633634//----------------------------------------------------------------------------------------------------635// UncommonTrapBlob (currently only used by Compiler 2)636637#ifdef COMPILER2638639class UncommonTrapBlob: public SingletonBlob {640friend class VMStructs;641private:642// Creation support643UncommonTrapBlob(644CodeBuffer* cb,645int size,646OopMapSet* oop_maps,647int frame_size648);649650public:651// Creation652static UncommonTrapBlob* create(653CodeBuffer* cb,654OopMapSet* oop_maps,655int frame_size656);657658// GC for args659void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* nothing to do */ }660661// Typing662bool is_uncommon_trap_stub() const { return true; }663};664665666//----------------------------------------------------------------------------------------------------667// ExceptionBlob: used for exception unwinding in compiled code (currently only used by Compiler 2)668669class ExceptionBlob: public SingletonBlob {670friend class VMStructs;671private:672// Creation support673ExceptionBlob(674CodeBuffer* cb,675int size,676OopMapSet* oop_maps,677int frame_size678);679680public:681// Creation682static ExceptionBlob* create(683CodeBuffer* cb,684OopMapSet* oop_maps,685int frame_size686);687688// GC for args689void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ }690691// Typing692bool is_exception_stub() const { return true; }693};694#endif // COMPILER2695696697//----------------------------------------------------------------------------------------------------698// SafepointBlob: handles illegal_instruction exceptions during a safepoint699700class SafepointBlob: public SingletonBlob {701friend class VMStructs;702private:703// Creation support704SafepointBlob(705CodeBuffer* cb,706int size,707OopMapSet* oop_maps,708int frame_size709);710711public:712// Creation713static SafepointBlob* create(714CodeBuffer* cb,715OopMapSet* oop_maps,716int frame_size717);718719// GC for args720void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ }721722// Typing723bool is_safepoint_stub() const { return true; }724};725726//----------------------------------------------------------------------------------------------------727728// For optimized upcall stubs729class OptimizedEntryBlob: public BufferBlob {730private:731intptr_t _exception_handler_offset;732jobject _receiver;733ByteSize _jfa_sp_offset;734735OptimizedEntryBlob(const char* name, int size, CodeBuffer* cb, intptr_t exception_handler_offset,736jobject receiver, ByteSize jfa_sp_offset);737738public:739// Creation740static OptimizedEntryBlob* create(const char* name, CodeBuffer* cb,741intptr_t exception_handler_offset, jobject receiver,742ByteSize jfa_sp_offset);743744address exception_handler() { return code_begin() + _exception_handler_offset; }745jobject receiver() { return _receiver; }746ByteSize jfa_sp_offset() const { return _jfa_sp_offset; }747748// defined in frame_ARCH.cpp749JavaFrameAnchor* jfa_for_frame(const frame& frame) const;750751// Typing752virtual bool is_optimized_entry_blob() const override { return true; }753};754755#endif // SHARE_CODE_CODEBLOB_HPP756757758