--- a/hotspot/src/share/vm/code/codeBlob.hpp Mon Apr 25 21:25:22 2016 +0300
+++ b/hotspot/src/share/vm/code/codeBlob.hpp Tue Apr 26 10:28:51 2016 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -45,12 +45,14 @@
// CodeBlob - superclass for all entries in the CodeCache.
//
-// Suptypes are:
-// nmethod : Compiled Java methods (include method that calls to native code)
-// RuntimeStub : Call to VM runtime methods
-// DeoptimizationBlob : Used for deoptimizatation
-// ExceptionBlob : Used for stack unrolling
-// SafepointBlob : Used to handle illegal instruction exceptions
+// Subtypes are:
+// CompiledMethod : Compiled Java methods (include method that calls to native code)
+// nmethod : JIT Compiled Java methods
+// RuntimeBlob : Non-compiled method code; generated glue code
+// RuntimeStub : Call to VM runtime methods
+// DeoptimizationBlob : Used for deoptimization
+// ExceptionBlob : Used for stack unrolling
+// SafepointBlob : Used to handle illegal instruction exceptions
//
//
// Layout:
@@ -59,90 +61,79 @@
// - content space
// - instruction space
// - data space
-class DeoptimizationBlob;
+
+
+class CodeBlobLayout;
class CodeBlob VALUE_OBJ_CLASS_SPEC {
-
friend class VMStructs;
friend class JVMCIVMStructs;
friend class CodeCacheDumper;
- private:
+protected:
const char* _name;
int _size; // total size of CodeBlob in bytes
int _header_size; // size of header (depends on subclass)
- int _relocation_size; // size of relocation
- int _content_offset; // offset to where content region begins (this includes consts, insts, stubs)
- int _code_offset; // offset to where instructions region begins (this includes insts, stubs)
int _frame_complete_offset; // instruction offsets in [0.._frame_complete_offset) have
// not finished setting up their frame. Beware of pc's in
// that range. There is a similar range(s) on returns
// which we don't detect.
int _data_offset; // offset to where data region begins
int _frame_size; // size of stack frame
+
+ address _code_begin;
+ address _code_end;
+ address _content_begin; // address to where content region begins (this includes consts, insts, stubs)
+ // address _content_end - not required, for all CodeBlobs _code_end == _content_end for now
+ address _data_end;
+ address _relocation_begin;
+ address _relocation_end;
+
ImmutableOopMapSet* _oop_maps; // OopMap for this CodeBlob
- CodeStrings _strings;
+ bool _caller_must_gc_arguments;
+ CodeStrings _strings;
- public:
+ CodeBlob(const char* name, const CodeBlobLayout& layout, int frame_complete_offset, int frame_size, ImmutableOopMapSet* oop_maps, bool caller_must_gc_arguments);
+ CodeBlob(const char* name, const CodeBlobLayout& layout, CodeBuffer* cb, int frame_complete_offset, int frame_size, OopMapSet* oop_maps, bool caller_must_gc_arguments);
+public:
// Returns the space needed for CodeBlob
static unsigned int allocation_size(CodeBuffer* cb, int header_size);
static unsigned int align_code_offset(int offset);
- // Creation
- // a) simple CodeBlob
- // frame_complete is the offset from the beginning of the instructions
- // to where the frame setup (from stackwalk viewpoint) is complete.
- CodeBlob(const char* name, int header_size, int size, int frame_complete, int locs_size);
-
- // b) full CodeBlob
- CodeBlob(
- const char* name,
- CodeBuffer* cb,
- int header_size,
- int size,
- int frame_complete,
- int frame_size,
- OopMapSet* oop_maps
- );
-
// Deletion
- void flush();
+ virtual void flush();
// Typing
- virtual bool is_buffer_blob() const { return false; }
- virtual bool is_nmethod() const { return false; }
- virtual bool is_runtime_stub() const { return false; }
- virtual bool is_deoptimization_stub() const { return false; }
- virtual bool is_uncommon_trap_stub() const { return false; }
- virtual bool is_exception_stub() const { return false; }
+ virtual bool is_buffer_blob() const { return false; }
+ virtual bool is_nmethod() const { return false; }
+ virtual bool is_runtime_stub() const { return false; }
+ virtual bool is_deoptimization_stub() const { return false; }
+ virtual bool is_uncommon_trap_stub() const { return false; }
+ virtual bool is_exception_stub() const { return false; }
virtual bool is_safepoint_stub() const { return false; }
virtual bool is_adapter_blob() const { return false; }
virtual bool is_method_handles_adapter_blob() const { return false; }
+ virtual bool is_compiled() const { return false; }
virtual bool is_compiled_by_c2() const { return false; }
virtual bool is_compiled_by_c1() const { return false; }
virtual bool is_compiled_by_jvmci() const { return false; }
// Casting
- nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; }
+ nmethod* as_nmethod_or_null() { return is_nmethod() ? (nmethod*) this : NULL; }
+ nmethod* as_nmethod() { assert(is_nmethod(), "must be nmethod"); return (nmethod*) this; }
+ CompiledMethod* as_compiled_method_or_null() { return is_compiled() ? (CompiledMethod*) this : NULL; }
+ CompiledMethod* as_compiled_method() { assert(is_compiled(), "must be compiled"); return (CompiledMethod*) this; }
// Boundaries
- address header_begin() const { return (address) this; }
- address header_end() const { return ((address) this) + _header_size; };
- relocInfo* relocation_begin() const { return (relocInfo*) header_end(); };
- relocInfo* relocation_end() const { return (relocInfo*)(header_end() + _relocation_size); }
- address content_begin() const { return (address) header_begin() + _content_offset; }
- address content_end() const { return (address) header_begin() + _data_offset; }
- address code_begin() const { return (address) header_begin() + _code_offset; }
- address code_end() const { return (address) header_begin() + _data_offset; }
- address data_begin() const { return (address) header_begin() + _data_offset; }
- address data_end() const { return (address) header_begin() + _size; }
-
- // Offsets
- int relocation_offset() const { return _header_size; }
- int content_offset() const { return _content_offset; }
- int code_offset() const { return _code_offset; }
- int data_offset() const { return _data_offset; }
+ address header_begin() const { return (address) this; }
+ relocInfo* relocation_begin() const { return (relocInfo*) _relocation_begin; };
+ relocInfo* relocation_end() const { return (relocInfo*) _relocation_end; }
+ address content_begin() const { return _content_begin; }
+ address 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 constructor
+ address code_begin() const { return _code_begin; }
+ address code_end() const { return _code_end; }
+ address data_end() const { return _data_end; }
// Sizes
int size() const { return _size; }
@@ -150,17 +141,12 @@
int relocation_size() const { return (address) relocation_end() - (address) relocation_begin(); }
int content_size() const { return content_end() - content_begin(); }
int code_size() const { return code_end() - code_begin(); }
- int data_size() const { return data_end() - data_begin(); }
// Containment
bool blob_contains(address addr) const { return header_begin() <= addr && addr < data_end(); }
- bool relocation_contains(relocInfo* addr) const{ return relocation_begin() <= addr && addr < relocation_end(); }
- bool content_contains(address addr) const { return content_begin() <= addr && addr < content_end(); }
bool code_contains(address addr) const { return code_begin() <= addr && addr < code_end(); }
- bool data_contains(address addr) const { return data_begin() <= addr && addr < data_end(); }
- bool contains(address addr) const { return content_contains(addr); }
- bool is_frame_complete_at(address addr) const { return code_contains(addr) &&
- addr >= code_begin() + _frame_complete_offset; }
+ bool contains(address addr) const { return content_begin() <= addr && addr < content_end(); }
+ bool is_frame_complete_at(address addr) const { return code_contains(addr) && addr >= code_begin() + _frame_complete_offset; }
// CodeCache support: really only used by the nmethods, but in order to get
// asserts and certain bookkeeping to work in the CodeCache they are defined
@@ -178,29 +164,26 @@
ImmutableOopMapSet* oop_maps() const { return _oop_maps; }
void set_oop_maps(OopMapSet* p);
const ImmutableOopMap* oop_map_for_return_address(address return_address);
- virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { ShouldNotReachHere(); }
+ virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) = 0;
// Frame support
int frame_size() const { return _frame_size; }
void set_frame_size(int size) { _frame_size = size; }
// Returns true, if the next frame is responsible for GC'ing oops passed as arguments
- virtual bool caller_must_gc_arguments(JavaThread* thread) const { return false; }
+ bool caller_must_gc_arguments(JavaThread* thread) const { return _caller_must_gc_arguments; }
// Naming
const char* name() const { return _name; }
void set_name(const char* name) { _name = name; }
// Debugging
- virtual void verify();
- void print() const { print_on(tty); }
+ virtual void verify() = 0;
+ virtual void print() const { print_on(tty); };
virtual void print_on(outputStream* st) const;
virtual void print_value_on(outputStream* st) const;
void print_code();
- // Deal with Disassembler, VTune, Forte, JvmtiExport, MemoryService.
- static void trace_new_stub(CodeBlob* blob, const char* name1, const char* name2 = "");
-
// Print the comment associated with offset on stream, if there is one
virtual void print_block_comment(outputStream* stream, address block_begin) const {
intptr_t offset = (intptr_t)(block_begin - code_begin());
@@ -221,11 +204,142 @@
}
};
+class CodeBlobLayout : public StackObj {
+private:
+ int _size;
+ int _header_size;
+ int _relocation_size;
+ int _content_offset;
+ int _code_offset;
+ int _data_offset;
+ address _code_begin;
+ address _code_end;
+ address _content_begin;
+ address _content_end;
+ address _data_end;
+ address _relocation_begin;
+ address _relocation_end;
+
+public:
+ CodeBlobLayout(address code_begin, address code_end, address content_begin, address content_end, address data_end, address relocation_begin, address relocation_end) :
+ _size(0),
+ _header_size(0),
+ _relocation_size(0),
+ _content_offset(0),
+ _code_offset(0),
+ _data_offset(0),
+ _content_begin(content_begin),
+ _content_end(content_end),
+ _code_begin(code_begin),
+ _code_end(code_end),
+ _data_end(data_end),
+ _relocation_begin(relocation_begin),
+ _relocation_end(relocation_end)
+ {
+ }
+
+ CodeBlobLayout(const address start, int size, int header_size, int relocation_size, int data_offset) :
+ _size(size),
+ _header_size(header_size),
+ _relocation_size(relocation_size),
+ _content_offset(CodeBlob::align_code_offset(_header_size + _relocation_size)),
+ _code_offset(_content_offset),
+ _data_offset(data_offset)
+ {
+ assert(_relocation_size == round_to(_relocation_size, oopSize), "unaligned size");
+
+ _code_begin = (address) start + _code_offset;
+ _code_end = (address) start + _data_offset;
+
+ _content_begin = (address) start + _content_offset;
+ _content_end = (address) start + _data_offset;
+
+ _data_end = (address) start + _size;
+ _relocation_begin = (address) start + _header_size;
+ _relocation_end = _relocation_begin + _relocation_size;
+ }
+
+ CodeBlobLayout(const address start, int size, int header_size, const CodeBuffer* cb) :
+ _size(size),
+ _header_size(header_size),
+ _relocation_size(round_to(cb->total_relocation_size(), oopSize)),
+ _content_offset(CodeBlob::align_code_offset(_header_size + _relocation_size)),
+ _code_offset(_content_offset + cb->total_offset_of(cb->insts())),
+ _data_offset(_content_offset + round_to(cb->total_content_size(), oopSize))
+ {
+ assert(_relocation_size == round_to(_relocation_size, oopSize), "unaligned size");
+
+ _code_begin = (address) start + _code_offset;
+ _code_end = (address) start + _data_offset;
+
+ _content_begin = (address) start + _content_offset;
+ _content_end = (address) start + _data_offset;
+
+ _data_end = (address) start + _size;
+ _relocation_begin = (address) start + _header_size;
+ _relocation_end = _relocation_begin + _relocation_size;
+ }
+
+ int size() const { return _size; }
+ int header_size() const { return _header_size; }
+ int relocation_size() const { return _relocation_size; }
+ int content_offset() const { return _content_offset; }
+ int code_offset() const { return _code_offset; }
+ int data_offset() const { return _data_offset; }
+ address code_begin() const { return _code_begin; }
+ address code_end() const { return _code_end; }
+ address data_end() const { return _data_end; }
+ address relocation_begin() const { return _relocation_begin; }
+ address relocation_end() const { return _relocation_end; }
+ address content_begin() const { return _content_begin; }
+ address content_end() const { return _content_end; }
+};
+
+
+class RuntimeBlob : public CodeBlob {
+ friend class VMStructs;
+ public:
+
+ // Creation
+ // a) simple CodeBlob
+ // frame_complete is the offset from the beginning of the instructions
+ // to where the frame setup (from stackwalk viewpoint) is complete.
+ RuntimeBlob(const char* name, int header_size, int size, int frame_complete, int locs_size);
+
+ // b) full CodeBlob
+ RuntimeBlob(
+ const char* name,
+ CodeBuffer* cb,
+ int header_size,
+ int size,
+ int frame_complete,
+ int frame_size,
+ OopMapSet* oop_maps,
+ bool caller_must_gc_arguments = false
+ );
+
+ // GC support
+ virtual bool is_alive() const = 0;
+
+ void verify();
+
+ // OopMap for frame
+ virtual void preserve_callee_argument_oops(frame fr, const RegisterMap* reg_map, OopClosure* f) { ShouldNotReachHere(); }
+
+ // Debugging
+ void print() const { print_on(tty); }
+ virtual void print_on(outputStream* st) const { CodeBlob::print_on(st); }
+ virtual void print_value_on(outputStream* st) const { CodeBlob::print_value_on(st); }
+
+ // Deal with Disassembler, VTune, Forte, JvmtiExport, MemoryService.
+ static void trace_new_stub(RuntimeBlob* blob, const char* name1, const char* name2 = "");
+};
+
class WhiteBox;
//----------------------------------------------------------------------------------------------------
// BufferBlob: used to hold non-relocatable machine code such as the interpreter, stubroutines, etc.
-class BufferBlob: public CodeBlob {
+class BufferBlob: public RuntimeBlob {
friend class VMStructs;
friend class AdapterBlob;
friend class MethodHandlesAdapterBlob;
@@ -293,11 +407,9 @@
//----------------------------------------------------------------------------------------------------
// RuntimeStub: describes stubs used by compiled code to call a (static) C++ runtime routine
-class RuntimeStub: public CodeBlob {
+class RuntimeStub: public RuntimeBlob {
friend class VMStructs;
private:
- bool _caller_must_gc_arguments;
-
// Creation support
RuntimeStub(
const char* name,
@@ -325,10 +437,7 @@
// Typing
bool is_runtime_stub() const { return true; }
- // GC support
- bool caller_must_gc_arguments(JavaThread* thread) const { return _caller_must_gc_arguments; }
-
- address entry_point() { return code_begin(); }
+ address entry_point() const { return code_begin(); }
// GC/Verification support
void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* nothing to do */ }
@@ -343,7 +452,7 @@
//----------------------------------------------------------------------------------------------------
// Super-class for all blobs that exist in only one instance. Implements default behaviour.
-class SingletonBlob: public CodeBlob {
+class SingletonBlob: public RuntimeBlob {
friend class VMStructs;
protected:
@@ -358,13 +467,15 @@
int frame_size,
OopMapSet* oop_maps
)
- : CodeBlob(name, cb, header_size, size, CodeOffsets::frame_never_safe, frame_size, oop_maps)
+ : RuntimeBlob(name, cb, header_size, size, CodeOffsets::frame_never_safe, frame_size, oop_maps)
{};
address entry_point() { return code_begin(); }
bool is_alive() const { return true; }
+ // GC/Verification support
+ void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f) { /* nothing to do */ }
void verify(); // does nothing
void print_on(outputStream* st) const;
void print_value_on(outputStream* st) const;