codeBlob.hpp revision 1879
0N/A/*
1472N/A * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1472N/A * or visit www.oracle.com if you need additional information or have any
1472N/A * questions.
0N/A *
0N/A */
0N/A
1879N/A#ifndef SHARE_VM_CODE_CODEBLOB_HPP
1879N/A#define SHARE_VM_CODE_CODEBLOB_HPP
1879N/A
1879N/A#include "asm/codeBuffer.hpp"
1879N/A#include "compiler/oopMap.hpp"
1879N/A#include "runtime/frame.hpp"
1879N/A#include "runtime/handles.hpp"
1879N/A
0N/A// CodeBlob - superclass for all entries in the CodeCache.
0N/A//
0N/A// Suptypes are:
0N/A// nmethod : Compiled Java methods (include method that calls to native code)
0N/A// RuntimeStub : Call to VM runtime methods
0N/A// DeoptimizationBlob : Used for deoptimizatation
0N/A// ExceptionBlob : Used for stack unrolling
0N/A// SafepointBlob : Used to handle illegal instruction exceptions
0N/A//
0N/A//
0N/A// Layout:
0N/A// - header
0N/A// - relocation
1668N/A// - content space
1668N/A// - instruction space
0N/A// - data space
0N/Aclass DeoptimizationBlob;
0N/A
0N/Aclass CodeBlob VALUE_OBJ_CLASS_SPEC {
0N/A
0N/A friend class VMStructs;
0N/A
0N/A private:
0N/A const char* _name;
0N/A int _size; // total size of CodeBlob in bytes
0N/A int _header_size; // size of header (depends on subclass)
0N/A int _relocation_size; // size of relocation
1668N/A int _content_offset; // offset to where content region begins (this includes consts, insts, stubs)
1668N/A int _code_offset; // offset to where instructions region begins (this includes insts, stubs)
0N/A int _frame_complete_offset; // instruction offsets in [0.._frame_complete_offset) have
0N/A // not finished setting up their frame. Beware of pc's in
0N/A // that range. There is a similar range(s) on returns
0N/A // which we don't detect.
0N/A int _data_offset; // offset to where data region begins
0N/A int _frame_size; // size of stack frame
0N/A OopMapSet* _oop_maps; // OopMap for this CodeBlob
0N/A CodeComments _comments;
0N/A
0N/A friend class OopRecorder;
0N/A
0N/A public:
0N/A // Returns the space needed for CodeBlob
0N/A static unsigned int allocation_size(CodeBuffer* cb, int header_size);
0N/A
0N/A // Creation
0N/A // a) simple CodeBlob
0N/A // frame_complete is the offset from the beginning of the instructions
0N/A // to where the frame setup (from stackwalk viewpoint) is complete.
0N/A CodeBlob(const char* name, int header_size, int size, int frame_complete, int locs_size);
0N/A
0N/A // b) full CodeBlob
0N/A CodeBlob(
0N/A const char* name,
0N/A CodeBuffer* cb,
0N/A int header_size,
0N/A int size,
0N/A int frame_complete,
0N/A int frame_size,
0N/A OopMapSet* oop_maps
0N/A );
0N/A
0N/A // Deletion
0N/A void flush();
0N/A
0N/A // Typing
1299N/A virtual bool is_buffer_blob() const { return false; }
1299N/A virtual bool is_nmethod() const { return false; }
1299N/A virtual bool is_runtime_stub() const { return false; }
1299N/A virtual bool is_deoptimization_stub() const { return false; }
1299N/A virtual bool is_uncommon_trap_stub() const { return false; }
1299N/A virtual bool is_exception_stub() const { return false; }
1299N/A virtual bool is_safepoint_stub() const { return false; }
1299N/A virtual bool is_adapter_blob() const { return false; }
1299N/A virtual bool is_method_handles_adapter_blob() const { return false; }
0N/A
0N/A virtual bool is_compiled_by_c2() const { return false; }
0N/A virtual bool is_compiled_by_c1() const { return false; }
0N/A
1135N/A // Casting
1135N/A nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; }
1135N/A
0N/A // Boundaries
0N/A address header_begin() const { return (address) this; }
0N/A address header_end() const { return ((address) this) + _header_size; };
0N/A relocInfo* relocation_begin() const { return (relocInfo*) header_end(); };
0N/A relocInfo* relocation_end() const { return (relocInfo*)(header_end() + _relocation_size); }
1668N/A address content_begin() const { return (address) header_begin() + _content_offset; }
1668N/A address content_end() const { return (address) header_begin() + _data_offset; }
1668N/A address code_begin() const { return (address) header_begin() + _code_offset; }
1668N/A address code_end() const { return (address) header_begin() + _data_offset; }
0N/A address data_begin() const { return (address) header_begin() + _data_offset; }
0N/A address data_end() const { return (address) header_begin() + _size; }
0N/A
0N/A // Offsets
0N/A int relocation_offset() const { return _header_size; }
1668N/A int content_offset() const { return _content_offset; }
1668N/A int code_offset() const { return _code_offset; }
0N/A int data_offset() const { return _data_offset; }
0N/A
0N/A // Sizes
0N/A int size() const { return _size; }
0N/A int header_size() const { return _header_size; }
0N/A int relocation_size() const { return (address) relocation_end() - (address) relocation_begin(); }
1668N/A int content_size() const { return content_end() - content_begin(); }
1668N/A int code_size() const { return code_end() - code_begin(); }
1668N/A int data_size() const { return data_end() - data_begin(); }
0N/A
0N/A // Containment
1668N/A bool blob_contains(address addr) const { return header_begin() <= addr && addr < data_end(); }
0N/A bool relocation_contains(relocInfo* addr) const{ return relocation_begin() <= addr && addr < relocation_end(); }
1668N/A bool content_contains(address addr) const { return content_begin() <= addr && addr < content_end(); }
1668N/A bool code_contains(address addr) const { return code_begin() <= addr && addr < code_end(); }
1668N/A bool data_contains(address addr) const { return data_begin() <= addr && addr < data_end(); }
1668N/A bool contains(address addr) const { return content_contains(addr); }
1668N/A bool is_frame_complete_at(address addr) const { return code_contains(addr) &&
1668N/A addr >= code_begin() + _frame_complete_offset; }
0N/A
0N/A // CodeCache support: really only used by the nmethods, but in order to get
0N/A // asserts and certain bookkeeping to work in the CodeCache they are defined
0N/A // virtual here.
0N/A virtual bool is_zombie() const { return false; }
0N/A virtual bool is_locked_by_vm() const { return false; }
0N/A
0N/A virtual bool is_unloaded() const { return false; }
0N/A virtual bool is_not_entrant() const { return false; }
0N/A
0N/A // GC support
0N/A virtual bool is_alive() const = 0;
0N/A
0N/A // OopMap for frame
0N/A OopMapSet* oop_maps() const { return _oop_maps; }
0N/A void set_oop_maps(OopMapSet* p);
0N/A OopMap* oop_map_for_return_address(address return_address);
0N/A virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { ShouldNotReachHere(); }
0N/A
0N/A // Frame support
0N/A int frame_size() const { return _frame_size; }
0N/A void set_frame_size(int size) { _frame_size = size; }
0N/A
0N/A // Returns true, if the next frame is responsible for GC'ing oops passed as arguments
0N/A virtual bool caller_must_gc_arguments(JavaThread* thread) const { return false; }
0N/A
0N/A // Naming
0N/A const char* name() const { return _name; }
0N/A void set_name(const char* name) { _name = name; }
0N/A
0N/A // Debugging
0N/A virtual void verify();
1601N/A void print() const { print_on(tty); }
1601N/A virtual void print_on(outputStream* st) const;
1601N/A virtual void print_value_on(outputStream* st) const;
0N/A
0N/A // Print the comment associated with offset on stream, if there is one
1155N/A virtual void print_block_comment(outputStream* stream, address block_begin) {
1668N/A intptr_t offset = (intptr_t)(block_begin - code_begin());
0N/A _comments.print_block_comment(stream, offset);
0N/A }
0N/A
0N/A // Transfer ownership of comments to this CodeBlob
0N/A void set_comments(CodeComments& comments) {
0N/A _comments.assign(comments);
0N/A }
0N/A};
0N/A
0N/A
0N/A//----------------------------------------------------------------------------------------------------
0N/A// BufferBlob: used to hold non-relocatable machine code such as the interpreter, stubroutines, etc.
0N/A
0N/Aclass BufferBlob: public CodeBlob {
0N/A friend class VMStructs;
1299N/A friend class AdapterBlob;
1299N/A friend class MethodHandlesAdapterBlob;
1299N/A
0N/A private:
0N/A // Creation support
0N/A BufferBlob(const char* name, int size);
0N/A BufferBlob(const char* name, int size, CodeBuffer* cb);
0N/A
0N/A void* operator new(size_t s, unsigned size);
0N/A
0N/A public:
0N/A // Creation
0N/A static BufferBlob* create(const char* name, int buffer_size);
0N/A static BufferBlob* create(const char* name, CodeBuffer* cb);
0N/A
0N/A static void free(BufferBlob* buf);
0N/A
0N/A // Typing
1299N/A virtual bool is_buffer_blob() const { return true; }
0N/A
0N/A // GC/Verification support
0N/A void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ }
0N/A bool is_alive() const { return true; }
0N/A
0N/A void verify();
1601N/A void print_on(outputStream* st) const;
1601N/A void print_value_on(outputStream* st) const;
0N/A};
0N/A
0N/A
0N/A//----------------------------------------------------------------------------------------------------
1299N/A// AdapterBlob: used to hold C2I/I2C adapters
1299N/A
1299N/Aclass AdapterBlob: public BufferBlob {
1299N/Aprivate:
1583N/A AdapterBlob(int size, CodeBuffer* cb);
1299N/A
1299N/Apublic:
1299N/A // Creation
1299N/A static AdapterBlob* create(CodeBuffer* cb);
1299N/A
1299N/A // Typing
1299N/A virtual bool is_adapter_blob() const { return true; }
1299N/A};
1299N/A
1299N/A
1299N/A//----------------------------------------------------------------------------------------------------
1299N/A// MethodHandlesAdapterBlob: used to hold MethodHandles adapters
1299N/A
1299N/Aclass MethodHandlesAdapterBlob: public BufferBlob {
1299N/Aprivate:
1299N/A MethodHandlesAdapterBlob(int size) : BufferBlob("MethodHandles adapters", size) {}
1299N/A MethodHandlesAdapterBlob(int size, CodeBuffer* cb) : BufferBlob("MethodHandles adapters", size, cb) {}
1299N/A
1299N/Apublic:
1299N/A // Creation
1299N/A static MethodHandlesAdapterBlob* create(int buffer_size);
1299N/A
1299N/A // Typing
1299N/A virtual bool is_method_handles_adapter_blob() const { return true; }
1299N/A};
1299N/A
1299N/A
1299N/A//----------------------------------------------------------------------------------------------------
0N/A// RuntimeStub: describes stubs used by compiled code to call a (static) C++ runtime routine
0N/A
0N/Aclass RuntimeStub: public CodeBlob {
0N/A friend class VMStructs;
0N/A private:
0N/A bool _caller_must_gc_arguments;
0N/A
0N/A // Creation support
0N/A RuntimeStub(
0N/A const char* name,
0N/A CodeBuffer* cb,
0N/A int size,
0N/A int frame_complete,
0N/A int frame_size,
0N/A OopMapSet* oop_maps,
0N/A bool caller_must_gc_arguments
0N/A );
0N/A
0N/A void* operator new(size_t s, unsigned size);
0N/A
0N/A public:
0N/A // Creation
0N/A static RuntimeStub* new_runtime_stub(
0N/A const char* stub_name,
0N/A CodeBuffer* cb,
0N/A int frame_complete,
0N/A int frame_size,
0N/A OopMapSet* oop_maps,
0N/A bool caller_must_gc_arguments
0N/A );
0N/A
0N/A // Typing
0N/A bool is_runtime_stub() const { return true; }
0N/A
0N/A // GC support
0N/A bool caller_must_gc_arguments(JavaThread* thread) const { return _caller_must_gc_arguments; }
0N/A
1668N/A address entry_point() { return code_begin(); }
0N/A
0N/A // GC/Verification support
0N/A void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* nothing to do */ }
0N/A bool is_alive() const { return true; }
0N/A
0N/A void verify();
1601N/A void print_on(outputStream* st) const;
1601N/A void print_value_on(outputStream* st) const;
0N/A};
0N/A
0N/A
0N/A//----------------------------------------------------------------------------------------------------
0N/A// Super-class for all blobs that exist in only one instance. Implements default behaviour.
0N/A
0N/Aclass SingletonBlob: public CodeBlob {
0N/A friend class VMStructs;
0N/A public:
0N/A SingletonBlob(
0N/A const char* name,
0N/A CodeBuffer* cb,
0N/A int header_size,
0N/A int size,
0N/A int frame_size,
0N/A OopMapSet* oop_maps
0N/A )
0N/A : CodeBlob(name, cb, header_size, size, CodeOffsets::frame_never_safe, frame_size, oop_maps)
1668N/A {};
0N/A
1668N/A address entry_point() { return code_begin(); }
0N/A
1668N/A bool is_alive() const { return true; }
1668N/A
1668N/A void verify(); // does nothing
1668N/A void print_on(outputStream* st) const;
1668N/A void print_value_on(outputStream* st) const;
0N/A};
0N/A
0N/A
0N/A//----------------------------------------------------------------------------------------------------
0N/A// DeoptimizationBlob
0N/A
0N/Aclass DeoptimizationBlob: public SingletonBlob {
0N/A friend class VMStructs;
0N/A private:
0N/A int _unpack_offset;
0N/A int _unpack_with_exception;
0N/A int _unpack_with_reexecution;
0N/A
0N/A int _unpack_with_exception_in_tls;
0N/A
0N/A // Creation support
0N/A DeoptimizationBlob(
0N/A CodeBuffer* cb,
0N/A int size,
0N/A OopMapSet* oop_maps,
0N/A int unpack_offset,
0N/A int unpack_with_exception_offset,
0N/A int unpack_with_reexecution_offset,
0N/A int frame_size
0N/A );
0N/A
0N/A void* operator new(size_t s, unsigned size);
0N/A
0N/A public:
0N/A // Creation
0N/A static DeoptimizationBlob* create(
0N/A CodeBuffer* cb,
0N/A OopMapSet* oop_maps,
0N/A int unpack_offset,
0N/A int unpack_with_exception_offset,
0N/A int unpack_with_reexecution_offset,
0N/A int frame_size
0N/A );
0N/A
0N/A // Typing
0N/A bool is_deoptimization_stub() const { return true; }
0N/A const DeoptimizationBlob *as_deoptimization_stub() const { return this; }
0N/A bool exception_address_is_unpack_entry(address pc) const {
0N/A address unpack_pc = unpack();
0N/A return (pc == unpack_pc || (pc + frame::pc_return_offset) == unpack_pc);
0N/A }
0N/A
0N/A
0N/A
0N/A
0N/A // GC for args
0N/A void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* Nothing to do */ }
0N/A
0N/A // Printing
1601N/A void print_value_on(outputStream* st) const;
0N/A
1668N/A address unpack() const { return code_begin() + _unpack_offset; }
1668N/A address unpack_with_exception() const { return code_begin() + _unpack_with_exception; }
1668N/A address unpack_with_reexecution() const { return code_begin() + _unpack_with_reexecution; }
0N/A
0N/A // Alternate entry point for C1 where the exception and issuing pc
0N/A // are in JavaThread::_exception_oop and JavaThread::_exception_pc
0N/A // instead of being in registers. This is needed because C1 doesn't
0N/A // model exception paths in a way that keeps these registers free so
0N/A // there may be live values in those registers during deopt.
0N/A void set_unpack_with_exception_in_tls_offset(int offset) {
0N/A _unpack_with_exception_in_tls = offset;
1668N/A assert(code_contains(code_begin() + _unpack_with_exception_in_tls), "must be PC inside codeblob");
0N/A }
1668N/A address unpack_with_exception_in_tls() const { return code_begin() + _unpack_with_exception_in_tls; }
0N/A};
0N/A
0N/A
0N/A//----------------------------------------------------------------------------------------------------
0N/A// UncommonTrapBlob (currently only used by Compiler 2)
0N/A
0N/A#ifdef COMPILER2
0N/A
0N/Aclass UncommonTrapBlob: public SingletonBlob {
0N/A friend class VMStructs;
0N/A private:
0N/A // Creation support
0N/A UncommonTrapBlob(
0N/A CodeBuffer* cb,
0N/A int size,
0N/A OopMapSet* oop_maps,
0N/A int frame_size
0N/A );
0N/A
0N/A void* operator new(size_t s, unsigned size);
0N/A
0N/A public:
0N/A // Creation
0N/A static UncommonTrapBlob* create(
0N/A CodeBuffer* cb,
0N/A OopMapSet* oop_maps,
0N/A int frame_size
0N/A );
0N/A
0N/A // GC for args
0N/A void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* nothing to do */ }
0N/A
0N/A // Typing
0N/A bool is_uncommon_trap_stub() const { return true; }
0N/A};
0N/A
0N/A
0N/A//----------------------------------------------------------------------------------------------------
0N/A// ExceptionBlob: used for exception unwinding in compiled code (currently only used by Compiler 2)
0N/A
0N/Aclass ExceptionBlob: public SingletonBlob {
0N/A friend class VMStructs;
0N/A private:
0N/A // Creation support
0N/A ExceptionBlob(
0N/A CodeBuffer* cb,
0N/A int size,
0N/A OopMapSet* oop_maps,
0N/A int frame_size
0N/A );
0N/A
0N/A void* operator new(size_t s, unsigned size);
0N/A
0N/A public:
0N/A // Creation
0N/A static ExceptionBlob* create(
0N/A CodeBuffer* cb,
0N/A OopMapSet* oop_maps,
0N/A int frame_size
0N/A );
0N/A
0N/A // GC for args
0N/A void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ }
0N/A
0N/A // Typing
0N/A bool is_exception_stub() const { return true; }
0N/A};
0N/A#endif // COMPILER2
0N/A
0N/A
0N/A//----------------------------------------------------------------------------------------------------
0N/A// SafepointBlob: handles illegal_instruction exceptions during a safepoint
0N/A
0N/Aclass SafepointBlob: public SingletonBlob {
0N/A friend class VMStructs;
0N/A private:
0N/A // Creation support
0N/A SafepointBlob(
0N/A CodeBuffer* cb,
0N/A int size,
0N/A OopMapSet* oop_maps,
0N/A int frame_size
0N/A );
0N/A
0N/A void* operator new(size_t s, unsigned size);
0N/A
0N/A public:
0N/A // Creation
0N/A static SafepointBlob* create(
0N/A CodeBuffer* cb,
0N/A OopMapSet* oop_maps,
0N/A int frame_size
0N/A );
0N/A
0N/A // GC for args
0N/A void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { /* nothing to do */ }
0N/A
0N/A // Typing
0N/A bool is_safepoint_stub() const { return true; }
0N/A};
1879N/A
1879N/A#endif // SHARE_VM_CODE_CODEBLOB_HPP