mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
6958292: C1: Enable parallel compilation
Enable parallel compilation in C1 Reviewed-by: never, kvn
This commit is contained in:
parent
36f8c82970
commit
00b75f8353
30 changed files with 328 additions and 344 deletions
|
@ -181,8 +181,8 @@ bool FrameMap::is_caller_save_register (Register r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FrameMap::init () {
|
void FrameMap::initialize() {
|
||||||
if (_init_done) return;
|
assert(!_init_done, "once");
|
||||||
|
|
||||||
int i=0;
|
int i=0;
|
||||||
// Register usage:
|
// Register usage:
|
||||||
|
|
|
@ -136,8 +136,8 @@ XMMRegister FrameMap::nr2xmmreg(int rnr) {
|
||||||
// FrameMap
|
// FrameMap
|
||||||
//--------------------------------------------------------
|
//--------------------------------------------------------
|
||||||
|
|
||||||
void FrameMap::init() {
|
void FrameMap::initialize() {
|
||||||
if (_init_done) return;
|
assert(!_init_done, "once");
|
||||||
|
|
||||||
assert(nof_cpu_regs == LP64_ONLY(16) NOT_LP64(8), "wrong number of CPU registers");
|
assert(nof_cpu_regs == LP64_ONLY(16) NOT_LP64(8), "wrong number of CPU registers");
|
||||||
map_register(0, rsi); rsi_opr = LIR_OprFact::single_cpu(0);
|
map_register(0, rsi); rsi_opr = LIR_OprFact::single_cpu(0);
|
||||||
|
|
|
@ -26,9 +26,11 @@
|
||||||
#include "incls/_c1_Canonicalizer.cpp.incl"
|
#include "incls/_c1_Canonicalizer.cpp.incl"
|
||||||
|
|
||||||
|
|
||||||
static void do_print_value(Value* vp) {
|
class PrintValueVisitor: public ValueVisitor {
|
||||||
|
void visit(Value* vp) {
|
||||||
(*vp)->print_line();
|
(*vp)->print_line();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void Canonicalizer::set_canonical(Value x) {
|
void Canonicalizer::set_canonical(Value x) {
|
||||||
assert(x != NULL, "value must exist");
|
assert(x != NULL, "value must exist");
|
||||||
|
@ -37,10 +39,11 @@ void Canonicalizer::set_canonical(Value x) {
|
||||||
// in the instructions).
|
// in the instructions).
|
||||||
if (canonical() != x) {
|
if (canonical() != x) {
|
||||||
if (PrintCanonicalization) {
|
if (PrintCanonicalization) {
|
||||||
canonical()->input_values_do(do_print_value);
|
PrintValueVisitor do_print_value;
|
||||||
|
canonical()->input_values_do(&do_print_value);
|
||||||
canonical()->print_line();
|
canonical()->print_line();
|
||||||
tty->print_cr("canonicalized to:");
|
tty->print_cr("canonicalized to:");
|
||||||
x->input_values_do(do_print_value);
|
x->input_values_do(&do_print_value);
|
||||||
x->print_line();
|
x->print_line();
|
||||||
tty->cr();
|
tty->cr();
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,9 +66,6 @@ class PhaseTraceTime: public TraceTime {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Arena* Compilation::_arena = NULL;
|
|
||||||
Compilation* Compilation::_compilation = NULL;
|
|
||||||
|
|
||||||
// Implementation of Compilation
|
// Implementation of Compilation
|
||||||
|
|
||||||
|
|
||||||
|
@ -238,9 +235,23 @@ void Compilation::emit_code_epilog(LIR_Assembler* assembler) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Compilation::setup_code_buffer(CodeBuffer* code, int call_stub_estimate) {
|
||||||
|
// Preinitialize the consts section to some large size:
|
||||||
|
int locs_buffer_size = 20 * (relocInfo::length_limit + sizeof(relocInfo));
|
||||||
|
char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size);
|
||||||
|
code->insts()->initialize_shared_locs((relocInfo*)locs_buffer,
|
||||||
|
locs_buffer_size / sizeof(relocInfo));
|
||||||
|
code->initialize_consts_size(Compilation::desired_max_constant_size());
|
||||||
|
// Call stubs + deopt/exception handler
|
||||||
|
code->initialize_stubs_size((call_stub_estimate * LIR_Assembler::call_stub_size) +
|
||||||
|
LIR_Assembler::exception_handler_size +
|
||||||
|
LIR_Assembler::deopt_handler_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Compilation::emit_code_body() {
|
int Compilation::emit_code_body() {
|
||||||
// emit code
|
// emit code
|
||||||
Runtime1::setup_code_buffer(code(), allocator()->num_calls());
|
setup_code_buffer(code(), allocator()->num_calls());
|
||||||
code()->initialize_oop_recorder(env()->oop_recorder());
|
code()->initialize_oop_recorder(env()->oop_recorder());
|
||||||
|
|
||||||
_masm = new C1_MacroAssembler(code());
|
_masm = new C1_MacroAssembler(code());
|
||||||
|
@ -422,7 +433,8 @@ void Compilation::generate_exception_handler_table() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method, int osr_bci)
|
Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
|
||||||
|
int osr_bci, BufferBlob* buffer_blob)
|
||||||
: _compiler(compiler)
|
: _compiler(compiler)
|
||||||
, _env(env)
|
, _env(env)
|
||||||
, _method(method)
|
, _method(method)
|
||||||
|
@ -437,8 +449,10 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho
|
||||||
, _bailout_msg(NULL)
|
, _bailout_msg(NULL)
|
||||||
, _exception_info_list(NULL)
|
, _exception_info_list(NULL)
|
||||||
, _allocator(NULL)
|
, _allocator(NULL)
|
||||||
, _code(Runtime1::get_buffer_blob()->instructions_begin(),
|
, _next_id(0)
|
||||||
Runtime1::get_buffer_blob()->instructions_size())
|
, _next_block_id(0)
|
||||||
|
, _code(buffer_blob->instructions_begin(),
|
||||||
|
buffer_blob->instructions_size())
|
||||||
, _current_instruction(NULL)
|
, _current_instruction(NULL)
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
, _last_instruction_printed(NULL)
|
, _last_instruction_printed(NULL)
|
||||||
|
@ -446,17 +460,15 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho
|
||||||
{
|
{
|
||||||
PhaseTraceTime timeit(_t_compile);
|
PhaseTraceTime timeit(_t_compile);
|
||||||
|
|
||||||
assert(_arena == NULL, "shouldn't only one instance of Compilation in existence at a time");
|
|
||||||
_arena = Thread::current()->resource_area();
|
_arena = Thread::current()->resource_area();
|
||||||
_compilation = this;
|
_env->set_compiler_data(this);
|
||||||
_exception_info_list = new ExceptionInfoList();
|
_exception_info_list = new ExceptionInfoList();
|
||||||
_implicit_exception_table.set_size(0);
|
_implicit_exception_table.set_size(0);
|
||||||
compile_method();
|
compile_method();
|
||||||
}
|
}
|
||||||
|
|
||||||
Compilation::~Compilation() {
|
Compilation::~Compilation() {
|
||||||
_arena = NULL;
|
_env->set_compiler_data(NULL);
|
||||||
_compilation = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -53,15 +53,11 @@ define_stack(ExceptionInfoList, ExceptionInfoArray)
|
||||||
|
|
||||||
class Compilation: public StackObj {
|
class Compilation: public StackObj {
|
||||||
friend class CompilationResourceObj;
|
friend class CompilationResourceObj;
|
||||||
private:
|
|
||||||
|
|
||||||
static Arena* _arena;
|
|
||||||
static Arena* arena() { return _arena; }
|
|
||||||
|
|
||||||
static Compilation* _compilation;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// compilation specifics
|
// compilation specifics
|
||||||
|
Arena* _arena;
|
||||||
|
int _next_id;
|
||||||
|
int _next_block_id;
|
||||||
AbstractCompiler* _compiler;
|
AbstractCompiler* _compiler;
|
||||||
ciEnv* _env;
|
ciEnv* _env;
|
||||||
ciMethod* _method;
|
ciMethod* _method;
|
||||||
|
@ -108,10 +104,14 @@ class Compilation: public StackObj {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// creation
|
// creation
|
||||||
Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method, int osr_bci);
|
Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
|
||||||
|
int osr_bci, BufferBlob* buffer_blob);
|
||||||
~Compilation();
|
~Compilation();
|
||||||
|
|
||||||
static Compilation* current_compilation() { return _compilation; }
|
|
||||||
|
static Compilation* current() {
|
||||||
|
return (Compilation*) ciEnv::current()->compiler_data();
|
||||||
|
}
|
||||||
|
|
||||||
// accessors
|
// accessors
|
||||||
ciEnv* env() const { return _env; }
|
ciEnv* env() const { return _env; }
|
||||||
|
@ -128,6 +128,15 @@ class Compilation: public StackObj {
|
||||||
CodeBuffer* code() { return &_code; }
|
CodeBuffer* code() { return &_code; }
|
||||||
C1_MacroAssembler* masm() const { return _masm; }
|
C1_MacroAssembler* masm() const { return _masm; }
|
||||||
CodeOffsets* offsets() { return &_offsets; }
|
CodeOffsets* offsets() { return &_offsets; }
|
||||||
|
Arena* arena() { return _arena; }
|
||||||
|
|
||||||
|
// Instruction ids
|
||||||
|
int get_next_id() { return _next_id++; }
|
||||||
|
int number_of_instructions() const { return _next_id; }
|
||||||
|
|
||||||
|
// BlockBegin ids
|
||||||
|
int get_next_block_id() { return _next_block_id++; }
|
||||||
|
int number_of_blocks() const { return _next_block_id; }
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
void set_has_exception_handlers(bool f) { _has_exception_handlers = f; }
|
void set_has_exception_handlers(bool f) { _has_exception_handlers = f; }
|
||||||
|
@ -158,6 +167,15 @@ class Compilation: public StackObj {
|
||||||
bool bailed_out() const { return _bailout_msg != NULL; }
|
bool bailed_out() const { return _bailout_msg != NULL; }
|
||||||
const char* bailout_msg() const { return _bailout_msg; }
|
const char* bailout_msg() const { return _bailout_msg; }
|
||||||
|
|
||||||
|
static int desired_max_code_buffer_size() {
|
||||||
|
return (int) NMethodSizeLimit; // default 256K or 512K
|
||||||
|
}
|
||||||
|
static int desired_max_constant_size() {
|
||||||
|
return (int) NMethodSizeLimit / 10; // about 25K
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_code_buffer(CodeBuffer* cb, int call_stub_estimate);
|
||||||
|
|
||||||
// timers
|
// timers
|
||||||
static void print_timers();
|
static void print_timers();
|
||||||
|
|
||||||
|
@ -203,7 +221,10 @@ class InstructionMark: public StackObj {
|
||||||
// Base class for objects allocated by the compiler in the compilation arena
|
// Base class for objects allocated by the compiler in the compilation arena
|
||||||
class CompilationResourceObj ALLOCATION_SUPER_CLASS_SPEC {
|
class CompilationResourceObj ALLOCATION_SUPER_CLASS_SPEC {
|
||||||
public:
|
public:
|
||||||
void* operator new(size_t size) { return Compilation::arena()->Amalloc(size); }
|
void* operator new(size_t size) { return Compilation::current()->arena()->Amalloc(size); }
|
||||||
|
void* operator new(size_t size, Arena* arena) {
|
||||||
|
return arena->Amalloc(size);
|
||||||
|
}
|
||||||
void operator delete(void* p) {} // nothing to do
|
void operator delete(void* p) {} // nothing to do
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -27,9 +27,6 @@
|
||||||
|
|
||||||
volatile int Compiler::_runtimes = uninitialized;
|
volatile int Compiler::_runtimes = uninitialized;
|
||||||
|
|
||||||
volatile bool Compiler::_compiling = false;
|
|
||||||
|
|
||||||
|
|
||||||
Compiler::Compiler() {
|
Compiler::Compiler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,47 +36,62 @@ Compiler::~Compiler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Compiler::initialize_all() {
|
||||||
|
BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
|
||||||
|
Arena* arena = new Arena();
|
||||||
|
Runtime1::initialize(buffer_blob);
|
||||||
|
FrameMap::initialize();
|
||||||
|
// initialize data structures
|
||||||
|
ValueType::initialize(arena);
|
||||||
|
// Instruction::initialize();
|
||||||
|
// BlockBegin::initialize();
|
||||||
|
GraphBuilder::initialize();
|
||||||
|
// note: to use more than one instance of LinearScan at a time this function call has to
|
||||||
|
// be moved somewhere outside of this constructor:
|
||||||
|
Interval::initialize(arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Compiler::initialize() {
|
void Compiler::initialize() {
|
||||||
if (_runtimes != initialized) {
|
if (_runtimes != initialized) {
|
||||||
initialize_runtimes( Runtime1::initialize, &_runtimes);
|
initialize_runtimes( initialize_all, &_runtimes);
|
||||||
}
|
}
|
||||||
mark_initialized();
|
mark_initialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BufferBlob* Compiler::build_buffer_blob() {
|
||||||
|
// setup CodeBuffer. Preallocate a BufferBlob of size
|
||||||
|
// NMethodSizeLimit plus some extra space for constants.
|
||||||
|
int code_buffer_size = Compilation::desired_max_code_buffer_size() +
|
||||||
|
Compilation::desired_max_constant_size();
|
||||||
|
BufferBlob* blob = BufferBlob::create("Compiler1 temporary CodeBuffer",
|
||||||
|
code_buffer_size);
|
||||||
|
guarantee(blob != NULL, "must create initial code buffer");
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
|
void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
|
||||||
|
// Allocate buffer blob once at startup since allocation for each
|
||||||
|
// compilation seems to be too expensive (at least on Intel win32).
|
||||||
|
BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
|
||||||
|
if (buffer_blob == NULL) {
|
||||||
|
buffer_blob = build_buffer_blob();
|
||||||
|
CompilerThread::current()->set_buffer_blob(buffer_blob);
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_initialized()) {
|
if (!is_initialized()) {
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
// invoke compilation
|
// invoke compilation
|
||||||
#ifdef TIERED
|
|
||||||
// We are thread in native here...
|
|
||||||
CompilerThread* thread = CompilerThread::current();
|
|
||||||
{
|
|
||||||
ThreadInVMfromNative tv(thread);
|
|
||||||
MutexLocker only_one (C1_lock, thread);
|
|
||||||
while ( _compiling) {
|
|
||||||
C1_lock->wait();
|
|
||||||
}
|
|
||||||
_compiling = true;
|
|
||||||
}
|
|
||||||
#endif // TIERED
|
|
||||||
{
|
{
|
||||||
// We are nested here because we need for the destructor
|
// We are nested here because we need for the destructor
|
||||||
// of Compilation to occur before we release the any
|
// of Compilation to occur before we release the any
|
||||||
// competing compiler thread
|
// competing compiler thread
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
Compilation c(this, env, method, entry_bci);
|
Compilation c(this, env, method, entry_bci, buffer_blob);
|
||||||
}
|
}
|
||||||
#ifdef TIERED
|
|
||||||
{
|
|
||||||
ThreadInVMfromNative tv(thread);
|
|
||||||
MutexLocker only_one (C1_lock, thread);
|
|
||||||
_compiling = false;
|
|
||||||
C1_lock->notify();
|
|
||||||
}
|
|
||||||
#endif // TIERED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,10 +31,6 @@ class Compiler: public AbstractCompiler {
|
||||||
// Tracks whether runtime has been initialized
|
// Tracks whether runtime has been initialized
|
||||||
static volatile int _runtimes;
|
static volatile int _runtimes;
|
||||||
|
|
||||||
// In tiered it is possible for multiple threads to want to do compilation
|
|
||||||
// only one can enter c1 at a time
|
|
||||||
static volatile bool _compiling;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Creation
|
// Creation
|
||||||
Compiler();
|
Compiler();
|
||||||
|
@ -47,6 +43,7 @@ class Compiler: public AbstractCompiler {
|
||||||
virtual bool is_c1() { return true; };
|
virtual bool is_c1() { return true; };
|
||||||
#endif // TIERED
|
#endif // TIERED
|
||||||
|
|
||||||
|
BufferBlob* build_buffer_blob();
|
||||||
|
|
||||||
// Missing feature tests
|
// Missing feature tests
|
||||||
virtual bool supports_native() { return true; }
|
virtual bool supports_native() { return true; }
|
||||||
|
@ -58,6 +55,7 @@ class Compiler: public AbstractCompiler {
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
virtual void initialize();
|
virtual void initialize();
|
||||||
|
static void initialize_all();
|
||||||
|
|
||||||
// Compilation entry point for methods
|
// Compilation entry point for methods
|
||||||
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
|
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
|
||||||
|
|
|
@ -153,7 +153,7 @@ int FrameMap::_cpu_reg2rnr [FrameMap::nof_cpu_regs];
|
||||||
|
|
||||||
|
|
||||||
FrameMap::FrameMap(ciMethod* method, int monitors, int reserved_argument_area_size) {
|
FrameMap::FrameMap(ciMethod* method, int monitors, int reserved_argument_area_size) {
|
||||||
if (!_init_done) init();
|
assert(_init_done, "should already be completed");
|
||||||
|
|
||||||
_framesize = -1;
|
_framesize = -1;
|
||||||
_num_spills = -1;
|
_num_spills = -1;
|
||||||
|
|
|
@ -235,7 +235,7 @@ class FrameMap : public CompilationResourceObj {
|
||||||
return _caller_save_fpu_regs[i];
|
return _caller_save_fpu_regs[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init();
|
static void initialize();
|
||||||
};
|
};
|
||||||
|
|
||||||
// CallingConvention
|
// CallingConvention
|
||||||
|
|
|
@ -2530,16 +2530,10 @@ void GraphBuilder::iterate_all_blocks(bool start_in_current_block_for_inlining)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool GraphBuilder::_is_initialized = false;
|
|
||||||
bool GraphBuilder::_can_trap [Bytecodes::number_of_java_codes];
|
bool GraphBuilder::_can_trap [Bytecodes::number_of_java_codes];
|
||||||
bool GraphBuilder::_is_async[Bytecodes::number_of_java_codes];
|
bool GraphBuilder::_is_async[Bytecodes::number_of_java_codes];
|
||||||
|
|
||||||
void GraphBuilder::initialize() {
|
void GraphBuilder::initialize() {
|
||||||
// make sure initialization happens only once (need a
|
|
||||||
// lock here, if we allow the compiler to be re-entrant)
|
|
||||||
if (is_initialized()) return;
|
|
||||||
_is_initialized = true;
|
|
||||||
|
|
||||||
// the following bytecodes are assumed to potentially
|
// the following bytecodes are assumed to potentially
|
||||||
// throw exceptions in compiled code - note that e.g.
|
// throw exceptions in compiled code - note that e.g.
|
||||||
// monitorexit & the return bytecodes do not throw
|
// monitorexit & the return bytecodes do not throw
|
||||||
|
@ -2855,7 +2849,6 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope)
|
||||||
BlockList* bci2block = blm.bci2block();
|
BlockList* bci2block = blm.bci2block();
|
||||||
BlockBegin* start_block = bci2block->at(0);
|
BlockBegin* start_block = bci2block->at(0);
|
||||||
|
|
||||||
assert(is_initialized(), "GraphBuilder must have been initialized");
|
|
||||||
push_root_scope(scope, bci2block, start_block);
|
push_root_scope(scope, bci2block, start_block);
|
||||||
|
|
||||||
// setup state for std entry
|
// setup state for std entry
|
||||||
|
|
|
@ -162,7 +162,6 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
|
||||||
};
|
};
|
||||||
|
|
||||||
// for all GraphBuilders
|
// for all GraphBuilders
|
||||||
static bool _is_initialized; // true if trap tables were initialized, false otherwise
|
|
||||||
static bool _can_trap[Bytecodes::number_of_java_codes];
|
static bool _can_trap[Bytecodes::number_of_java_codes];
|
||||||
static bool _is_async[Bytecodes::number_of_java_codes];
|
static bool _is_async[Bytecodes::number_of_java_codes];
|
||||||
|
|
||||||
|
@ -268,7 +267,6 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
|
||||||
Instruction* append_split(StateSplit* instr);
|
Instruction* append_split(StateSplit* instr);
|
||||||
|
|
||||||
// other helpers
|
// other helpers
|
||||||
static bool is_initialized() { return _is_initialized; }
|
|
||||||
static bool is_async(Bytecodes::Code code) {
|
static bool is_async(Bytecodes::Code code) {
|
||||||
assert(0 <= code && code < Bytecodes::number_of_java_codes, "illegal bytecode");
|
assert(0 <= code && code < Bytecodes::number_of_java_codes, "illegal bytecode");
|
||||||
return _is_async[code];
|
return _is_async[code];
|
||||||
|
|
|
@ -287,11 +287,6 @@ void CodeEmitInfo::add_register_oop(LIR_Opr opr) {
|
||||||
IR::IR(Compilation* compilation, ciMethod* method, int osr_bci) :
|
IR::IR(Compilation* compilation, ciMethod* method, int osr_bci) :
|
||||||
_locals_size(in_WordSize(-1))
|
_locals_size(in_WordSize(-1))
|
||||||
, _num_loops(0) {
|
, _num_loops(0) {
|
||||||
// initialize data structures
|
|
||||||
ValueType::initialize();
|
|
||||||
Instruction::initialize();
|
|
||||||
BlockBegin::initialize();
|
|
||||||
GraphBuilder::initialize();
|
|
||||||
// setup IR fields
|
// setup IR fields
|
||||||
_compilation = compilation;
|
_compilation = compilation;
|
||||||
_top_scope = new IRScope(compilation, NULL, -1, method, osr_bci, true);
|
_top_scope = new IRScope(compilation, NULL, -1, method, osr_bci, true);
|
||||||
|
@ -381,15 +376,15 @@ void IR::split_critical_edges() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class UseCountComputer: public AllStatic {
|
class UseCountComputer: public ValueVisitor, BlockClosure {
|
||||||
private:
|
private:
|
||||||
static void update_use_count(Value* n) {
|
void visit(Value* n) {
|
||||||
// Local instructions and Phis for expression stack values at the
|
// Local instructions and Phis for expression stack values at the
|
||||||
// start of basic blocks are not added to the instruction list
|
// start of basic blocks are not added to the instruction list
|
||||||
if ((*n)->bci() == -99 && (*n)->as_Local() == NULL &&
|
if ((*n)->bci() == -99 && (*n)->as_Local() == NULL &&
|
||||||
(*n)->as_Phi() == NULL) {
|
(*n)->as_Phi() == NULL) {
|
||||||
assert(false, "a node was not appended to the graph");
|
assert(false, "a node was not appended to the graph");
|
||||||
Compilation::current_compilation()->bailout("a node was not appended to the graph");
|
Compilation::current()->bailout("a node was not appended to the graph");
|
||||||
}
|
}
|
||||||
// use n's input if not visited before
|
// use n's input if not visited before
|
||||||
if (!(*n)->is_pinned() && !(*n)->has_uses()) {
|
if (!(*n)->is_pinned() && !(*n)->has_uses()) {
|
||||||
|
@ -402,31 +397,31 @@ class UseCountComputer: public AllStatic {
|
||||||
(*n)->_use_count++;
|
(*n)->_use_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Values* worklist;
|
Values* worklist;
|
||||||
static int depth;
|
int depth;
|
||||||
enum {
|
enum {
|
||||||
max_recurse_depth = 20
|
max_recurse_depth = 20
|
||||||
};
|
};
|
||||||
|
|
||||||
static void uses_do(Value* n) {
|
void uses_do(Value* n) {
|
||||||
depth++;
|
depth++;
|
||||||
if (depth > max_recurse_depth) {
|
if (depth > max_recurse_depth) {
|
||||||
// don't allow the traversal to recurse too deeply
|
// don't allow the traversal to recurse too deeply
|
||||||
worklist->push(*n);
|
worklist->push(*n);
|
||||||
} else {
|
} else {
|
||||||
(*n)->input_values_do(update_use_count);
|
(*n)->input_values_do(this);
|
||||||
// special handling for some instructions
|
// special handling for some instructions
|
||||||
if ((*n)->as_BlockEnd() != NULL) {
|
if ((*n)->as_BlockEnd() != NULL) {
|
||||||
// note on BlockEnd:
|
// note on BlockEnd:
|
||||||
// must 'use' the stack only if the method doesn't
|
// must 'use' the stack only if the method doesn't
|
||||||
// terminate, however, in those cases stack is empty
|
// terminate, however, in those cases stack is empty
|
||||||
(*n)->state_values_do(update_use_count);
|
(*n)->state_values_do(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
depth--;
|
depth--;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void basic_compute_use_count(BlockBegin* b) {
|
void block_do(BlockBegin* b) {
|
||||||
depth = 0;
|
depth = 0;
|
||||||
// process all pinned nodes as the roots of expression trees
|
// process all pinned nodes as the roots of expression trees
|
||||||
for (Instruction* n = b; n != NULL; n = n->next()) {
|
for (Instruction* n = b; n != NULL; n = n->next()) {
|
||||||
|
@ -449,18 +444,19 @@ class UseCountComputer: public AllStatic {
|
||||||
assert(depth == 0, "should have counted back down");
|
assert(depth == 0, "should have counted back down");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UseCountComputer() {
|
||||||
|
worklist = new Values();
|
||||||
|
depth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void compute(BlockList* blocks) {
|
static void compute(BlockList* blocks) {
|
||||||
worklist = new Values();
|
UseCountComputer ucc;
|
||||||
blocks->blocks_do(basic_compute_use_count);
|
blocks->iterate_backward(&ucc);
|
||||||
worklist = NULL;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Values* UseCountComputer::worklist = NULL;
|
|
||||||
int UseCountComputer::depth = 0;
|
|
||||||
|
|
||||||
// helper macro for short definition of trace-output inside code
|
// helper macro for short definition of trace-output inside code
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
#define TRACE_LINEAR_SCAN(level, code) \
|
#define TRACE_LINEAR_SCAN(level, code) \
|
||||||
|
@ -1302,7 +1298,7 @@ void IR::verify() {
|
||||||
|
|
||||||
#endif // PRODUCT
|
#endif // PRODUCT
|
||||||
|
|
||||||
void SubstitutionResolver::substitute(Value* v) {
|
void SubstitutionResolver::visit(Value* v) {
|
||||||
Value v0 = *v;
|
Value v0 = *v;
|
||||||
if (v0) {
|
if (v0) {
|
||||||
Value vs = v0->subst();
|
Value vs = v0->subst();
|
||||||
|
@ -1313,20 +1309,22 @@ void SubstitutionResolver::substitute(Value* v) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void check_substitute(Value* v) {
|
class SubstitutionChecker: public ValueVisitor {
|
||||||
|
void visit(Value* v) {
|
||||||
Value v0 = *v;
|
Value v0 = *v;
|
||||||
if (v0) {
|
if (v0) {
|
||||||
Value vs = v0->subst();
|
Value vs = v0->subst();
|
||||||
assert(vs == v0, "missed substitution");
|
assert(vs == v0, "missed substitution");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void SubstitutionResolver::block_do(BlockBegin* block) {
|
void SubstitutionResolver::block_do(BlockBegin* block) {
|
||||||
Instruction* last = NULL;
|
Instruction* last = NULL;
|
||||||
for (Instruction* n = block; n != NULL;) {
|
for (Instruction* n = block; n != NULL;) {
|
||||||
n->values_do(substitute);
|
n->values_do(this);
|
||||||
// need to remove this instruction from the instruction stream
|
// need to remove this instruction from the instruction stream
|
||||||
if (n->subst() != n) {
|
if (n->subst() != n) {
|
||||||
assert(last != NULL, "must have last");
|
assert(last != NULL, "must have last");
|
||||||
|
@ -1338,8 +1336,9 @@ void SubstitutionResolver::block_do(BlockBegin* block) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
if (block->state()) block->state()->values_do(check_substitute);
|
SubstitutionChecker check_substitute;
|
||||||
block->block_values_do(check_substitute);
|
if (block->state()) block->state()->values_do(&check_substitute);
|
||||||
if (block->end() && block->end()->state()) block->end()->state()->values_do(check_substitute);
|
block->block_values_do(&check_substitute);
|
||||||
|
if (block->end() && block->end()->state()) block->end()->state()->values_do(&check_substitute);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -371,8 +371,8 @@ class IR: public CompilationResourceObj {
|
||||||
// instructions from the instruction list.
|
// instructions from the instruction list.
|
||||||
//
|
//
|
||||||
|
|
||||||
class SubstitutionResolver: public BlockClosure {
|
class SubstitutionResolver: public BlockClosure, ValueVisitor {
|
||||||
static void substitute(Value* v);
|
virtual void visit(Value* v);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SubstitutionResolver(IR* hir) {
|
SubstitutionResolver(IR* hir) {
|
||||||
|
|
|
@ -29,8 +29,6 @@
|
||||||
// Implementation of Instruction
|
// Implementation of Instruction
|
||||||
|
|
||||||
|
|
||||||
int Instruction::_next_id = 0;
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void Instruction::create_hi_word() {
|
void Instruction::create_hi_word() {
|
||||||
assert(type()->is_double_word() && _hi_word == NULL, "only double word has high word");
|
assert(type()->is_double_word() && _hi_word == NULL, "only double word has high word");
|
||||||
|
@ -193,22 +191,22 @@ ciType* CheckCast::exact_type() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ArithmeticOp::other_values_do(void f(Value*)) {
|
void ArithmeticOp::other_values_do(ValueVisitor* f) {
|
||||||
if (lock_stack() != NULL) lock_stack()->values_do(f);
|
if (lock_stack() != NULL) lock_stack()->values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NullCheck::other_values_do(void f(Value*)) {
|
void NullCheck::other_values_do(ValueVisitor* f) {
|
||||||
lock_stack()->values_do(f);
|
lock_stack()->values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccessArray::other_values_do(void f(Value*)) {
|
void AccessArray::other_values_do(ValueVisitor* f) {
|
||||||
if (lock_stack() != NULL) lock_stack()->values_do(f);
|
if (lock_stack() != NULL) lock_stack()->values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Implementation of AccessField
|
// Implementation of AccessField
|
||||||
|
|
||||||
void AccessField::other_values_do(void f(Value*)) {
|
void AccessField::other_values_do(ValueVisitor* f) {
|
||||||
if (state_before() != NULL) state_before()->values_do(f);
|
if (state_before() != NULL) state_before()->values_do(f);
|
||||||
if (lock_stack() != NULL) lock_stack()->values_do(f);
|
if (lock_stack() != NULL) lock_stack()->values_do(f);
|
||||||
}
|
}
|
||||||
|
@ -270,7 +268,7 @@ bool LogicOp::is_commutative() const {
|
||||||
|
|
||||||
// Implementation of CompareOp
|
// Implementation of CompareOp
|
||||||
|
|
||||||
void CompareOp::other_values_do(void f(Value*)) {
|
void CompareOp::other_values_do(ValueVisitor* f) {
|
||||||
if (state_before() != NULL) state_before()->values_do(f);
|
if (state_before() != NULL) state_before()->values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,12 +300,12 @@ IRScope* StateSplit::scope() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StateSplit::state_values_do(void f(Value*)) {
|
void StateSplit::state_values_do(ValueVisitor* f) {
|
||||||
if (state() != NULL) state()->values_do(f);
|
if (state() != NULL) state()->values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BlockBegin::state_values_do(void f(Value*)) {
|
void BlockBegin::state_values_do(ValueVisitor* f) {
|
||||||
StateSplit::state_values_do(f);
|
StateSplit::state_values_do(f);
|
||||||
|
|
||||||
if (is_set(BlockBegin::exception_entry_flag)) {
|
if (is_set(BlockBegin::exception_entry_flag)) {
|
||||||
|
@ -318,13 +316,13 @@ void BlockBegin::state_values_do(void f(Value*)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MonitorEnter::state_values_do(void f(Value*)) {
|
void MonitorEnter::state_values_do(ValueVisitor* f) {
|
||||||
StateSplit::state_values_do(f);
|
StateSplit::state_values_do(f);
|
||||||
_lock_stack_before->values_do(f);
|
_lock_stack_before->values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Intrinsic::state_values_do(void f(Value*)) {
|
void Intrinsic::state_values_do(ValueVisitor* f) {
|
||||||
StateSplit::state_values_do(f);
|
StateSplit::state_values_do(f);
|
||||||
if (lock_stack() != NULL) lock_stack()->values_do(f);
|
if (lock_stack() != NULL) lock_stack()->values_do(f);
|
||||||
}
|
}
|
||||||
|
@ -349,8 +347,9 @@ Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values*
|
||||||
|
|
||||||
assert(args != NULL, "args must exist");
|
assert(args != NULL, "args must exist");
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
values_do(assert_value);
|
AssertValues assert_value;
|
||||||
#endif // ASSERT
|
values_do(&assert_value);
|
||||||
|
#endif
|
||||||
|
|
||||||
// provide an initial guess of signature size.
|
// provide an initial guess of signature size.
|
||||||
_signature = new BasicTypeList(number_of_arguments() + (has_receiver() ? 1 : 0));
|
_signature = new BasicTypeList(number_of_arguments() + (has_receiver() ? 1 : 0));
|
||||||
|
@ -368,7 +367,7 @@ Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Invoke::state_values_do(void f(Value*)) {
|
void Invoke::state_values_do(ValueVisitor* f) {
|
||||||
StateSplit::state_values_do(f);
|
StateSplit::state_values_do(f);
|
||||||
if (state_before() != NULL) state_before()->values_do(f);
|
if (state_before() != NULL) state_before()->values_do(f);
|
||||||
if (state() != NULL) state()->values_do(f);
|
if (state() != NULL) state()->values_do(f);
|
||||||
|
@ -500,30 +499,27 @@ BlockBegin* Constant::compare(Instruction::Condition cond, Value right,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Constant::other_values_do(void f(Value*)) {
|
void Constant::other_values_do(ValueVisitor* f) {
|
||||||
if (state() != NULL) state()->values_do(f);
|
if (state() != NULL) state()->values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Implementation of NewArray
|
// Implementation of NewArray
|
||||||
|
|
||||||
void NewArray::other_values_do(void f(Value*)) {
|
void NewArray::other_values_do(ValueVisitor* f) {
|
||||||
if (state_before() != NULL) state_before()->values_do(f);
|
if (state_before() != NULL) state_before()->values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Implementation of TypeCheck
|
// Implementation of TypeCheck
|
||||||
|
|
||||||
void TypeCheck::other_values_do(void f(Value*)) {
|
void TypeCheck::other_values_do(ValueVisitor* f) {
|
||||||
if (state_before() != NULL) state_before()->values_do(f);
|
if (state_before() != NULL) state_before()->values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Implementation of BlockBegin
|
// Implementation of BlockBegin
|
||||||
|
|
||||||
int BlockBegin::_next_block_id = 0;
|
|
||||||
|
|
||||||
|
|
||||||
void BlockBegin::set_end(BlockEnd* end) {
|
void BlockBegin::set_end(BlockEnd* end) {
|
||||||
assert(end != NULL, "should not reset block end to NULL");
|
assert(end != NULL, "should not reset block end to NULL");
|
||||||
BlockEnd* old_end = _end;
|
BlockEnd* old_end = _end;
|
||||||
|
@ -738,7 +734,7 @@ void BlockBegin::iterate_postorder(BlockClosure* closure) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BlockBegin::block_values_do(void f(Value*)) {
|
void BlockBegin::block_values_do(ValueVisitor* f) {
|
||||||
for (Instruction* n = this; n != NULL; n = n->next()) n->values_do(f);
|
for (Instruction* n = this; n != NULL; n = n->next()) n->values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -930,7 +926,7 @@ void BlockList::blocks_do(void f(BlockBegin*)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BlockList::values_do(void f(Value*)) {
|
void BlockList::values_do(ValueVisitor* f) {
|
||||||
for (int i = length() - 1; i >= 0; i--) at(i)->block_values_do(f);
|
for (int i = length() - 1; i >= 0; i--) at(i)->block_values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -973,7 +969,7 @@ void BlockEnd::substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BlockEnd::other_values_do(void f(Value*)) {
|
void BlockEnd::other_values_do(ValueVisitor* f) {
|
||||||
if (state_before() != NULL) state_before()->values_do(f);
|
if (state_before() != NULL) state_before()->values_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1012,6 +1008,6 @@ int Phi::operand_count() const {
|
||||||
|
|
||||||
// Implementation of Throw
|
// Implementation of Throw
|
||||||
|
|
||||||
void Throw::state_values_do(void f(Value*)) {
|
void Throw::state_values_do(ValueVisitor* f) {
|
||||||
BlockEnd::state_values_do(f);
|
BlockEnd::state_values_do(f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,13 @@ class BlockClosure: public CompilationResourceObj {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// A simple closure class for visiting the values of an Instruction
|
||||||
|
class ValueVisitor: public StackObj {
|
||||||
|
public:
|
||||||
|
virtual void visit(Value* v) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Some array and list classes
|
// Some array and list classes
|
||||||
define_array(BlockBeginArray, BlockBegin*)
|
define_array(BlockBeginArray, BlockBegin*)
|
||||||
define_stack(_BlockList, BlockBeginArray)
|
define_stack(_BlockList, BlockBeginArray)
|
||||||
|
@ -129,7 +136,7 @@ class BlockList: public _BlockList {
|
||||||
void iterate_forward(BlockClosure* closure);
|
void iterate_forward(BlockClosure* closure);
|
||||||
void iterate_backward(BlockClosure* closure);
|
void iterate_backward(BlockClosure* closure);
|
||||||
void blocks_do(void f(BlockBegin*));
|
void blocks_do(void f(BlockBegin*));
|
||||||
void values_do(void f(Value*));
|
void values_do(ValueVisitor* f);
|
||||||
void print(bool cfg_only = false, bool live_only = false) PRODUCT_RETURN;
|
void print(bool cfg_only = false, bool live_only = false) PRODUCT_RETURN;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -264,8 +271,6 @@ class InstructionVisitor: public StackObj {
|
||||||
|
|
||||||
class Instruction: public CompilationResourceObj {
|
class Instruction: public CompilationResourceObj {
|
||||||
private:
|
private:
|
||||||
static int _next_id; // the node counter
|
|
||||||
|
|
||||||
int _id; // the unique instruction id
|
int _id; // the unique instruction id
|
||||||
int _bci; // the instruction bci
|
int _bci; // the instruction bci
|
||||||
int _use_count; // the number of instructions refering to this value (w/o prev/next); only roots can have use count = 0 or > 1
|
int _use_count; // the number of instructions refering to this value (w/o prev/next); only roots can have use count = 0 or > 1
|
||||||
|
@ -283,6 +288,7 @@ class Instruction: public CompilationResourceObj {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
friend class UseCountComputer;
|
friend class UseCountComputer;
|
||||||
|
friend class BlockBegin;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void set_bci(int bci) { assert(bci == SynchronizationEntryBCI || bci >= 0, "illegal bci"); _bci = bci; }
|
void set_bci(int bci) { assert(bci == SynchronizationEntryBCI || bci >= 0, "illegal bci"); _bci = bci; }
|
||||||
|
@ -292,6 +298,13 @@ class Instruction: public CompilationResourceObj {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void* operator new(size_t size) {
|
||||||
|
Compilation* c = Compilation::current();
|
||||||
|
void* res = c->arena()->Amalloc(size);
|
||||||
|
((Instruction*)res)->_id = c->get_next_id();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
enum InstructionFlag {
|
enum InstructionFlag {
|
||||||
NeedsNullCheckFlag = 0,
|
NeedsNullCheckFlag = 0,
|
||||||
CanTrapFlag,
|
CanTrapFlag,
|
||||||
|
@ -338,13 +351,13 @@ class Instruction: public CompilationResourceObj {
|
||||||
static Condition negate(Condition cond);
|
static Condition negate(Condition cond);
|
||||||
|
|
||||||
// initialization
|
// initialization
|
||||||
static void initialize() { _next_id = 0; }
|
static int number_of_instructions() {
|
||||||
static int number_of_instructions() { return _next_id; }
|
return Compilation::current()->number_of_instructions();
|
||||||
|
}
|
||||||
|
|
||||||
// creation
|
// creation
|
||||||
Instruction(ValueType* type, bool type_is_constant = false, bool create_hi = true)
|
Instruction(ValueType* type, bool type_is_constant = false, bool create_hi = true)
|
||||||
: _id(_next_id++)
|
: _bci(-99)
|
||||||
, _bci(-99)
|
|
||||||
, _use_count(0)
|
, _use_count(0)
|
||||||
, _pin_state(0)
|
, _pin_state(0)
|
||||||
, _type(type)
|
, _type(type)
|
||||||
|
@ -479,10 +492,10 @@ class Instruction: public CompilationResourceObj {
|
||||||
|
|
||||||
virtual bool can_trap() const { return false; }
|
virtual bool can_trap() const { return false; }
|
||||||
|
|
||||||
virtual void input_values_do(void f(Value*)) = 0;
|
virtual void input_values_do(ValueVisitor* f) = 0;
|
||||||
virtual void state_values_do(void f(Value*)) { /* usually no state - override on demand */ }
|
virtual void state_values_do(ValueVisitor* f) { /* usually no state - override on demand */ }
|
||||||
virtual void other_values_do(void f(Value*)) { /* usually no other - override on demand */ }
|
virtual void other_values_do(ValueVisitor* f) { /* usually no other - override on demand */ }
|
||||||
void values_do(void f(Value*)) { input_values_do(f); state_values_do(f); other_values_do(f); }
|
void values_do(ValueVisitor* f) { input_values_do(f); state_values_do(f); other_values_do(f); }
|
||||||
|
|
||||||
virtual ciType* exact_type() const { return NULL; }
|
virtual ciType* exact_type() const { return NULL; }
|
||||||
virtual ciType* declared_type() const { return NULL; }
|
virtual ciType* declared_type() const { return NULL; }
|
||||||
|
@ -517,9 +530,12 @@ class Instruction: public CompilationResourceObj {
|
||||||
|
|
||||||
// Debugging support
|
// Debugging support
|
||||||
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
static void assert_value(Value* x) { assert((*x) != NULL, "value must exist"); }
|
class AssertValues: public ValueVisitor {
|
||||||
#define ASSERT_VALUES values_do(assert_value);
|
void visit(Value* x) { assert((*x) != NULL, "value must exist"); }
|
||||||
|
};
|
||||||
|
#define ASSERT_VALUES { AssertValues assert_value; values_do(&assert_value); }
|
||||||
#else
|
#else
|
||||||
#define ASSERT_VALUES
|
#define ASSERT_VALUES
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
@ -555,7 +571,7 @@ LEAF(HiWord, Instruction)
|
||||||
void make_illegal() { set_type(illegalType); }
|
void make_illegal() { set_type(illegalType); }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { ShouldNotReachHere(); }
|
virtual void input_values_do(ValueVisitor* f) { ShouldNotReachHere(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -615,7 +631,7 @@ LEAF(Phi, Instruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) {
|
virtual void input_values_do(ValueVisitor* f) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -635,7 +651,7 @@ LEAF(Local, Instruction)
|
||||||
int java_index() const { return _java_index; }
|
int java_index() const { return _java_index; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { /* no values */ }
|
virtual void input_values_do(ValueVisitor* f) { /* no values */ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -663,8 +679,8 @@ LEAF(Constant, Instruction)
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual bool can_trap() const { return state() != NULL; }
|
virtual bool can_trap() const { return state() != NULL; }
|
||||||
virtual void input_values_do(void f(Value*)) { /* no values */ }
|
virtual void input_values_do(ValueVisitor* f) { /* no values */ }
|
||||||
virtual void other_values_do(void f(Value*));
|
virtual void other_values_do(ValueVisitor* f);
|
||||||
|
|
||||||
virtual intx hash() const;
|
virtual intx hash() const;
|
||||||
virtual bool is_equal(Value v) const;
|
virtual bool is_equal(Value v) const;
|
||||||
|
@ -734,8 +750,8 @@ BASE(AccessField, Instruction)
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual bool can_trap() const { return needs_null_check() || needs_patching(); }
|
virtual bool can_trap() const { return needs_null_check() || needs_patching(); }
|
||||||
virtual void input_values_do(void f(Value*)) { f(&_obj); }
|
virtual void input_values_do(ValueVisitor* f) { f->visit(&_obj); }
|
||||||
virtual void other_values_do(void f(Value*));
|
virtual void other_values_do(ValueVisitor* f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -776,7 +792,7 @@ LEAF(StoreField, AccessField)
|
||||||
bool needs_write_barrier() const { return check_flag(NeedsWriteBarrierFlag); }
|
bool needs_write_barrier() const { return check_flag(NeedsWriteBarrierFlag); }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { AccessField::input_values_do(f); f(&_value); }
|
virtual void input_values_do(ValueVisitor* f) { AccessField::input_values_do(f); f->visit(&_value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -804,8 +820,8 @@ BASE(AccessArray, Instruction)
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual bool can_trap() const { return needs_null_check(); }
|
virtual bool can_trap() const { return needs_null_check(); }
|
||||||
virtual void input_values_do(void f(Value*)) { f(&_array); }
|
virtual void input_values_do(ValueVisitor* f) { f->visit(&_array); }
|
||||||
virtual void other_values_do(void f(Value*));
|
virtual void other_values_do(ValueVisitor* f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -857,7 +873,7 @@ BASE(AccessIndexed, AccessArray)
|
||||||
bool compute_needs_range_check();
|
bool compute_needs_range_check();
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { AccessArray::input_values_do(f); f(&_index); if (_length != NULL) f(&_length); }
|
virtual void input_values_do(ValueVisitor* f) { AccessArray::input_values_do(f); f->visit(&_index); if (_length != NULL) f->visit(&_length); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -909,7 +925,7 @@ LEAF(StoreIndexed, AccessIndexed)
|
||||||
bool needs_store_check() const { return check_flag(NeedsStoreCheckFlag); }
|
bool needs_store_check() const { return check_flag(NeedsStoreCheckFlag); }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { AccessIndexed::input_values_do(f); f(&_value); }
|
virtual void input_values_do(ValueVisitor* f) { AccessIndexed::input_values_do(f); f->visit(&_value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -927,7 +943,7 @@ LEAF(NegateOp, Instruction)
|
||||||
Value x() const { return _x; }
|
Value x() const { return _x; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { f(&_x); }
|
virtual void input_values_do(ValueVisitor* f) { f->visit(&_x); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -956,7 +972,7 @@ BASE(Op2, Instruction)
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual bool is_commutative() const { return false; }
|
virtual bool is_commutative() const { return false; }
|
||||||
virtual void input_values_do(void f(Value*)) { f(&_x); f(&_y); }
|
virtual void input_values_do(ValueVisitor* f) { f->visit(&_x); f->visit(&_y); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -982,7 +998,7 @@ LEAF(ArithmeticOp, Op2)
|
||||||
// generic
|
// generic
|
||||||
virtual bool is_commutative() const;
|
virtual bool is_commutative() const;
|
||||||
virtual bool can_trap() const;
|
virtual bool can_trap() const;
|
||||||
virtual void other_values_do(void f(Value*));
|
virtual void other_values_do(ValueVisitor* f);
|
||||||
HASHING3(Op2, true, op(), x()->subst(), y()->subst())
|
HASHING3(Op2, true, op(), x()->subst(), y()->subst())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1023,7 +1039,7 @@ LEAF(CompareOp, Op2)
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
HASHING3(Op2, true, op(), x()->subst(), y()->subst())
|
HASHING3(Op2, true, op(), x()->subst(), y()->subst())
|
||||||
virtual void other_values_do(void f(Value*));
|
virtual void other_values_do(ValueVisitor* f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1051,7 +1067,7 @@ LEAF(IfOp, Op2)
|
||||||
Value fval() const { return _fval; }
|
Value fval() const { return _fval; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { Op2::input_values_do(f); f(&_tval); f(&_fval); }
|
virtual void input_values_do(ValueVisitor* f) { Op2::input_values_do(f); f->visit(&_tval); f->visit(&_fval); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1071,7 +1087,7 @@ LEAF(Convert, Instruction)
|
||||||
Value value() const { return _value; }
|
Value value() const { return _value; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { f(&_value); }
|
virtual void input_values_do(ValueVisitor* f) { f->visit(&_value); }
|
||||||
HASHING2(Convert, true, op(), value()->subst())
|
HASHING2(Convert, true, op(), value()->subst())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1100,8 +1116,8 @@ LEAF(NullCheck, Instruction)
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual bool can_trap() const { return check_flag(CanTrapFlag); /* null-check elimination sets to false */ }
|
virtual bool can_trap() const { return check_flag(CanTrapFlag); /* null-check elimination sets to false */ }
|
||||||
virtual void input_values_do(void f(Value*)) { f(&_obj); }
|
virtual void input_values_do(ValueVisitor* f) { f->visit(&_obj); }
|
||||||
virtual void other_values_do(void f(Value*));
|
virtual void other_values_do(ValueVisitor* f);
|
||||||
HASHING1(NullCheck, true, obj()->subst())
|
HASHING1(NullCheck, true, obj()->subst())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1127,8 +1143,8 @@ BASE(StateSplit, Instruction)
|
||||||
void set_state(ValueStack* state) { _state = state; }
|
void set_state(ValueStack* state) { _state = state; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { /* no values */ }
|
virtual void input_values_do(ValueVisitor* f) { /* no values */ }
|
||||||
virtual void state_values_do(void f(Value*));
|
virtual void state_values_do(ValueVisitor* f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1169,12 +1185,12 @@ LEAF(Invoke, StateSplit)
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual bool can_trap() const { return true; }
|
virtual bool can_trap() const { return true; }
|
||||||
virtual void input_values_do(void f(Value*)) {
|
virtual void input_values_do(ValueVisitor* f) {
|
||||||
StateSplit::input_values_do(f);
|
StateSplit::input_values_do(f);
|
||||||
if (has_receiver()) f(&_recv);
|
if (has_receiver()) f->visit(&_recv);
|
||||||
for (int i = 0; i < _args->length(); i++) f(_args->adr_at(i));
|
for (int i = 0; i < _args->length(); i++) f->visit(_args->adr_at(i));
|
||||||
}
|
}
|
||||||
virtual void state_values_do(void f(Value*));
|
virtual void state_values_do(ValueVisitor *f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1212,8 +1228,8 @@ BASE(NewArray, StateSplit)
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual bool can_trap() const { return true; }
|
virtual bool can_trap() const { return true; }
|
||||||
virtual void input_values_do(void f(Value*)) { StateSplit::input_values_do(f); f(&_length); }
|
virtual void input_values_do(ValueVisitor* f) { StateSplit::input_values_do(f); f->visit(&_length); }
|
||||||
virtual void other_values_do(void f(Value*));
|
virtual void other_values_do(ValueVisitor* f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1262,7 +1278,7 @@ LEAF(NewMultiArray, NewArray)
|
||||||
int rank() const { return dims()->length(); }
|
int rank() const { return dims()->length(); }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) {
|
virtual void input_values_do(ValueVisitor* f) {
|
||||||
// NOTE: we do not call NewArray::input_values_do since "length"
|
// NOTE: we do not call NewArray::input_values_do since "length"
|
||||||
// is meaningless for a multi-dimensional array; passing the
|
// is meaningless for a multi-dimensional array; passing the
|
||||||
// zeroth element down to NewArray as its length is a bad idea
|
// zeroth element down to NewArray as its length is a bad idea
|
||||||
|
@ -1270,7 +1286,7 @@ LEAF(NewMultiArray, NewArray)
|
||||||
// get updated, and the value must not be traversed twice. Was bug
|
// get updated, and the value must not be traversed twice. Was bug
|
||||||
// - kbr 4/10/2001
|
// - kbr 4/10/2001
|
||||||
StateSplit::input_values_do(f);
|
StateSplit::input_values_do(f);
|
||||||
for (int i = 0; i < _dims->length(); i++) f(_dims->adr_at(i));
|
for (int i = 0; i < _dims->length(); i++) f->visit(_dims->adr_at(i));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1300,8 +1316,8 @@ BASE(TypeCheck, StateSplit)
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual bool can_trap() const { return true; }
|
virtual bool can_trap() const { return true; }
|
||||||
virtual void input_values_do(void f(Value*)) { StateSplit::input_values_do(f); f(&_obj); }
|
virtual void input_values_do(ValueVisitor* f) { StateSplit::input_values_do(f); f->visit(&_obj); }
|
||||||
virtual void other_values_do(void f(Value*));
|
virtual void other_values_do(ValueVisitor* f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1366,7 +1382,7 @@ BASE(AccessMonitor, StateSplit)
|
||||||
int monitor_no() const { return _monitor_no; }
|
int monitor_no() const { return _monitor_no; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { StateSplit::input_values_do(f); f(&_obj); }
|
virtual void input_values_do(ValueVisitor* f) { StateSplit::input_values_do(f); f->visit(&_obj); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1385,7 +1401,7 @@ LEAF(MonitorEnter, AccessMonitor)
|
||||||
|
|
||||||
// accessors
|
// accessors
|
||||||
ValueStack* lock_stack_before() const { return _lock_stack_before; }
|
ValueStack* lock_stack_before() const { return _lock_stack_before; }
|
||||||
virtual void state_values_do(void f(Value*));
|
virtual void state_values_do(ValueVisitor* f);
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual bool can_trap() const { return true; }
|
virtual bool can_trap() const { return true; }
|
||||||
|
@ -1454,11 +1470,11 @@ LEAF(Intrinsic, StateSplit)
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual bool can_trap() const { return check_flag(CanTrapFlag); }
|
virtual bool can_trap() const { return check_flag(CanTrapFlag); }
|
||||||
virtual void input_values_do(void f(Value*)) {
|
virtual void input_values_do(ValueVisitor* f) {
|
||||||
StateSplit::input_values_do(f);
|
StateSplit::input_values_do(f);
|
||||||
for (int i = 0; i < _args->length(); i++) f(_args->adr_at(i));
|
for (int i = 0; i < _args->length(); i++) f->visit(_args->adr_at(i));
|
||||||
}
|
}
|
||||||
virtual void state_values_do(void f(Value*));
|
virtual void state_values_do(ValueVisitor* f);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1467,8 +1483,6 @@ class LIR_List;
|
||||||
|
|
||||||
LEAF(BlockBegin, StateSplit)
|
LEAF(BlockBegin, StateSplit)
|
||||||
private:
|
private:
|
||||||
static int _next_block_id; // the block counter
|
|
||||||
|
|
||||||
int _block_id; // the unique block id
|
int _block_id; // the unique block id
|
||||||
int _depth_first_number; // number of this block in a depth-first ordering
|
int _depth_first_number; // number of this block in a depth-first ordering
|
||||||
int _linear_scan_number; // number of this block in linear-scan ordering
|
int _linear_scan_number; // number of this block in linear-scan ordering
|
||||||
|
@ -1510,14 +1524,22 @@ LEAF(BlockBegin, StateSplit)
|
||||||
friend class SuxAndWeightAdjuster;
|
friend class SuxAndWeightAdjuster;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void* operator new(size_t size) {
|
||||||
|
Compilation* c = Compilation::current();
|
||||||
|
void* res = c->arena()->Amalloc(size);
|
||||||
|
((BlockBegin*)res)->_id = c->get_next_id();
|
||||||
|
((BlockBegin*)res)->_block_id = c->get_next_block_id();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// initialization/counting
|
// initialization/counting
|
||||||
static void initialize() { _next_block_id = 0; }
|
static int number_of_blocks() {
|
||||||
static int number_of_blocks() { return _next_block_id; }
|
return Compilation::current()->number_of_blocks();
|
||||||
|
}
|
||||||
|
|
||||||
// creation
|
// creation
|
||||||
BlockBegin(int bci)
|
BlockBegin(int bci)
|
||||||
: StateSplit(illegalType)
|
: StateSplit(illegalType)
|
||||||
, _block_id(_next_block_id++)
|
|
||||||
, _depth_first_number(-1)
|
, _depth_first_number(-1)
|
||||||
, _linear_scan_number(-1)
|
, _linear_scan_number(-1)
|
||||||
, _loop_depth(0)
|
, _loop_depth(0)
|
||||||
|
@ -1592,7 +1614,7 @@ LEAF(BlockBegin, StateSplit)
|
||||||
void init_stores_to_locals(int locals_count) { _stores_to_locals = BitMap(locals_count); _stores_to_locals.clear(); }
|
void init_stores_to_locals(int locals_count) { _stores_to_locals = BitMap(locals_count); _stores_to_locals.clear(); }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void state_values_do(void f(Value*));
|
virtual void state_values_do(ValueVisitor* f);
|
||||||
|
|
||||||
// successors and predecessors
|
// successors and predecessors
|
||||||
int number_of_sux() const;
|
int number_of_sux() const;
|
||||||
|
@ -1646,7 +1668,7 @@ LEAF(BlockBegin, StateSplit)
|
||||||
void iterate_preorder (BlockClosure* closure);
|
void iterate_preorder (BlockClosure* closure);
|
||||||
void iterate_postorder (BlockClosure* closure);
|
void iterate_postorder (BlockClosure* closure);
|
||||||
|
|
||||||
void block_values_do(void f(Value*));
|
void block_values_do(ValueVisitor* f);
|
||||||
|
|
||||||
// loops
|
// loops
|
||||||
void set_loop_index(int ix) { _loop_index = ix; }
|
void set_loop_index(int ix) { _loop_index = ix; }
|
||||||
|
@ -1698,7 +1720,7 @@ BASE(BlockEnd, StateSplit)
|
||||||
void set_begin(BlockBegin* begin);
|
void set_begin(BlockBegin* begin);
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void other_values_do(void f(Value*));
|
virtual void other_values_do(ValueVisitor* f);
|
||||||
|
|
||||||
// successors
|
// successors
|
||||||
int number_of_sux() const { return _sux != NULL ? _sux->length() : 0; }
|
int number_of_sux() const { return _sux != NULL ? _sux->length() : 0; }
|
||||||
|
@ -1787,7 +1809,7 @@ LEAF(If, BlockEnd)
|
||||||
void set_profiled_bci(int bci) { _profiled_bci = bci; }
|
void set_profiled_bci(int bci) { _profiled_bci = bci; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { BlockEnd::input_values_do(f); f(&_x); f(&_y); }
|
virtual void input_values_do(ValueVisitor* f) { BlockEnd::input_values_do(f); f->visit(&_x); f->visit(&_y); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1841,7 +1863,7 @@ LEAF(IfInstanceOf, BlockEnd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { BlockEnd::input_values_do(f); f(&_obj); }
|
virtual void input_values_do(ValueVisitor* f) { BlockEnd::input_values_do(f); f->visit(&_obj); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1863,7 +1885,7 @@ BASE(Switch, BlockEnd)
|
||||||
int length() const { return number_of_sux() - 1; }
|
int length() const { return number_of_sux() - 1; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { BlockEnd::input_values_do(f); f(&_tag); }
|
virtual void input_values_do(ValueVisitor* f) { BlockEnd::input_values_do(f); f->visit(&_tag); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1916,9 +1938,9 @@ LEAF(Return, BlockEnd)
|
||||||
bool has_result() const { return result() != NULL; }
|
bool has_result() const { return result() != NULL; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) {
|
virtual void input_values_do(ValueVisitor* f) {
|
||||||
BlockEnd::input_values_do(f);
|
BlockEnd::input_values_do(f);
|
||||||
if (has_result()) f(&_result);
|
if (has_result()) f->visit(&_result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1938,8 +1960,8 @@ LEAF(Throw, BlockEnd)
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual bool can_trap() const { return true; }
|
virtual bool can_trap() const { return true; }
|
||||||
virtual void input_values_do(void f(Value*)) { BlockEnd::input_values_do(f); f(&_exception); }
|
virtual void input_values_do(ValueVisitor* f) { BlockEnd::input_values_do(f); f->visit(&_exception); }
|
||||||
virtual void state_values_do(void f(Value*));
|
virtual void state_values_do(ValueVisitor* f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1971,7 +1993,7 @@ LEAF(OsrEntry, Instruction)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { }
|
virtual void input_values_do(ValueVisitor* f) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1984,7 +2006,7 @@ LEAF(ExceptionObject, Instruction)
|
||||||
}
|
}
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { }
|
virtual void input_values_do(ValueVisitor* f) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2008,7 +2030,7 @@ LEAF(RoundFP, Instruction)
|
||||||
Value input() const { return _input; }
|
Value input() const { return _input; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { f(&_input); }
|
virtual void input_values_do(ValueVisitor* f) { f->visit(&_input); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2033,8 +2055,8 @@ BASE(UnsafeOp, Instruction)
|
||||||
BasicType basic_type() { return _basic_type; }
|
BasicType basic_type() { return _basic_type; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { }
|
virtual void input_values_do(ValueVisitor* f) { }
|
||||||
virtual void other_values_do(void f(Value*)) { }
|
virtual void other_values_do(ValueVisitor* f) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2078,9 +2100,9 @@ BASE(UnsafeRawOp, UnsafeOp)
|
||||||
void set_log2_scale(int log2_scale) { _log2_scale = log2_scale; }
|
void set_log2_scale(int log2_scale) { _log2_scale = log2_scale; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { UnsafeOp::input_values_do(f);
|
virtual void input_values_do(ValueVisitor* f) { UnsafeOp::input_values_do(f);
|
||||||
f(&_base);
|
f->visit(&_base);
|
||||||
if (has_index()) f(&_index); }
|
if (has_index()) f->visit(&_index); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2128,8 +2150,8 @@ LEAF(UnsafePutRaw, UnsafeRawOp)
|
||||||
Value value() { return _value; }
|
Value value() { return _value; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { UnsafeRawOp::input_values_do(f);
|
virtual void input_values_do(ValueVisitor* f) { UnsafeRawOp::input_values_do(f);
|
||||||
f(&_value); }
|
f->visit(&_value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2149,9 +2171,9 @@ BASE(UnsafeObjectOp, UnsafeOp)
|
||||||
Value offset() { return _offset; }
|
Value offset() { return _offset; }
|
||||||
bool is_volatile() { return _is_volatile; }
|
bool is_volatile() { return _is_volatile; }
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { UnsafeOp::input_values_do(f);
|
virtual void input_values_do(ValueVisitor* f) { UnsafeOp::input_values_do(f);
|
||||||
f(&_object);
|
f->visit(&_object);
|
||||||
f(&_offset); }
|
f->visit(&_offset); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2180,8 +2202,8 @@ LEAF(UnsafePutObject, UnsafeObjectOp)
|
||||||
Value value() { return _value; }
|
Value value() { return _value; }
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
virtual void input_values_do(void f(Value*)) { UnsafeObjectOp::input_values_do(f);
|
virtual void input_values_do(ValueVisitor* f) { UnsafeObjectOp::input_values_do(f);
|
||||||
f(&_value); }
|
f->visit(&_value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2238,7 +2260,7 @@ LEAF(ProfileCall, Instruction)
|
||||||
Value recv() { return _recv; }
|
Value recv() { return _recv; }
|
||||||
ciKlass* known_holder() { return _known_holder; }
|
ciKlass* known_holder() { return _known_holder; }
|
||||||
|
|
||||||
virtual void input_values_do(void f(Value*)) { if (_recv != NULL) f(&_recv); }
|
virtual void input_values_do(ValueVisitor* f) { if (_recv != NULL) f->visit(&_recv); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2266,7 +2288,7 @@ LEAF(ProfileCounter, Instruction)
|
||||||
int offset() { return _offset; }
|
int offset() { return _offset; }
|
||||||
int increment() { return _increment; }
|
int increment() { return _increment; }
|
||||||
|
|
||||||
virtual void input_values_do(void f(Value*)) { f(&_mdo); }
|
virtual void input_values_do(ValueVisitor* f) { f->visit(&_mdo); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -304,7 +304,7 @@ void LIRGenerator::block_do_prolog(BlockBegin* block) {
|
||||||
__ branch_destination(block->label());
|
__ branch_destination(block->label());
|
||||||
|
|
||||||
if (LIRTraceExecution &&
|
if (LIRTraceExecution &&
|
||||||
Compilation::current_compilation()->hir()->start()->block_id() != block->block_id() &&
|
Compilation::current()->hir()->start()->block_id() != block->block_id() &&
|
||||||
!block->is_set(BlockBegin::exception_entry_flag)) {
|
!block->is_set(BlockBegin::exception_entry_flag)) {
|
||||||
assert(block->lir()->instructions_list()->length() == 1, "should come right after br_dst");
|
assert(block->lir()->instructions_list()->length() == 1, "should come right after br_dst");
|
||||||
trace_block_entry(block);
|
trace_block_entry(block);
|
||||||
|
|
|
@ -84,10 +84,6 @@ LinearScan::LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map)
|
||||||
, _fpu_stack_allocator(NULL)
|
, _fpu_stack_allocator(NULL)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// note: to use more than on instance of LinearScan at a time this function call has to
|
|
||||||
// be moved somewhere outside of this constructor:
|
|
||||||
Interval::initialize();
|
|
||||||
|
|
||||||
assert(this->ir() != NULL, "check if valid");
|
assert(this->ir() != NULL, "check if valid");
|
||||||
assert(this->compilation() != NULL, "check if valid");
|
assert(this->compilation() != NULL, "check if valid");
|
||||||
assert(this->gen() != NULL, "check if valid");
|
assert(this->gen() != NULL, "check if valid");
|
||||||
|
@ -3929,8 +3925,8 @@ Range::Range(int from, int to, Range* next) :
|
||||||
|
|
||||||
// initialize sentinel
|
// initialize sentinel
|
||||||
Range* Range::_end = NULL;
|
Range* Range::_end = NULL;
|
||||||
void Range::initialize() {
|
void Range::initialize(Arena* arena) {
|
||||||
_end = new Range(max_jint, max_jint, NULL);
|
_end = new (arena) Range(max_jint, max_jint, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Range::intersects_at(Range* r2) const {
|
int Range::intersects_at(Range* r2) const {
|
||||||
|
@ -3976,9 +3972,9 @@ void Range::print(outputStream* out) const {
|
||||||
|
|
||||||
// initialize sentinel
|
// initialize sentinel
|
||||||
Interval* Interval::_end = NULL;
|
Interval* Interval::_end = NULL;
|
||||||
void Interval::initialize() {
|
void Interval::initialize(Arena* arena) {
|
||||||
Range::initialize();
|
Range::initialize(arena);
|
||||||
_end = new Interval(-1);
|
_end = new (arena) Interval(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Interval::Interval(int reg_num) :
|
Interval::Interval(int reg_num) :
|
||||||
|
|
|
@ -462,7 +462,7 @@ class Range : public CompilationResourceObj {
|
||||||
public:
|
public:
|
||||||
Range(int from, int to, Range* next);
|
Range(int from, int to, Range* next);
|
||||||
|
|
||||||
static void initialize();
|
static void initialize(Arena* arena);
|
||||||
static Range* end() { return _end; }
|
static Range* end() { return _end; }
|
||||||
|
|
||||||
int from() const { return _from; }
|
int from() const { return _from; }
|
||||||
|
@ -529,7 +529,7 @@ class Interval : public CompilationResourceObj {
|
||||||
public:
|
public:
|
||||||
Interval(int reg_num);
|
Interval(int reg_num);
|
||||||
|
|
||||||
static void initialize();
|
static void initialize(Arena* arena);
|
||||||
static Interval* end() { return _end; }
|
static Interval* end() { return _end; }
|
||||||
|
|
||||||
// accessors
|
// accessors
|
||||||
|
|
|
@ -437,11 +437,8 @@ public:
|
||||||
// Because of a static contained within (for the purpose of iteration
|
// Because of a static contained within (for the purpose of iteration
|
||||||
// over instructions), it is only valid to have one of these active at
|
// over instructions), it is only valid to have one of these active at
|
||||||
// a time
|
// a time
|
||||||
class NullCheckEliminator {
|
class NullCheckEliminator: public ValueVisitor {
|
||||||
private:
|
private:
|
||||||
static NullCheckEliminator* _static_nce;
|
|
||||||
static void do_value(Value* vp);
|
|
||||||
|
|
||||||
Optimizer* _opt;
|
Optimizer* _opt;
|
||||||
|
|
||||||
ValueSet* _visitable_instructions; // Visit each instruction only once per basic block
|
ValueSet* _visitable_instructions; // Visit each instruction only once per basic block
|
||||||
|
@ -504,6 +501,8 @@ class NullCheckEliminator {
|
||||||
// Process a graph
|
// Process a graph
|
||||||
void iterate(BlockBegin* root);
|
void iterate(BlockBegin* root);
|
||||||
|
|
||||||
|
void visit(Value* f);
|
||||||
|
|
||||||
// In some situations (like NullCheck(x); getfield(x)) the debug
|
// In some situations (like NullCheck(x); getfield(x)) the debug
|
||||||
// information from the explicit NullCheck can be used to populate
|
// information from the explicit NullCheck can be used to populate
|
||||||
// the getfield, even if the two instructions are in different
|
// the getfield, even if the two instructions are in different
|
||||||
|
@ -602,14 +601,11 @@ void NullCheckVisitor::do_ProfileCall (ProfileCall* x) { nce()->clear_las
|
||||||
void NullCheckVisitor::do_ProfileCounter (ProfileCounter* x) {}
|
void NullCheckVisitor::do_ProfileCounter (ProfileCounter* x) {}
|
||||||
|
|
||||||
|
|
||||||
NullCheckEliminator* NullCheckEliminator::_static_nce = NULL;
|
void NullCheckEliminator::visit(Value* p) {
|
||||||
|
|
||||||
|
|
||||||
void NullCheckEliminator::do_value(Value* p) {
|
|
||||||
assert(*p != NULL, "should not find NULL instructions");
|
assert(*p != NULL, "should not find NULL instructions");
|
||||||
if (_static_nce->visitable(*p)) {
|
if (visitable(*p)) {
|
||||||
_static_nce->mark_visited(*p);
|
mark_visited(*p);
|
||||||
(*p)->visit(&_static_nce->_visitor);
|
(*p)->visit(&_visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,7 +633,6 @@ void NullCheckEliminator::iterate_all() {
|
||||||
|
|
||||||
|
|
||||||
void NullCheckEliminator::iterate_one(BlockBegin* block) {
|
void NullCheckEliminator::iterate_one(BlockBegin* block) {
|
||||||
_static_nce = this;
|
|
||||||
clear_visitable_state();
|
clear_visitable_state();
|
||||||
// clear out an old explicit null checks
|
// clear out an old explicit null checks
|
||||||
set_last_explicit_null_check(NULL);
|
set_last_explicit_null_check(NULL);
|
||||||
|
@ -712,7 +707,7 @@ void NullCheckEliminator::iterate_one(BlockBegin* block) {
|
||||||
mark_visitable(instr);
|
mark_visitable(instr);
|
||||||
if (instr->is_root() || instr->can_trap() || (instr->as_NullCheck() != NULL)) {
|
if (instr->is_root() || instr->can_trap() || (instr->as_NullCheck() != NULL)) {
|
||||||
mark_visited(instr);
|
mark_visited(instr);
|
||||||
instr->input_values_do(&NullCheckEliminator::do_value);
|
instr->input_values_do(this);
|
||||||
instr->visit(&_visitor);
|
instr->visit(&_visitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,6 @@ void StubAssembler::set_num_rt_args(int args) {
|
||||||
|
|
||||||
// Implementation of Runtime1
|
// Implementation of Runtime1
|
||||||
|
|
||||||
bool Runtime1::_is_initialized = false;
|
|
||||||
CodeBlob* Runtime1::_blobs[Runtime1::number_of_ids];
|
CodeBlob* Runtime1::_blobs[Runtime1::number_of_ids];
|
||||||
const char *Runtime1::_blob_names[] = {
|
const char *Runtime1::_blob_names[] = {
|
||||||
RUNTIME1_STUBS(STUB_NAME, LAST_STUB_NAME)
|
RUNTIME1_STUBS(STUB_NAME, LAST_STUB_NAME)
|
||||||
|
@ -89,8 +88,6 @@ int Runtime1::_throw_array_store_exception_count = 0;
|
||||||
int Runtime1::_throw_count = 0;
|
int Runtime1::_throw_count = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BufferBlob* Runtime1::_buffer_blob = NULL;
|
|
||||||
|
|
||||||
// Simple helper to see if the caller of a runtime stub which
|
// Simple helper to see if the caller of a runtime stub which
|
||||||
// entered the VM has been deoptimized
|
// entered the VM has been deoptimized
|
||||||
|
|
||||||
|
@ -117,43 +114,14 @@ static void deopt_caller() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BufferBlob* Runtime1::get_buffer_blob() {
|
void Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubID id) {
|
||||||
// Allocate code buffer space only once
|
|
||||||
BufferBlob* blob = _buffer_blob;
|
|
||||||
if (blob == NULL) {
|
|
||||||
// setup CodeBuffer. Preallocate a BufferBlob of size
|
|
||||||
// NMethodSizeLimit plus some extra space for constants.
|
|
||||||
int code_buffer_size = desired_max_code_buffer_size() + desired_max_constant_size();
|
|
||||||
blob = BufferBlob::create("Compiler1 temporary CodeBuffer",
|
|
||||||
code_buffer_size);
|
|
||||||
guarantee(blob != NULL, "must create initial code buffer");
|
|
||||||
_buffer_blob = blob;
|
|
||||||
}
|
|
||||||
return _buffer_blob;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Runtime1::setup_code_buffer(CodeBuffer* code, int call_stub_estimate) {
|
|
||||||
// Preinitialize the consts section to some large size:
|
|
||||||
int locs_buffer_size = 20 * (relocInfo::length_limit + sizeof(relocInfo));
|
|
||||||
char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size);
|
|
||||||
code->insts()->initialize_shared_locs((relocInfo*)locs_buffer,
|
|
||||||
locs_buffer_size / sizeof(relocInfo));
|
|
||||||
code->initialize_consts_size(desired_max_constant_size());
|
|
||||||
// Call stubs + deopt/exception handler
|
|
||||||
code->initialize_stubs_size((call_stub_estimate * LIR_Assembler::call_stub_size) +
|
|
||||||
LIR_Assembler::exception_handler_size +
|
|
||||||
LIR_Assembler::deopt_handler_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Runtime1::generate_blob_for(StubID id) {
|
|
||||||
assert(0 <= id && id < number_of_ids, "illegal stub id");
|
assert(0 <= id && id < number_of_ids, "illegal stub id");
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
// create code buffer for code storage
|
// create code buffer for code storage
|
||||||
CodeBuffer code(get_buffer_blob()->instructions_begin(),
|
CodeBuffer code(buffer_blob->instructions_begin(),
|
||||||
get_buffer_blob()->instructions_size());
|
buffer_blob->instructions_size());
|
||||||
|
|
||||||
setup_code_buffer(&code, 0);
|
Compilation::setup_code_buffer(&code, 0);
|
||||||
|
|
||||||
// create assembler for code generation
|
// create assembler for code generation
|
||||||
StubAssembler* sasm = new StubAssembler(&code, name_for(id), id);
|
StubAssembler* sasm = new StubAssembler(&code, name_for(id), id);
|
||||||
|
@ -204,16 +172,11 @@ void Runtime1::generate_blob_for(StubID id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Runtime1::initialize() {
|
void Runtime1::initialize(BufferBlob* blob) {
|
||||||
// Warning: If we have more than one compilation running in parallel, we
|
|
||||||
// need a lock here with the current setup (lazy initialization).
|
|
||||||
if (!is_initialized()) {
|
|
||||||
_is_initialized = true;
|
|
||||||
|
|
||||||
// platform-dependent initialization
|
// platform-dependent initialization
|
||||||
initialize_pd();
|
initialize_pd();
|
||||||
// generate stubs
|
// generate stubs
|
||||||
for (int id = 0; id < number_of_ids; id++) generate_blob_for((StubID)id);
|
for (int id = 0; id < number_of_ids; id++) generate_blob_for(blob, (StubID)id);
|
||||||
// printing
|
// printing
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (PrintSimpleStubs) {
|
if (PrintSimpleStubs) {
|
||||||
|
@ -227,12 +190,10 @@ void Runtime1::initialize() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CodeBlob* Runtime1::blob_for(StubID id) {
|
CodeBlob* Runtime1::blob_for(StubID id) {
|
||||||
assert(0 <= id && id < number_of_ids, "illegal stub id");
|
assert(0 <= id && id < number_of_ids, "illegal stub id");
|
||||||
if (!is_initialized()) initialize();
|
|
||||||
return _blobs[id];
|
return _blobs[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,18 +70,6 @@ class StubAssembler;
|
||||||
class Runtime1: public AllStatic {
|
class Runtime1: public AllStatic {
|
||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class ArrayCopyStub;
|
friend class ArrayCopyStub;
|
||||||
private:
|
|
||||||
static int desired_max_code_buffer_size() {
|
|
||||||
return (int) NMethodSizeLimit; // default 256K or 512K
|
|
||||||
}
|
|
||||||
static int desired_max_constant_size() {
|
|
||||||
return (int) NMethodSizeLimit / 10; // about 25K
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: This buffers is allocated once at startup since allocation
|
|
||||||
// for each compilation seems to be too expensive (at least on Intel
|
|
||||||
// win32).
|
|
||||||
static BufferBlob* _buffer_blob;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum StubID {
|
enum StubID {
|
||||||
|
@ -115,12 +103,11 @@ class Runtime1: public AllStatic {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool _is_initialized;
|
|
||||||
static CodeBlob* _blobs[number_of_ids];
|
static CodeBlob* _blobs[number_of_ids];
|
||||||
static const char* _blob_names[];
|
static const char* _blob_names[];
|
||||||
|
|
||||||
// stub generation
|
// stub generation
|
||||||
static void generate_blob_for(StubID id);
|
static void generate_blob_for(BufferBlob* blob, StubID id);
|
||||||
static OopMapSet* generate_code_for(StubID id, StubAssembler* masm);
|
static OopMapSet* generate_code_for(StubID id, StubAssembler* masm);
|
||||||
static OopMapSet* generate_exception_throw(StubAssembler* sasm, address target, bool has_argument);
|
static OopMapSet* generate_exception_throw(StubAssembler* sasm, address target, bool has_argument);
|
||||||
static void generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_maps, OopMap* oop_map, bool ignore_fpu_registers = false);
|
static void generate_handle_exception(StubAssembler *sasm, OopMapSet* oop_maps, OopMap* oop_map, bool ignore_fpu_registers = false);
|
||||||
|
@ -162,12 +149,8 @@ class Runtime1: public AllStatic {
|
||||||
static void patch_code(JavaThread* thread, StubID stub_id);
|
static void patch_code(JavaThread* thread, StubID stub_id);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static BufferBlob* get_buffer_blob();
|
|
||||||
static void setup_code_buffer(CodeBuffer* cb, int call_stub_estimate);
|
|
||||||
|
|
||||||
// initialization
|
// initialization
|
||||||
static bool is_initialized() { return _is_initialized; }
|
static void initialize(BufferBlob* blob);
|
||||||
static void initialize();
|
|
||||||
static void initialize_pd();
|
static void initialize_pd();
|
||||||
|
|
||||||
// stubs
|
// stubs
|
||||||
|
|
|
@ -119,14 +119,14 @@ void ValueStack::pin_stack_for_linear_scan() {
|
||||||
|
|
||||||
|
|
||||||
// apply function to all values of a list; factored out from values_do(f)
|
// apply function to all values of a list; factored out from values_do(f)
|
||||||
void ValueStack::apply(Values list, void f(Value*)) {
|
void ValueStack::apply(Values list, ValueVisitor* f) {
|
||||||
for (int i = 0; i < list.length(); i++) {
|
for (int i = 0; i < list.length(); i++) {
|
||||||
Value* va = list.adr_at(i);
|
Value* va = list.adr_at(i);
|
||||||
Value v0 = *va;
|
Value v0 = *va;
|
||||||
if (v0 != NULL) {
|
if (v0 != NULL) {
|
||||||
if (!v0->type()->is_illegal()) {
|
if (!v0->type()->is_illegal()) {
|
||||||
assert(v0->as_HiWord() == NULL, "should never see HiWord during traversal");
|
assert(v0->as_HiWord() == NULL, "should never see HiWord during traversal");
|
||||||
f(va);
|
f->visit(va);
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
Value v1 = *va;
|
Value v1 = *va;
|
||||||
if (v0 != v1) {
|
if (v0 != v1) {
|
||||||
|
@ -143,7 +143,7 @@ void ValueStack::apply(Values list, void f(Value*)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ValueStack::values_do(void f(Value*)) {
|
void ValueStack::values_do(ValueVisitor* f) {
|
||||||
apply(_stack, f);
|
apply(_stack, f);
|
||||||
apply(_locks, f);
|
apply(_locks, f);
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ class ValueStack: public CompilationResourceObj {
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper routine
|
// helper routine
|
||||||
static void apply(Values list, void f(Value*));
|
static void apply(Values list, ValueVisitor* f);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// creation
|
// creation
|
||||||
|
@ -143,7 +143,7 @@ class ValueStack: public CompilationResourceObj {
|
||||||
void pin_stack_for_linear_scan();
|
void pin_stack_for_linear_scan();
|
||||||
|
|
||||||
// iteration
|
// iteration
|
||||||
void values_do(void f(Value*));
|
void values_do(ValueVisitor* f);
|
||||||
|
|
||||||
// untyped manipulation (for dup_x1, etc.)
|
// untyped manipulation (for dup_x1, etc.)
|
||||||
void clear_stack() { _stack.clear(); }
|
void clear_stack() { _stack.clear(); }
|
||||||
|
|
|
@ -46,27 +46,26 @@ IntConstant* intOne = NULL;
|
||||||
ObjectConstant* objectNull = NULL;
|
ObjectConstant* objectNull = NULL;
|
||||||
|
|
||||||
|
|
||||||
void ValueType::initialize() {
|
void ValueType::initialize(Arena* arena) {
|
||||||
// Note: Must initialize all types for each compilation
|
// Note: Must initialize all types for each compilation
|
||||||
// as they are allocated within a ResourceMark!
|
// as they are allocated within a ResourceMark!
|
||||||
|
|
||||||
// types
|
// types
|
||||||
voidType = new VoidType();
|
voidType = new (arena) VoidType();
|
||||||
intType = new IntType();
|
intType = new (arena) IntType();
|
||||||
longType = new LongType();
|
longType = new (arena) LongType();
|
||||||
floatType = new FloatType();
|
floatType = new (arena) FloatType();
|
||||||
doubleType = new DoubleType();
|
doubleType = new (arena) DoubleType();
|
||||||
objectType = new ObjectType();
|
objectType = new (arena) ObjectType();
|
||||||
arrayType = new ArrayType();
|
arrayType = new (arena) ArrayType();
|
||||||
instanceType = new InstanceType();
|
instanceType = new (arena) InstanceType();
|
||||||
classType = new ClassType();
|
classType = new (arena) ClassType();
|
||||||
addressType = new AddressType();
|
addressType = new (arena) AddressType();
|
||||||
illegalType = new IllegalType();
|
illegalType = new (arena) IllegalType();
|
||||||
|
|
||||||
// constants
|
intZero = new (arena) IntConstant(0);
|
||||||
intZero = new IntConstant(0);
|
intOne = new (arena) IntConstant(1);
|
||||||
intOne = new IntConstant(1);
|
objectNull = new (arena) ObjectConstant(ciNullObject::make());
|
||||||
objectNull = new ObjectConstant(ciNullObject::make());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ class ValueType: public CompilationResourceObj {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// initialization
|
// initialization
|
||||||
static void initialize();
|
static void initialize(Arena* arena);
|
||||||
|
|
||||||
// accessors
|
// accessors
|
||||||
virtual ValueType* base() const = 0; // the 'canonical' type (e.g., intType for an IntConstant)
|
virtual ValueType* base() const = 0; // the 'canonical' type (e.g., intType for an IntConstant)
|
||||||
|
|
|
@ -71,8 +71,8 @@ c1_Compilation.cpp c1_LinearScan.hpp
|
||||||
c1_Compilation.cpp c1_MacroAssembler.hpp
|
c1_Compilation.cpp c1_MacroAssembler.hpp
|
||||||
c1_Compilation.cpp c1_ValueMap.hpp
|
c1_Compilation.cpp c1_ValueMap.hpp
|
||||||
c1_Compilation.cpp c1_ValueStack.hpp
|
c1_Compilation.cpp c1_ValueStack.hpp
|
||||||
c1_Compilation.cpp ciEnv.hpp
|
|
||||||
c1_Compilation.cpp debugInfoRec.hpp
|
c1_Compilation.cpp debugInfoRec.hpp
|
||||||
|
c1_Compilation.hpp ciEnv.hpp
|
||||||
c1_Compilation.hpp exceptionHandlerTable.hpp
|
c1_Compilation.hpp exceptionHandlerTable.hpp
|
||||||
c1_Compilation.hpp resourceArea.hpp
|
c1_Compilation.hpp resourceArea.hpp
|
||||||
|
|
||||||
|
@ -82,6 +82,8 @@ c1_Compiler.cpp arguments.hpp
|
||||||
c1_Compiler.cpp c1_Compilation.hpp
|
c1_Compiler.cpp c1_Compilation.hpp
|
||||||
c1_Compiler.cpp c1_Compiler.hpp
|
c1_Compiler.cpp c1_Compiler.hpp
|
||||||
c1_Compiler.cpp c1_FrameMap.hpp
|
c1_Compiler.cpp c1_FrameMap.hpp
|
||||||
|
c1_Compiler.cpp c1_GraphBuilder.hpp
|
||||||
|
c1_Compiler.cpp c1_LinearScan.hpp
|
||||||
c1_Compiler.cpp c1_MacroAssembler.hpp
|
c1_Compiler.cpp c1_MacroAssembler.hpp
|
||||||
c1_Compiler.cpp c1_Runtime1.hpp
|
c1_Compiler.cpp c1_Runtime1.hpp
|
||||||
c1_Compiler.cpp c1_ValueType.hpp
|
c1_Compiler.cpp c1_ValueType.hpp
|
||||||
|
|
|
@ -82,9 +82,6 @@ Mutex* EvacFailureStack_lock = NULL;
|
||||||
Mutex* DerivedPointerTableGC_lock = NULL;
|
Mutex* DerivedPointerTableGC_lock = NULL;
|
||||||
Mutex* Compile_lock = NULL;
|
Mutex* Compile_lock = NULL;
|
||||||
Monitor* MethodCompileQueue_lock = NULL;
|
Monitor* MethodCompileQueue_lock = NULL;
|
||||||
#ifdef TIERED
|
|
||||||
Monitor* C1_lock = NULL;
|
|
||||||
#endif // TIERED
|
|
||||||
Monitor* CompileThread_lock = NULL;
|
Monitor* CompileThread_lock = NULL;
|
||||||
Mutex* CompileTaskAlloc_lock = NULL;
|
Mutex* CompileTaskAlloc_lock = NULL;
|
||||||
Mutex* CompileStatistics_lock = NULL;
|
Mutex* CompileStatistics_lock = NULL;
|
||||||
|
@ -255,11 +252,6 @@ void mutex_init() {
|
||||||
def(Debug3_lock , Mutex , nonleaf+4, true );
|
def(Debug3_lock , Mutex , nonleaf+4, true );
|
||||||
def(ProfileVM_lock , Monitor, nonleaf+4, false); // used for profiling of the VMThread
|
def(ProfileVM_lock , Monitor, nonleaf+4, false); // used for profiling of the VMThread
|
||||||
def(CompileThread_lock , Monitor, nonleaf+5, false );
|
def(CompileThread_lock , Monitor, nonleaf+5, false );
|
||||||
#ifdef TIERED
|
|
||||||
def(C1_lock , Monitor, nonleaf+5, false );
|
|
||||||
#endif // TIERED
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GCMutexLocker::GCMutexLocker(Monitor * mutex) {
|
GCMutexLocker::GCMutexLocker(Monitor * mutex) {
|
||||||
|
|
|
@ -84,9 +84,6 @@ extern Mutex* ParGCRareEvent_lock; // Synchronizes various (rare)
|
||||||
extern Mutex* EvacFailureStack_lock; // guards the evac failure scan stack
|
extern Mutex* EvacFailureStack_lock; // guards the evac failure scan stack
|
||||||
extern Mutex* Compile_lock; // a lock held when Compilation is updating code (used to block CodeCache traversal, CHA updates, etc)
|
extern Mutex* Compile_lock; // a lock held when Compilation is updating code (used to block CodeCache traversal, CHA updates, etc)
|
||||||
extern Monitor* MethodCompileQueue_lock; // a lock held when method compilations are enqueued, dequeued
|
extern Monitor* MethodCompileQueue_lock; // a lock held when method compilations are enqueued, dequeued
|
||||||
#ifdef TIERED
|
|
||||||
extern Monitor* C1_lock; // a lock to ensure on single c1 compile is ever active
|
|
||||||
#endif // TIERED
|
|
||||||
extern Monitor* CompileThread_lock; // a lock held by compile threads during compilation system initialization
|
extern Monitor* CompileThread_lock; // a lock held by compile threads during compilation system initialization
|
||||||
extern Mutex* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
|
extern Mutex* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
|
||||||
extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics
|
extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics
|
||||||
|
|
|
@ -2797,6 +2797,7 @@ CompilerThread::CompilerThread(CompileQueue* queue, CompilerCounters* counters)
|
||||||
_task = NULL;
|
_task = NULL;
|
||||||
_queue = queue;
|
_queue = queue;
|
||||||
_counters = counters;
|
_counters = counters;
|
||||||
|
_buffer_blob = NULL;
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
_ideal_graph_printer = NULL;
|
_ideal_graph_printer = NULL;
|
||||||
|
|
|
@ -1576,6 +1576,7 @@ class CompilerThread : public JavaThread {
|
||||||
CompileLog* _log;
|
CompileLog* _log;
|
||||||
CompileTask* _task;
|
CompileTask* _task;
|
||||||
CompileQueue* _queue;
|
CompileQueue* _queue;
|
||||||
|
BufferBlob* _buffer_blob;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -1594,6 +1595,9 @@ class CompilerThread : public JavaThread {
|
||||||
ciEnv* env() { return _env; }
|
ciEnv* env() { return _env; }
|
||||||
void set_env(ciEnv* env) { _env = env; }
|
void set_env(ciEnv* env) { _env = env; }
|
||||||
|
|
||||||
|
BufferBlob* get_buffer_blob() { return _buffer_blob; }
|
||||||
|
void set_buffer_blob(BufferBlob* b) { _buffer_blob = b; };
|
||||||
|
|
||||||
// Get/set the thread's logging information
|
// Get/set the thread's logging information
|
||||||
CompileLog* log() { return _log; }
|
CompileLog* log() { return _log; }
|
||||||
void init_log(CompileLog* log) {
|
void init_log(CompileLog* log) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue