--- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -181,8 +181,8 @@
}
-void FrameMap::init () {
- if (_init_done) return;
+void FrameMap::initialize() {
+ assert(!_init_done, "once");
int i=0;
// Register usage:
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -7643,6 +7643,9 @@
// Pass register number to verify_oop_subroutine
char* b = new char[strlen(s) + 50];
sprintf(b, "verify_oop: %s: %s", reg->name(), s);
+#ifdef _LP64
+ push(rscratch1); // save r10, trashed by movptr()
+#endif
push(rax); // save rax,
push(reg); // pass register argument
ExternalAddress buffer((address) b);
@@ -7653,6 +7656,7 @@
// call indirectly to solve generation ordering problem
movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address()));
call(rax);
+ // Caller pops the arguments (oop, message) and restores rax, r10
}
@@ -7767,6 +7771,9 @@
char* b = new char[strlen(s) + 50];
sprintf(b, "verify_oop_addr: %s", s);
+#ifdef _LP64
+ push(rscratch1); // save r10, trashed by movptr()
+#endif
push(rax); // save rax,
// addr may contain rsp so we will have to adjust it based on the push
// we just did
@@ -7789,7 +7796,7 @@
// call indirectly to solve generation ordering problem
movptr(rax, ExternalAddress(StubRoutines::verify_oop_subroutine_entry_address()));
call(rax);
- // Caller pops the arguments and restores rax, from the stack
+ // Caller pops the arguments (addr, message) and restores rax, r10.
}
void MacroAssembler::verify_tlab() {
--- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -136,8 +136,8 @@
// FrameMap
//--------------------------------------------------------
-void FrameMap::init() {
- if (_init_done) return;
+void FrameMap::initialize() {
+ assert(!_init_done, "once");
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);
--- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -914,6 +914,7 @@
// * [tos + 5]: error message (char*)
// * [tos + 6]: object to verify (oop)
// * [tos + 7]: saved rax - saved by caller and bashed
+ // * [tos + 8]: saved r10 (rscratch1) - saved by caller
// * = popped on exit
address generate_verify_oop() {
StubCodeMark mark(this, "StubRoutines", "verify_oop");
@@ -934,6 +935,7 @@
// After previous pushes.
oop_to_verify = 6 * wordSize,
saved_rax = 7 * wordSize,
+ saved_r10 = 8 * wordSize,
// Before the call to MacroAssembler::debug(), see below.
return_addr = 16 * wordSize,
@@ -983,15 +985,17 @@
// return if everything seems ok
__ bind(exit);
__ movptr(rax, Address(rsp, saved_rax)); // get saved rax back
+ __ movptr(rscratch1, Address(rsp, saved_r10)); // get saved r10 back
__ pop(c_rarg3); // restore c_rarg3
__ pop(c_rarg2); // restore c_rarg2
__ pop(r12); // restore r12
__ popf(); // restore flags
- __ ret(3 * wordSize); // pop caller saved stuff
+ __ ret(4 * wordSize); // pop caller saved stuff
// handle errors
__ bind(error);
__ movptr(rax, Address(rsp, saved_rax)); // get saved rax back
+ __ movptr(rscratch1, Address(rsp, saved_r10)); // get saved r10 back
__ pop(c_rarg3); // get saved c_rarg3 back
__ pop(c_rarg2); // get saved c_rarg2 back
__ pop(r12); // get saved r12 back
@@ -1009,6 +1013,7 @@
// * [tos + 17] error message (char*)
// * [tos + 18] object to verify (oop)
// * [tos + 19] saved rax - saved by caller and bashed
+ // * [tos + 20] saved r10 (rscratch1) - saved by caller
// * = popped on exit
__ movptr(c_rarg0, Address(rsp, error_msg)); // pass address of error message
@@ -1021,7 +1026,7 @@
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, MacroAssembler::debug64)));
__ mov(rsp, r12); // restore rsp
__ popa(); // pop registers (includes r12)
- __ ret(3 * wordSize); // pop caller saved stuff
+ __ ret(4 * wordSize); // pop caller saved stuff
return start;
}
--- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -26,9 +26,11 @@
#include "incls/_c1_Canonicalizer.cpp.incl"
-static void do_print_value(Value* vp) {
- (*vp)->print_line();
-}
+class PrintValueVisitor: public ValueVisitor {
+ void visit(Value* vp) {
+ (*vp)->print_line();
+ }
+};
void Canonicalizer::set_canonical(Value x) {
assert(x != NULL, "value must exist");
@@ -37,10 +39,11 @@
// in the instructions).
if (canonical() != x) {
if (PrintCanonicalization) {
- canonical()->input_values_do(do_print_value);
+ PrintValueVisitor do_print_value;
+ canonical()->input_values_do(&do_print_value);
canonical()->print_line();
tty->print_cr("canonicalized to:");
- x->input_values_do(do_print_value);
+ x->input_values_do(&do_print_value);
x->print_line();
tty->cr();
}
@@ -202,7 +205,7 @@
// limit this optimization to current block
if (value != NULL && in_current_block(conv)) {
set_canonical(new StoreField(x->obj(), x->offset(), x->field(), value, x->is_static(),
- x->lock_stack(), x->state_before(), x->is_loaded(), x->is_initialized()));
+ x->lock_stack(), x->state_before(), x->is_loaded(), x->is_initialized()));
return;
}
}
--- a/hotspot/src/share/vm/c1/c1_Compilation.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -66,9 +66,6 @@
}
};
-Arena* Compilation::_arena = NULL;
-Compilation* Compilation::_compilation = NULL;
-
// Implementation of Compilation
@@ -238,9 +235,23 @@
}
+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() {
// emit code
- Runtime1::setup_code_buffer(code(), allocator()->num_calls());
+ setup_code_buffer(code(), allocator()->num_calls());
code()->initialize_oop_recorder(env()->oop_recorder());
_masm = new C1_MacroAssembler(code());
@@ -422,7 +433,8 @@
}
-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)
, _env(env)
, _method(method)
@@ -437,8 +449,10 @@
, _bailout_msg(NULL)
, _exception_info_list(NULL)
, _allocator(NULL)
-, _code(Runtime1::get_buffer_blob()->instructions_begin(),
- Runtime1::get_buffer_blob()->instructions_size())
+, _next_id(0)
+, _next_block_id(0)
+, _code(buffer_blob->instructions_begin(),
+ buffer_blob->instructions_size())
, _current_instruction(NULL)
#ifndef PRODUCT
, _last_instruction_printed(NULL)
@@ -446,17 +460,15 @@
{
PhaseTraceTime timeit(_t_compile);
- assert(_arena == NULL, "shouldn't only one instance of Compilation in existence at a time");
_arena = Thread::current()->resource_area();
- _compilation = this;
+ _env->set_compiler_data(this);
_exception_info_list = new ExceptionInfoList();
_implicit_exception_table.set_size(0);
compile_method();
}
Compilation::~Compilation() {
- _arena = NULL;
- _compilation = NULL;
+ _env->set_compiler_data(NULL);
}
--- a/hotspot/src/share/vm/c1/c1_Compilation.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compilation.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -54,14 +54,10 @@
class Compilation: public StackObj {
friend class CompilationResourceObj;
private:
-
- static Arena* _arena;
- static Arena* arena() { return _arena; }
-
- static Compilation* _compilation;
-
- private:
// compilation specifics
+ Arena* _arena;
+ int _next_id;
+ int _next_block_id;
AbstractCompiler* _compiler;
ciEnv* _env;
ciMethod* _method;
@@ -108,10 +104,14 @@
public:
// 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();
- static Compilation* current_compilation() { return _compilation; }
+
+ static Compilation* current() {
+ return (Compilation*) ciEnv::current()->compiler_data();
+ }
// accessors
ciEnv* env() const { return _env; }
@@ -128,6 +128,15 @@
CodeBuffer* code() { return &_code; }
C1_MacroAssembler* masm() const { return _masm; }
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
void set_has_exception_handlers(bool f) { _has_exception_handlers = f; }
@@ -158,6 +167,15 @@
bool bailed_out() const { return _bailout_msg != NULL; }
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
static void print_timers();
@@ -203,7 +221,10 @@
// Base class for objects allocated by the compiler in the compilation arena
class CompilationResourceObj ALLOCATION_SUPER_CLASS_SPEC {
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
};
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -27,9 +27,6 @@
volatile int Compiler::_runtimes = uninitialized;
-volatile bool Compiler::_compiling = false;
-
-
Compiler::Compiler() {
}
@@ -39,47 +36,62 @@
}
+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() {
if (_runtimes != initialized) {
- initialize_runtimes( Runtime1::initialize, &_runtimes);
+ initialize_runtimes( initialize_all, &_runtimes);
}
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) {
+ // 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()) {
initialize();
}
// 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
// of Compilation to occur before we release the any
// competing compiler thread
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
}
--- a/hotspot/src/share/vm/c1/c1_Compiler.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compiler.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -31,10 +31,6 @@
// Tracks whether runtime has been initialized
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:
// Creation
Compiler();
@@ -47,6 +43,7 @@
virtual bool is_c1() { return true; };
#endif // TIERED
+ BufferBlob* build_buffer_blob();
// Missing feature tests
virtual bool supports_native() { return true; }
@@ -58,6 +55,7 @@
// Initialization
virtual void initialize();
+ static void initialize_all();
// Compilation entry point for methods
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
--- a/hotspot/src/share/vm/c1/c1_FrameMap.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_FrameMap.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -153,7 +153,7 @@
FrameMap::FrameMap(ciMethod* method, int monitors, int reserved_argument_area_size) {
- if (!_init_done) init();
+ assert(_init_done, "should already be completed");
_framesize = -1;
_num_spills = -1;
--- a/hotspot/src/share/vm/c1/c1_FrameMap.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_FrameMap.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -235,7 +235,7 @@
return _caller_save_fpu_regs[i];
}
- static void init();
+ static void initialize();
};
// CallingConvention
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -2530,16 +2530,10 @@
}
-bool GraphBuilder::_is_initialized = false;
bool GraphBuilder::_can_trap [Bytecodes::number_of_java_codes];
bool GraphBuilder::_is_async[Bytecodes::number_of_java_codes];
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
// throw exceptions in compiled code - note that e.g.
// monitorexit & the return bytecodes do not throw
@@ -2855,7 +2849,6 @@
BlockList* bci2block = blm.bci2block();
BlockBegin* start_block = bci2block->at(0);
- assert(is_initialized(), "GraphBuilder must have been initialized");
push_root_scope(scope, bci2block, start_block);
// setup state for std entry
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -162,7 +162,6 @@
};
// 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 _is_async[Bytecodes::number_of_java_codes];
@@ -268,7 +267,6 @@
Instruction* append_split(StateSplit* instr);
// other helpers
- static bool is_initialized() { return _is_initialized; }
static bool is_async(Bytecodes::Code code) {
assert(0 <= code && code < Bytecodes::number_of_java_codes, "illegal bytecode");
return _is_async[code];
--- a/hotspot/src/share/vm/c1/c1_IR.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_IR.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -287,11 +287,6 @@
IR::IR(Compilation* compilation, ciMethod* method, int osr_bci) :
_locals_size(in_WordSize(-1))
, _num_loops(0) {
- // initialize data structures
- ValueType::initialize();
- Instruction::initialize();
- BlockBegin::initialize();
- GraphBuilder::initialize();
// setup IR fields
_compilation = compilation;
_top_scope = new IRScope(compilation, NULL, -1, method, osr_bci, true);
@@ -381,15 +376,15 @@
}
-class UseCountComputer: public AllStatic {
+class UseCountComputer: public ValueVisitor, BlockClosure {
private:
- static void update_use_count(Value* n) {
+ void visit(Value* n) {
// Local instructions and Phis for expression stack values at the
// start of basic blocks are not added to the instruction list
if ((*n)->bci() == -99 && (*n)->as_Local() == NULL &&
(*n)->as_Phi() == NULL) {
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
if (!(*n)->is_pinned() && !(*n)->has_uses()) {
@@ -402,31 +397,31 @@
(*n)->_use_count++;
}
- static Values* worklist;
- static int depth;
+ Values* worklist;
+ int depth;
enum {
max_recurse_depth = 20
};
- static void uses_do(Value* n) {
+ void uses_do(Value* n) {
depth++;
if (depth > max_recurse_depth) {
// don't allow the traversal to recurse too deeply
worklist->push(*n);
} else {
- (*n)->input_values_do(update_use_count);
+ (*n)->input_values_do(this);
// special handling for some instructions
if ((*n)->as_BlockEnd() != NULL) {
// note on BlockEnd:
// must 'use' the stack only if the method doesn't
// terminate, however, in those cases stack is empty
- (*n)->state_values_do(update_use_count);
+ (*n)->state_values_do(this);
}
}
depth--;
}
- static void basic_compute_use_count(BlockBegin* b) {
+ void block_do(BlockBegin* b) {
depth = 0;
// process all pinned nodes as the roots of expression trees
for (Instruction* n = b; n != NULL; n = n->next()) {
@@ -449,18 +444,19 @@
assert(depth == 0, "should have counted back down");
}
+ UseCountComputer() {
+ worklist = new Values();
+ depth = 0;
+ }
+
public:
static void compute(BlockList* blocks) {
- worklist = new Values();
- blocks->blocks_do(basic_compute_use_count);
- worklist = NULL;
+ UseCountComputer ucc;
+ blocks->iterate_backward(&ucc);
}
};
-Values* UseCountComputer::worklist = NULL;
-int UseCountComputer::depth = 0;
-
// helper macro for short definition of trace-output inside code
#ifndef PRODUCT
#define TRACE_LINEAR_SCAN(level, code) \
@@ -1302,7 +1298,7 @@
#endif // PRODUCT
-void SubstitutionResolver::substitute(Value* v) {
+void SubstitutionResolver::visit(Value* v) {
Value v0 = *v;
if (v0) {
Value vs = v0->subst();
@@ -1313,20 +1309,22 @@
}
#ifdef ASSERT
-void check_substitute(Value* v) {
- Value v0 = *v;
- if (v0) {
- Value vs = v0->subst();
- assert(vs == v0, "missed substitution");
+class SubstitutionChecker: public ValueVisitor {
+ void visit(Value* v) {
+ Value v0 = *v;
+ if (v0) {
+ Value vs = v0->subst();
+ assert(vs == v0, "missed substitution");
+ }
}
-}
+};
#endif
void SubstitutionResolver::block_do(BlockBegin* block) {
Instruction* last = NULL;
for (Instruction* n = block; n != NULL;) {
- n->values_do(substitute);
+ n->values_do(this);
// need to remove this instruction from the instruction stream
if (n->subst() != n) {
assert(last != NULL, "must have last");
@@ -1338,8 +1336,9 @@
}
#ifdef ASSERT
- if (block->state()) block->state()->values_do(check_substitute);
- block->block_values_do(check_substitute);
- if (block->end() && block->end()->state()) block->end()->state()->values_do(check_substitute);
+ SubstitutionChecker check_substitute;
+ if (block->state()) block->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
}
--- a/hotspot/src/share/vm/c1/c1_IR.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_IR.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -371,8 +371,8 @@
// instructions from the instruction list.
//
-class SubstitutionResolver: public BlockClosure {
- static void substitute(Value* v);
+class SubstitutionResolver: public BlockClosure, ValueVisitor {
+ virtual void visit(Value* v);
public:
SubstitutionResolver(IR* hir) {
--- a/hotspot/src/share/vm/c1/c1_Instruction.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Instruction.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -29,8 +29,6 @@
// Implementation of Instruction
-int Instruction::_next_id = 0;
-
#ifdef ASSERT
void Instruction::create_hi_word() {
assert(type()->is_double_word() && _hi_word == NULL, "only double word has high word");
@@ -193,22 +191,22 @@
}
-void ArithmeticOp::other_values_do(void f(Value*)) {
+void ArithmeticOp::other_values_do(ValueVisitor* 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);
}
-void AccessArray::other_values_do(void f(Value*)) {
+void AccessArray::other_values_do(ValueVisitor* f) {
if (lock_stack() != NULL) lock_stack()->values_do(f);
}
// 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 (lock_stack() != NULL) lock_stack()->values_do(f);
}
@@ -270,7 +268,7 @@
// 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);
}
@@ -302,12 +300,12 @@
}
-void StateSplit::state_values_do(void f(Value*)) {
+void StateSplit::state_values_do(ValueVisitor* 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);
if (is_set(BlockBegin::exception_entry_flag)) {
@@ -318,13 +316,13 @@
}
-void MonitorEnter::state_values_do(void f(Value*)) {
+void MonitorEnter::state_values_do(ValueVisitor* f) {
StateSplit::state_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);
if (lock_stack() != NULL) lock_stack()->values_do(f);
}
@@ -349,8 +347,9 @@
assert(args != NULL, "args must exist");
#ifdef ASSERT
- values_do(assert_value);
-#endif // ASSERT
+ AssertValues assert_value;
+ values_do(&assert_value);
+#endif
// provide an initial guess of signature size.
_signature = new BasicTypeList(number_of_arguments() + (has_receiver() ? 1 : 0));
@@ -368,7 +367,7 @@
}
-void Invoke::state_values_do(void f(Value*)) {
+void Invoke::state_values_do(ValueVisitor* f) {
StateSplit::state_values_do(f);
if (state_before() != NULL) state_before()->values_do(f);
if (state() != NULL) state()->values_do(f);
@@ -500,30 +499,27 @@
}
-void Constant::other_values_do(void f(Value*)) {
+void Constant::other_values_do(ValueVisitor* f) {
if (state() != NULL) state()->values_do(f);
}
// 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);
}
// 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);
}
// Implementation of BlockBegin
-int BlockBegin::_next_block_id = 0;
-
-
void BlockBegin::set_end(BlockEnd* end) {
assert(end != NULL, "should not reset block end to NULL");
BlockEnd* old_end = _end;
@@ -738,7 +734,7 @@
}
-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);
}
@@ -930,7 +926,7 @@
}
-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);
}
@@ -973,7 +969,7 @@
}
-void BlockEnd::other_values_do(void f(Value*)) {
+void BlockEnd::other_values_do(ValueVisitor* f) {
if (state_before() != NULL) state_before()->values_do(f);
}
@@ -1012,6 +1008,6 @@
// Implementation of Throw
-void Throw::state_values_do(void f(Value*)) {
+void Throw::state_values_do(ValueVisitor* f) {
BlockEnd::state_values_do(f);
}
--- a/hotspot/src/share/vm/c1/c1_Instruction.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -116,6 +116,13 @@
};
+// 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
define_array(BlockBeginArray, BlockBegin*)
define_stack(_BlockList, BlockBeginArray)
@@ -129,7 +136,7 @@
void iterate_forward(BlockClosure* closure);
void iterate_backward(BlockClosure* closure);
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;
};
@@ -264,8 +271,6 @@
class Instruction: public CompilationResourceObj {
private:
- static int _next_id; // the node counter
-
int _id; // the unique instruction id
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
@@ -283,6 +288,7 @@
#endif
friend class UseCountComputer;
+ friend class BlockBegin;
protected:
void set_bci(int bci) { assert(bci == SynchronizationEntryBCI || bci >= 0, "illegal bci"); _bci = bci; }
@@ -292,6 +298,13 @@
}
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 {
NeedsNullCheckFlag = 0,
CanTrapFlag,
@@ -338,13 +351,13 @@
static Condition negate(Condition cond);
// initialization
- static void initialize() { _next_id = 0; }
- static int number_of_instructions() { return _next_id; }
+ static int number_of_instructions() {
+ return Compilation::current()->number_of_instructions();
+ }
// creation
Instruction(ValueType* type, bool type_is_constant = false, bool create_hi = true)
- : _id(_next_id++)
- , _bci(-99)
+ : _bci(-99)
, _use_count(0)
, _pin_state(0)
, _type(type)
@@ -479,10 +492,10 @@
virtual bool can_trap() const { return false; }
- virtual void input_values_do(void f(Value*)) = 0;
- virtual void state_values_do(void f(Value*)) { /* usually no state - override on demand */ }
- virtual void other_values_do(void f(Value*)) { /* usually no other - override on demand */ }
- void values_do(void f(Value*)) { input_values_do(f); state_values_do(f); other_values_do(f); }
+ virtual void input_values_do(ValueVisitor* f) = 0;
+ virtual void state_values_do(ValueVisitor* f) { /* usually no state - override on demand */ }
+ virtual void other_values_do(ValueVisitor* f) { /* usually no other - override on demand */ }
+ 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* declared_type() const { return NULL; }
@@ -517,9 +530,12 @@
// Debugging support
+
#ifdef ASSERT
- static void assert_value(Value* x) { assert((*x) != NULL, "value must exist"); }
- #define ASSERT_VALUES values_do(assert_value);
+class AssertValues: public ValueVisitor {
+ void visit(Value* x) { assert((*x) != NULL, "value must exist"); }
+};
+ #define ASSERT_VALUES { AssertValues assert_value; values_do(&assert_value); }
#else
#define ASSERT_VALUES
#endif // ASSERT
@@ -555,7 +571,7 @@
void make_illegal() { set_type(illegalType); }
// generic
- virtual void input_values_do(void f(Value*)) { ShouldNotReachHere(); }
+ virtual void input_values_do(ValueVisitor* f) { ShouldNotReachHere(); }
};
@@ -615,7 +631,7 @@
}
// generic
- virtual void input_values_do(void f(Value*)) {
+ virtual void input_values_do(ValueVisitor* f) {
}
};
@@ -635,7 +651,7 @@
int java_index() const { return _java_index; }
// generic
- virtual void input_values_do(void f(Value*)) { /* no values */ }
+ virtual void input_values_do(ValueVisitor* f) { /* no values */ }
};
@@ -663,8 +679,8 @@
// generic
virtual bool can_trap() const { return state() != NULL; }
- virtual void input_values_do(void f(Value*)) { /* no values */ }
- virtual void other_values_do(void f(Value*));
+ virtual void input_values_do(ValueVisitor* f) { /* no values */ }
+ virtual void other_values_do(ValueVisitor* f);
virtual intx hash() const;
virtual bool is_equal(Value v) const;
@@ -734,8 +750,8 @@
// generic
virtual bool can_trap() const { return needs_null_check() || needs_patching(); }
- virtual void input_values_do(void f(Value*)) { f(&_obj); }
- virtual void other_values_do(void f(Value*));
+ virtual void input_values_do(ValueVisitor* f) { f->visit(&_obj); }
+ virtual void other_values_do(ValueVisitor* f);
};
@@ -776,7 +792,7 @@
bool needs_write_barrier() const { return check_flag(NeedsWriteBarrierFlag); }
// 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 @@
// generic
virtual bool can_trap() const { return needs_null_check(); }
- virtual void input_values_do(void f(Value*)) { f(&_array); }
- virtual void other_values_do(void f(Value*));
+ virtual void input_values_do(ValueVisitor* f) { f->visit(&_array); }
+ virtual void other_values_do(ValueVisitor* f);
};
@@ -857,7 +873,7 @@
bool compute_needs_range_check();
// 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 @@
bool needs_store_check() const { return check_flag(NeedsStoreCheckFlag); }
// 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 @@
Value x() const { return _x; }
// 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 @@
// generic
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 @@
// generic
virtual bool is_commutative() 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())
};
@@ -1023,7 +1039,7 @@
// generic
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 @@
Value fval() const { return _fval; }
// 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 @@
Value value() const { return _value; }
// 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())
};
@@ -1100,8 +1116,8 @@
// generic
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 other_values_do(void f(Value*));
+ virtual void input_values_do(ValueVisitor* f) { f->visit(&_obj); }
+ virtual void other_values_do(ValueVisitor* f);
HASHING1(NullCheck, true, obj()->subst())
};
@@ -1127,8 +1143,8 @@
void set_state(ValueStack* state) { _state = state; }
// generic
- virtual void input_values_do(void f(Value*)) { /* no values */ }
- virtual void state_values_do(void f(Value*));
+ virtual void input_values_do(ValueVisitor* f) { /* no values */ }
+ virtual void state_values_do(ValueVisitor* f);
};
@@ -1169,12 +1185,12 @@
// generic
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);
- if (has_receiver()) f(&_recv);
- for (int i = 0; i < _args->length(); i++) f(_args->adr_at(i));
+ if (has_receiver()) f->visit(&_recv);
+ 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 @@
// generic
virtual bool can_trap() const { return true; }
- virtual void input_values_do(void f(Value*)) { StateSplit::input_values_do(f); f(&_length); }
- virtual void other_values_do(void f(Value*));
+ virtual void input_values_do(ValueVisitor* f) { StateSplit::input_values_do(f); f->visit(&_length); }
+ virtual void other_values_do(ValueVisitor* f);
};
@@ -1262,7 +1278,7 @@
int rank() const { return dims()->length(); }
// 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"
// is meaningless for a multi-dimensional array; passing the
// zeroth element down to NewArray as its length is a bad idea
@@ -1270,7 +1286,7 @@
// get updated, and the value must not be traversed twice. Was bug
// - kbr 4/10/2001
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 @@
// generic
virtual bool can_trap() const { return true; }
- virtual void input_values_do(void f(Value*)) { StateSplit::input_values_do(f); f(&_obj); }
- virtual void other_values_do(void f(Value*));
+ virtual void input_values_do(ValueVisitor* f) { StateSplit::input_values_do(f); f->visit(&_obj); }
+ virtual void other_values_do(ValueVisitor* f);
};
@@ -1366,7 +1382,7 @@
int monitor_no() const { return _monitor_no; }
// 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 @@
// accessors
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
virtual bool can_trap() const { return true; }
@@ -1454,11 +1470,11 @@
// generic
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);
- 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 @@
LEAF(BlockBegin, StateSplit)
private:
- static int _next_block_id; // the block counter
-
int _block_id; // the unique block id
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
@@ -1510,14 +1524,22 @@
friend class SuxAndWeightAdjuster;
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
- static void initialize() { _next_block_id = 0; }
- static int number_of_blocks() { return _next_block_id; }
+ static int number_of_blocks() {
+ return Compilation::current()->number_of_blocks();
+ }
// creation
BlockBegin(int bci)
: StateSplit(illegalType)
- , _block_id(_next_block_id++)
, _depth_first_number(-1)
, _linear_scan_number(-1)
, _loop_depth(0)
@@ -1592,7 +1614,7 @@
void init_stores_to_locals(int locals_count) { _stores_to_locals = BitMap(locals_count); _stores_to_locals.clear(); }
// generic
- virtual void state_values_do(void f(Value*));
+ virtual void state_values_do(ValueVisitor* f);
// successors and predecessors
int number_of_sux() const;
@@ -1646,7 +1668,7 @@
void iterate_preorder (BlockClosure* closure);
void iterate_postorder (BlockClosure* closure);
- void block_values_do(void f(Value*));
+ void block_values_do(ValueVisitor* f);
// loops
void set_loop_index(int ix) { _loop_index = ix; }
@@ -1698,7 +1720,7 @@
void set_begin(BlockBegin* begin);
// generic
- virtual void other_values_do(void f(Value*));
+ virtual void other_values_do(ValueVisitor* f);
// successors
int number_of_sux() const { return _sux != NULL ? _sux->length() : 0; }
@@ -1787,7 +1809,7 @@
void set_profiled_bci(int bci) { _profiled_bci = bci; }
// 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 @@
}
// 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 @@
int length() const { return number_of_sux() - 1; }
// 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 @@
bool has_result() const { return result() != NULL; }
// generic
- virtual void input_values_do(void f(Value*)) {
+ virtual void input_values_do(ValueVisitor* f) {
BlockEnd::input_values_do(f);
- if (has_result()) f(&_result);
+ if (has_result()) f->visit(&_result);
}
};
@@ -1938,8 +1960,8 @@
// generic
virtual bool can_trap() const { return true; }
- virtual void input_values_do(void f(Value*)) { BlockEnd::input_values_do(f); f(&_exception); }
- virtual void state_values_do(void f(Value*));
+ virtual void input_values_do(ValueVisitor* f) { BlockEnd::input_values_do(f); f->visit(&_exception); }
+ virtual void state_values_do(ValueVisitor* f);
};
@@ -1971,7 +1993,7 @@
#endif
// generic
- virtual void input_values_do(void f(Value*)) { }
+ virtual void input_values_do(ValueVisitor* f) { }
};
@@ -1984,7 +2006,7 @@
}
// generic
- virtual void input_values_do(void f(Value*)) { }
+ virtual void input_values_do(ValueVisitor* f) { }
};
@@ -2008,7 +2030,7 @@
Value input() const { return _input; }
// 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 @@
BasicType basic_type() { return _basic_type; }
// generic
- virtual void input_values_do(void f(Value*)) { }
- virtual void other_values_do(void f(Value*)) { }
+ virtual void input_values_do(ValueVisitor* f) { }
+ virtual void other_values_do(ValueVisitor* f) { }
};
@@ -2078,9 +2100,9 @@
void set_log2_scale(int log2_scale) { _log2_scale = log2_scale; }
// generic
- virtual void input_values_do(void f(Value*)) { UnsafeOp::input_values_do(f);
- f(&_base);
- if (has_index()) f(&_index); }
+ virtual void input_values_do(ValueVisitor* f) { UnsafeOp::input_values_do(f);
+ f->visit(&_base);
+ if (has_index()) f->visit(&_index); }
};
@@ -2128,8 +2150,8 @@
Value value() { return _value; }
// generic
- virtual void input_values_do(void f(Value*)) { UnsafeRawOp::input_values_do(f);
- f(&_value); }
+ virtual void input_values_do(ValueVisitor* f) { UnsafeRawOp::input_values_do(f);
+ f->visit(&_value); }
};
@@ -2149,9 +2171,9 @@
Value offset() { return _offset; }
bool is_volatile() { return _is_volatile; }
// generic
- virtual void input_values_do(void f(Value*)) { UnsafeOp::input_values_do(f);
- f(&_object);
- f(&_offset); }
+ virtual void input_values_do(ValueVisitor* f) { UnsafeOp::input_values_do(f);
+ f->visit(&_object);
+ f->visit(&_offset); }
};
@@ -2180,8 +2202,8 @@
Value value() { return _value; }
// generic
- virtual void input_values_do(void f(Value*)) { UnsafeObjectOp::input_values_do(f);
- f(&_value); }
+ virtual void input_values_do(ValueVisitor* f) { UnsafeObjectOp::input_values_do(f);
+ f->visit(&_value); }
};
@@ -2238,7 +2260,7 @@
Value recv() { return _recv; }
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 @@
int offset() { return _offset; }
int increment() { return _increment; }
- virtual void input_values_do(void f(Value*)) { f(&_mdo); }
+ virtual void input_values_do(ValueVisitor* f) { f->visit(&_mdo); }
};
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -304,7 +304,7 @@
__ branch_destination(block->label());
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)) {
assert(block->lir()->instructions_list()->length() == 1, "should come right after br_dst");
trace_block_entry(block);
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -84,10 +84,6 @@
, _fpu_stack_allocator(NULL)
#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->compilation() != NULL, "check if valid");
assert(this->gen() != NULL, "check if valid");
@@ -3929,8 +3925,8 @@
// initialize sentinel
Range* Range::_end = NULL;
-void Range::initialize() {
- _end = new Range(max_jint, max_jint, NULL);
+void Range::initialize(Arena* arena) {
+ _end = new (arena) Range(max_jint, max_jint, NULL);
}
int Range::intersects_at(Range* r2) const {
@@ -3976,9 +3972,9 @@
// initialize sentinel
Interval* Interval::_end = NULL;
-void Interval::initialize() {
- Range::initialize();
- _end = new Interval(-1);
+void Interval::initialize(Arena* arena) {
+ Range::initialize(arena);
+ _end = new (arena) Interval(-1);
}
Interval::Interval(int reg_num) :
--- a/hotspot/src/share/vm/c1/c1_LinearScan.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -462,7 +462,7 @@
public:
Range(int from, int to, Range* next);
- static void initialize();
+ static void initialize(Arena* arena);
static Range* end() { return _end; }
int from() const { return _from; }
@@ -529,7 +529,7 @@
public:
Interval(int reg_num);
- static void initialize();
+ static void initialize(Arena* arena);
static Interval* end() { return _end; }
// accessors
--- a/hotspot/src/share/vm/c1/c1_Optimizer.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Optimizer.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -437,11 +437,8 @@
// Because of a static contained within (for the purpose of iteration
// over instructions), it is only valid to have one of these active at
// a time
-class NullCheckEliminator {
+class NullCheckEliminator: public ValueVisitor {
private:
- static NullCheckEliminator* _static_nce;
- static void do_value(Value* vp);
-
Optimizer* _opt;
ValueSet* _visitable_instructions; // Visit each instruction only once per basic block
@@ -504,6 +501,8 @@
// Process a graph
void iterate(BlockBegin* root);
+ void visit(Value* f);
+
// In some situations (like NullCheck(x); getfield(x)) the debug
// information from the explicit NullCheck can be used to populate
// the getfield, even if the two instructions are in different
@@ -602,14 +601,11 @@
void NullCheckVisitor::do_ProfileCounter (ProfileCounter* x) {}
-NullCheckEliminator* NullCheckEliminator::_static_nce = NULL;
-
-
-void NullCheckEliminator::do_value(Value* p) {
+void NullCheckEliminator::visit(Value* p) {
assert(*p != NULL, "should not find NULL instructions");
- if (_static_nce->visitable(*p)) {
- _static_nce->mark_visited(*p);
- (*p)->visit(&_static_nce->_visitor);
+ if (visitable(*p)) {
+ mark_visited(*p);
+ (*p)->visit(&_visitor);
}
}
@@ -637,7 +633,6 @@
void NullCheckEliminator::iterate_one(BlockBegin* block) {
- _static_nce = this;
clear_visitable_state();
// clear out an old explicit null checks
set_last_explicit_null_check(NULL);
@@ -712,7 +707,7 @@
mark_visitable(instr);
if (instr->is_root() || instr->can_trap() || (instr->as_NullCheck() != NULL)) {
mark_visited(instr);
- instr->input_values_do(&NullCheckEliminator::do_value);
+ instr->input_values_do(this);
instr->visit(&_visitor);
}
}
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -60,7 +60,6 @@
// Implementation of Runtime1
-bool Runtime1::_is_initialized = false;
CodeBlob* Runtime1::_blobs[Runtime1::number_of_ids];
const char *Runtime1::_blob_names[] = {
RUNTIME1_STUBS(STUB_NAME, LAST_STUB_NAME)
@@ -89,8 +88,6 @@
int Runtime1::_throw_count = 0;
#endif
-BufferBlob* Runtime1::_buffer_blob = NULL;
-
// Simple helper to see if the caller of a runtime stub which
// entered the VM has been deoptimized
@@ -117,43 +114,14 @@
}
-BufferBlob* Runtime1::get_buffer_blob() {
- // 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) {
+void Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubID id) {
assert(0 <= id && id < number_of_ids, "illegal stub id");
ResourceMark rm;
// create code buffer for code storage
- CodeBuffer code(get_buffer_blob()->instructions_begin(),
- get_buffer_blob()->instructions_size());
+ CodeBuffer code(buffer_blob->instructions_begin(),
+ buffer_blob->instructions_size());
- setup_code_buffer(&code, 0);
+ Compilation::setup_code_buffer(&code, 0);
// create assembler for code generation
StubAssembler* sasm = new StubAssembler(&code, name_for(id), id);
@@ -204,35 +172,28 @@
}
-void Runtime1::initialize() {
- // 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
- initialize_pd();
- // generate stubs
- for (int id = 0; id < number_of_ids; id++) generate_blob_for((StubID)id);
- // printing
+void Runtime1::initialize(BufferBlob* blob) {
+ // platform-dependent initialization
+ initialize_pd();
+ // generate stubs
+ for (int id = 0; id < number_of_ids; id++) generate_blob_for(blob, (StubID)id);
+ // printing
#ifndef PRODUCT
- if (PrintSimpleStubs) {
- ResourceMark rm;
- for (int id = 0; id < number_of_ids; id++) {
- _blobs[id]->print();
- if (_blobs[id]->oop_maps() != NULL) {
- _blobs[id]->oop_maps()->print();
- }
+ if (PrintSimpleStubs) {
+ ResourceMark rm;
+ for (int id = 0; id < number_of_ids; id++) {
+ _blobs[id]->print();
+ if (_blobs[id]->oop_maps() != NULL) {
+ _blobs[id]->oop_maps()->print();
}
}
+ }
#endif
- }
}
CodeBlob* Runtime1::blob_for(StubID id) {
assert(0 <= id && id < number_of_ids, "illegal stub id");
- if (!is_initialized()) initialize();
return _blobs[id];
}
--- a/hotspot/src/share/vm/c1/c1_Runtime1.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -70,18 +70,6 @@
class Runtime1: public AllStatic {
friend class VMStructs;
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:
enum StubID {
@@ -115,12 +103,11 @@
#endif
private:
- static bool _is_initialized;
static CodeBlob* _blobs[number_of_ids];
static const char* _blob_names[];
// 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_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);
@@ -162,12 +149,8 @@
static void patch_code(JavaThread* thread, StubID stub_id);
public:
- static BufferBlob* get_buffer_blob();
- static void setup_code_buffer(CodeBuffer* cb, int call_stub_estimate);
-
// initialization
- static bool is_initialized() { return _is_initialized; }
- static void initialize();
+ static void initialize(BufferBlob* blob);
static void initialize_pd();
// stubs
--- a/hotspot/src/share/vm/c1/c1_ValueStack.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_ValueStack.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -119,14 +119,14 @@
// 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++) {
Value* va = list.adr_at(i);
Value v0 = *va;
if (v0 != NULL) {
if (!v0->type()->is_illegal()) {
assert(v0->as_HiWord() == NULL, "should never see HiWord during traversal");
- f(va);
+ f->visit(va);
#ifdef ASSERT
Value v1 = *va;
if (v0 != v1) {
@@ -143,7 +143,7 @@
}
-void ValueStack::values_do(void f(Value*)) {
+void ValueStack::values_do(ValueVisitor* f) {
apply(_stack, f);
apply(_locks, f);
--- a/hotspot/src/share/vm/c1/c1_ValueStack.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_ValueStack.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -41,7 +41,7 @@
}
// helper routine
- static void apply(Values list, void f(Value*));
+ static void apply(Values list, ValueVisitor* f);
public:
// creation
@@ -143,7 +143,7 @@
void pin_stack_for_linear_scan();
// iteration
- void values_do(void f(Value*));
+ void values_do(ValueVisitor* f);
// untyped manipulation (for dup_x1, etc.)
void clear_stack() { _stack.clear(); }
--- a/hotspot/src/share/vm/c1/c1_ValueType.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_ValueType.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -46,27 +46,26 @@
ObjectConstant* objectNull = NULL;
-void ValueType::initialize() {
+void ValueType::initialize(Arena* arena) {
// Note: Must initialize all types for each compilation
// as they are allocated within a ResourceMark!
// types
- voidType = new VoidType();
- intType = new IntType();
- longType = new LongType();
- floatType = new FloatType();
- doubleType = new DoubleType();
- objectType = new ObjectType();
- arrayType = new ArrayType();
- instanceType = new InstanceType();
- classType = new ClassType();
- addressType = new AddressType();
- illegalType = new IllegalType();
+ voidType = new (arena) VoidType();
+ intType = new (arena) IntType();
+ longType = new (arena) LongType();
+ floatType = new (arena) FloatType();
+ doubleType = new (arena) DoubleType();
+ objectType = new (arena) ObjectType();
+ arrayType = new (arena) ArrayType();
+ instanceType = new (arena) InstanceType();
+ classType = new (arena) ClassType();
+ addressType = new (arena) AddressType();
+ illegalType = new (arena) IllegalType();
- // constants
- intZero = new IntConstant(0);
- intOne = new IntConstant(1);
- objectNull = new ObjectConstant(ciNullObject::make());
+ intZero = new (arena) IntConstant(0);
+ intOne = new (arena) IntConstant(1);
+ objectNull = new (arena) ObjectConstant(ciNullObject::make());
};
--- a/hotspot/src/share/vm/c1/c1_ValueType.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/c1/c1_ValueType.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -94,7 +94,7 @@
public:
// initialization
- static void initialize();
+ static void initialize(Arena* arena);
// accessors
virtual ValueType* base() const = 0; // the 'canonical' type (e.g., intType for an IntConstant)
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -25,10 +25,10 @@
#include "incls/_precompiled.incl"
#include "incls/_classFileParser.cpp.incl"
-// We generally try to create the oops directly when parsing, rather than allocating
-// temporary data structures and copying the bytes twice. A temporary area is only
-// needed when parsing utf8 entries in the constant pool and when parsing line number
-// tables.
+// We generally try to create the oops directly when parsing, rather than
+// allocating temporary data structures and copying the bytes twice. A
+// temporary area is only needed when parsing utf8 entries in the constant
+// pool and when parsing line number tables.
// We add assert in debug mode when class format is not checked.
@@ -47,6 +47,10 @@
// - also used as the max version when running in jdk6
#define JAVA_6_VERSION 50
+// Used for backward compatibility reasons:
+// - to check NameAndType_info signatures more aggressively
+#define JAVA_7_VERSION 51
+
void ClassFileParser::parse_constant_pool_entries(constantPoolHandle cp, int length, TRAPS) {
// Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
@@ -384,6 +388,20 @@
verify_legal_class_name(class_name, CHECK_(nullHandle));
break;
}
+ case JVM_CONSTANT_NameAndType: {
+ if (_need_verify && _major_version >= JAVA_7_VERSION) {
+ int sig_index = cp->signature_ref_index_at(index);
+ int name_index = cp->name_ref_index_at(index);
+ symbolHandle name(THREAD, cp->symbol_at(name_index));
+ symbolHandle sig(THREAD, cp->symbol_at(sig_index));
+ if (sig->byte_at(0) == JVM_SIGNATURE_FUNC) {
+ verify_legal_method_signature(name, sig, CHECK_(nullHandle));
+ } else {
+ verify_legal_field_signature(name, sig, CHECK_(nullHandle));
+ }
+ }
+ break;
+ }
case JVM_CONSTANT_Fieldref:
case JVM_CONSTANT_Methodref:
case JVM_CONSTANT_InterfaceMethodref: {
@@ -396,10 +414,28 @@
symbolHandle signature(THREAD, cp->symbol_at(signature_ref_index));
if (tag == JVM_CONSTANT_Fieldref) {
verify_legal_field_name(name, CHECK_(nullHandle));
- verify_legal_field_signature(name, signature, CHECK_(nullHandle));
+ if (_need_verify && _major_version >= JAVA_7_VERSION) {
+ // Signature is verified above, when iterating NameAndType_info.
+ // Need only to be sure it's the right type.
+ if (signature->byte_at(0) == JVM_SIGNATURE_FUNC) {
+ throwIllegalSignature(
+ "Field", name, signature, CHECK_(nullHandle));
+ }
+ } else {
+ verify_legal_field_signature(name, signature, CHECK_(nullHandle));
+ }
} else {
verify_legal_method_name(name, CHECK_(nullHandle));
- verify_legal_method_signature(name, signature, CHECK_(nullHandle));
+ if (_need_verify && _major_version >= JAVA_7_VERSION) {
+ // Signature is verified above, when iterating NameAndType_info.
+ // Need only to be sure it's the right type.
+ if (signature->byte_at(0) != JVM_SIGNATURE_FUNC) {
+ throwIllegalSignature(
+ "Method", name, signature, CHECK_(nullHandle));
+ }
+ } else {
+ verify_legal_method_signature(name, signature, CHECK_(nullHandle));
+ }
if (tag == JVM_CONSTANT_Methodref) {
// 4509014: If a class method name begins with '<', it must be "<init>".
assert(!name.is_null(), "method name in constant pool is null");
@@ -1313,6 +1349,14 @@
return checked_exceptions_start;
}
+void ClassFileParser::throwIllegalSignature(
+ const char* type, symbolHandle name, symbolHandle sig, TRAPS) {
+ ResourceMark rm(THREAD);
+ Exceptions::fthrow(THREAD_AND_LOCATION,
+ vmSymbols::java_lang_ClassFormatError(),
+ "%s \"%s\" in class %s has illegal signature \"%s\"", type,
+ name->as_C_string(), _class_name->as_C_string(), sig->as_C_string());
+}
#define MAX_ARGS_SIZE 255
#define MAX_CODE_SIZE 65535
@@ -4058,14 +4102,7 @@
char* p = skip_over_field_signature(bytes, false, length, CHECK);
if (p == NULL || (p - bytes) != (int)length) {
- ResourceMark rm(THREAD);
- Exceptions::fthrow(
- THREAD_AND_LOCATION,
- vmSymbolHandles::java_lang_ClassFormatError(),
- "Field \"%s\" in class %s has illegal signature \"%s\"",
- name->as_C_string(), _class_name->as_C_string(), bytes
- );
- return;
+ throwIllegalSignature("Field", name, signature, CHECK);
}
}
@@ -4116,13 +4153,7 @@
}
}
// Report error
- ResourceMark rm(THREAD);
- Exceptions::fthrow(
- THREAD_AND_LOCATION,
- vmSymbolHandles::java_lang_ClassFormatError(),
- "Method \"%s\" in class %s has illegal signature \"%s\"",
- name->as_C_string(), _class_name->as_C_string(), p
- );
+ throwIllegalSignature("Method", name, signature, CHECK_0);
return 0;
}
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -195,6 +195,9 @@
if (!b) { classfile_parse_error(msg, index, name, CHECK); }
}
+ void throwIllegalSignature(
+ const char* type, symbolHandle name, symbolHandle sig, TRAPS);
+
bool is_supported_version(u2 major, u2 minor);
bool has_illegal_visibility(jint flags);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -81,20 +81,24 @@
remove_expired_entries(end);
if (_no_entries == QueueLength) {
- // OK, right now when we fill up we bomb out
- // there are a few ways of dealing with this "gracefully"
+ // OK, we've filled up the queue. There are a few ways
+ // of dealing with this "gracefully"
// increase the array size (:-)
// remove the oldest entry (this might allow more GC time for
- // the time slice than what's allowed)
+ // the time slice than what's allowed) - this is what we
+ // currently do
// consolidate the two entries with the minimum gap between them
// (this might allow less GC time than what's allowed)
- guarantee(NOT_PRODUCT(ScavengeALot ||) G1UseFixedWindowMMUTracker,
- "array full, currently we can't recover unless +G1UseFixedWindowMMUTracker");
+
// In the case where ScavengeALot is true, such overflow is not
// uncommon; in such cases, we can, without much loss of precision
// or performance (we are GC'ing most of the time anyway!),
- // simply overwrite the oldest entry in the tracker: this
- // is also the behaviour when G1UseFixedWindowMMUTracker is enabled.
+ // simply overwrite the oldest entry in the tracker.
+
+ if (G1PolicyVerbose > 1) {
+ warning("MMU Tracker Queue overflow. Replacing earliest entry.");
+ }
+
_head_index = trim_index(_head_index + 1);
assert(_head_index == _tail_index, "Because we have a full circular buffer");
_tail_index = trim_index(_tail_index + 1);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -254,9 +254,6 @@
"If non-0 is the size of the G1 survivor space, " \
"otherwise SurvivorRatio is used to determine the size") \
\
- product(bool, G1UseFixedWindowMMUTracker, false, \
- "If the MMU tracker's memory is full, forget the oldest entry") \
- \
product(uintx, G1HeapRegionSize, 0, \
"Size of the G1 regions.") \
\
--- a/hotspot/src/share/vm/includeDB_compiler1 Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/includeDB_compiler1 Fri Jun 18 00:09:22 2010 -0700
@@ -71,8 +71,8 @@
c1_Compilation.cpp c1_MacroAssembler.hpp
c1_Compilation.cpp c1_ValueMap.hpp
c1_Compilation.cpp c1_ValueStack.hpp
-c1_Compilation.cpp ciEnv.hpp
c1_Compilation.cpp debugInfoRec.hpp
+c1_Compilation.hpp ciEnv.hpp
c1_Compilation.hpp exceptionHandlerTable.hpp
c1_Compilation.hpp resourceArea.hpp
@@ -82,6 +82,8 @@
c1_Compiler.cpp c1_Compilation.hpp
c1_Compiler.cpp c1_Compiler.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_Runtime1.hpp
c1_Compiler.cpp c1_ValueType.hpp
--- a/hotspot/src/share/vm/opto/graphKit.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -3487,7 +3487,6 @@
Node* tls = __ thread(); // ThreadLocalStorage
- Node* no_ctrl = NULL;
Node* no_base = __ top();
float likely = PROB_LIKELY(0.999);
float unlikely = PROB_UNLIKELY(0.999);
@@ -3511,10 +3510,10 @@
Node* index_adr = __ AddP(no_base, tls, __ ConX(index_offset));
// Now some values
-
- Node* index = __ load(no_ctrl, index_adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw);
- Node* buffer = __ load(no_ctrl, buffer_adr, TypeRawPtr::NOTNULL, T_ADDRESS, Compile::AliasIdxRaw);
-
+ // Use ctrl to avoid hoisting these values past a safepoint, which could
+ // potentially reset these fields in the JavaThread.
+ Node* index = __ load(__ ctrl(), index_adr, TypeInt::INT, T_INT, Compile::AliasIdxRaw);
+ Node* buffer = __ load(__ ctrl(), buffer_adr, TypeRawPtr::NOTNULL, T_ADDRESS, Compile::AliasIdxRaw);
// Convert the store obj pointer to an int prior to doing math on it
// Must use ctrl to prevent "integerized oop" existing across safepoint
--- a/hotspot/src/share/vm/opto/superword.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/opto/superword.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2010, 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
@@ -514,6 +514,13 @@
bool SuperWord::are_adjacent_refs(Node* s1, Node* s2) {
if (!s1->is_Mem() || !s2->is_Mem()) return false;
if (!in_bb(s1) || !in_bb(s2)) return false;
+
+ // Do not use superword for non-primitives
+ if (!is_java_primitive(s1->as_Mem()->memory_type()) ||
+ !is_java_primitive(s2->as_Mem()->memory_type())) {
+ return false;
+ }
+
// FIXME - co_locate_pack fails on Stores in different mem-slices, so
// only pack memops that are in the same alias set until that's fixed.
if (_phase->C->get_alias_index(s1->as_Mem()->adr_type()) !=
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -923,6 +923,10 @@
\
product(intx, AlwaysInflate, 0, "(Unstable) Force inflation") \
\
+ product(intx, MonitorBound, 0, "Bound Monitor population") \
+ \
+ product(bool, MonitorInUseLists, false, "Track Monitors for Deflation") \
+ \
product(intx, Atomics, 0, \
"(Unsafe,Unstable) Diagnostic - Controls emission of atomics") \
\
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -82,9 +82,6 @@
Mutex* DerivedPointerTableGC_lock = NULL;
Mutex* Compile_lock = NULL;
Monitor* MethodCompileQueue_lock = NULL;
-#ifdef TIERED
-Monitor* C1_lock = NULL;
-#endif // TIERED
Monitor* CompileThread_lock = NULL;
Mutex* CompileTaskAlloc_lock = NULL;
Mutex* CompileStatistics_lock = NULL;
@@ -255,11 +252,6 @@
def(Debug3_lock , Mutex , nonleaf+4, true );
def(ProfileVM_lock , Monitor, nonleaf+4, false); // used for profiling of the VMThread
def(CompileThread_lock , Monitor, nonleaf+5, false );
-#ifdef TIERED
- def(C1_lock , Monitor, nonleaf+5, false );
-#endif // TIERED
-
-
}
GCMutexLocker::GCMutexLocker(Monitor * mutex) {
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -84,9 +84,6 @@
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 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 Mutex* CompileTaskAlloc_lock; // a lock held when CompileTasks are allocated
extern Mutex* CompileStatistics_lock; // a lock held when updating compilation statistics
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -185,6 +185,8 @@
} ;
static SharedGlobals GVars ;
+static int MonitorScavengeThreshold = 1000000 ;
+static volatile int ForceMonitorScavenge = 0 ; // Scavenge required and pending
// Tunables ...
@@ -746,8 +748,85 @@
ObjectMonitor * ObjectSynchronizer::gBlockList = NULL ;
ObjectMonitor * volatile ObjectSynchronizer::gFreeList = NULL ;
static volatile intptr_t ListLock = 0 ; // protects global monitor free-list cache
+static volatile int MonitorFreeCount = 0 ; // # on gFreeList
+static volatile int MonitorPopulation = 0 ; // # Extant -- in circulation
#define CHAINMARKER ((oop)-1)
+// Constraining monitor pool growth via MonitorBound ...
+//
+// The monitor pool is grow-only. We scavenge at STW safepoint-time, but the
+// the rate of scavenging is driven primarily by GC. As such, we can find
+// an inordinate number of monitors in circulation.
+// To avoid that scenario we can artificially induce a STW safepoint
+// if the pool appears to be growing past some reasonable bound.
+// Generally we favor time in space-time tradeoffs, but as there's no
+// natural back-pressure on the # of extant monitors we need to impose some
+// type of limit. Beware that if MonitorBound is set to too low a value
+// we could just loop. In addition, if MonitorBound is set to a low value
+// we'll incur more safepoints, which are harmful to performance.
+// See also: GuaranteedSafepointInterval
+//
+// As noted elsewhere, the correct long-term solution is to deflate at
+// monitorexit-time, in which case the number of inflated objects is bounded
+// by the number of threads. That policy obviates the need for scavenging at
+// STW safepoint time. As an aside, scavenging can be time-consuming when the
+// # of extant monitors is large. Unfortunately there's a day-1 assumption baked
+// into much HotSpot code that the object::monitor relationship, once established
+// or observed, will remain stable except over potential safepoints.
+//
+// We can use either a blocking synchronous VM operation or an async VM operation.
+// -- If we use a blocking VM operation :
+// Calls to ScavengeCheck() should be inserted only into 'safe' locations in paths
+// that lead to ::inflate() or ::omAlloc().
+// Even though the safepoint will not directly induce GC, a GC might
+// piggyback on the safepoint operation, so the caller should hold no naked oops.
+// Furthermore, monitor::object relationships are NOT necessarily stable over this call
+// unless the caller has made provisions to "pin" the object to the monitor, say
+// by incrementing the monitor's _count field.
+// -- If we use a non-blocking asynchronous VM operation :
+// the constraints above don't apply. The safepoint will fire in the future
+// at a more convenient time. On the other hand the latency between posting and
+// running the safepoint introduces or admits "slop" or laxity during which the
+// monitor population can climb further above the threshold. The monitor population,
+// however, tends to converge asymptotically over time to a count that's slightly
+// above the target value specified by MonitorBound. That is, we avoid unbounded
+// growth, albeit with some imprecision.
+//
+// The current implementation uses asynchronous VM operations.
+//
+// Ideally we'd check if (MonitorPopulation > MonitorBound) in omAlloc()
+// immediately before trying to grow the global list via allocation.
+// If the predicate was true then we'd induce a synchronous safepoint, wait
+// for the safepoint to complete, and then again to allocate from the global
+// free list. This approach is much simpler and precise, admitting no "slop".
+// Unfortunately we can't safely safepoint in the midst of omAlloc(), so
+// instead we use asynchronous safepoints.
+
+static void InduceScavenge (Thread * Self, const char * Whence) {
+ // Induce STW safepoint to trim monitors
+ // Ultimately, this results in a call to deflate_idle_monitors() in the near future.
+ // More precisely, trigger an asynchronous STW safepoint as the number
+ // of active monitors passes the specified threshold.
+ // TODO: assert thread state is reasonable
+
+ if (ForceMonitorScavenge == 0 && Atomic::xchg (1, &ForceMonitorScavenge) == 0) {
+ if (Knob_Verbose) {
+ ::printf ("Monitor scavenge - Induced STW @%s (%d)\n", Whence, ForceMonitorScavenge) ;
+ ::fflush(stdout) ;
+ }
+ // Induce a 'null' safepoint to scavenge monitors
+ // Must VM_Operation instance be heap allocated as the op will be enqueue and posted
+ // to the VMthread and have a lifespan longer than that of this activation record.
+ // The VMThread will delete the op when completed.
+ VMThread::execute (new VM_ForceAsyncSafepoint()) ;
+
+ if (Knob_Verbose) {
+ ::printf ("Monitor scavenge - STW posted @%s (%d)\n", Whence, ForceMonitorScavenge) ;
+ ::fflush(stdout) ;
+ }
+ }
+}
+
ObjectMonitor * ATTR ObjectSynchronizer::omAlloc (Thread * Self) {
// A large MAXPRIVATE value reduces both list lock contention
// and list coherency traffic, but also tends to increase the
@@ -770,6 +849,11 @@
Self->omFreeCount -- ;
// CONSIDER: set m->FreeNext = BAD -- diagnostic hygiene
guarantee (m->object() == NULL, "invariant") ;
+ if (MonitorInUseLists) {
+ m->FreeNext = Self->omInUseList;
+ Self->omInUseList = m;
+ Self->omInUseCount ++;
+ }
return m ;
}
@@ -784,6 +868,7 @@
// on various locks.
Thread::muxAcquire (&ListLock, "omAlloc") ;
for (int i = Self->omFreeProvision; --i >= 0 && gFreeList != NULL; ) {
+ MonitorFreeCount --;
ObjectMonitor * take = gFreeList ;
gFreeList = take->FreeNext ;
guarantee (take->object() == NULL, "invariant") ;
@@ -796,6 +881,15 @@
if (Self->omFreeProvision > MAXPRIVATE ) Self->omFreeProvision = MAXPRIVATE ;
TEVENT (omFirst - reprovision) ;
continue ;
+
+ const int mx = MonitorBound ;
+ if (mx > 0 && (MonitorPopulation-MonitorFreeCount) > mx) {
+ // We can't safely induce a STW safepoint from omAlloc() as our thread
+ // state may not be appropriate for such activities and callers may hold
+ // naked oops, so instead we defer the action.
+ InduceScavenge (Self, "omAlloc") ;
+ }
+ continue;
}
// 3: allocate a block of new ObjectMonitors
@@ -836,6 +930,8 @@
// Acquire the ListLock to manipulate BlockList and FreeList.
// An Oyama-Taura-Yonezawa scheme might be more efficient.
Thread::muxAcquire (&ListLock, "omAlloc [2]") ;
+ MonitorPopulation += _BLOCKSIZE-1;
+ MonitorFreeCount += _BLOCKSIZE-1;
// Add the new block to the list of extant blocks (gBlockList).
// The very first objectMonitor in a block is reserved and dedicated.
@@ -894,7 +990,9 @@
if (List == NULL) return ;
ObjectMonitor * Tail = NULL ;
ObjectMonitor * s ;
+ int Tally = 0;
for (s = List ; s != NULL ; s = s->FreeNext) {
+ Tally ++ ;
Tail = s ;
guarantee (s->object() == NULL, "invariant") ;
guarantee (!s->is_busy(), "invariant") ;
@@ -906,6 +1004,7 @@
Thread::muxAcquire (&ListLock, "omFlush") ;
Tail->FreeNext = gFreeList ;
gFreeList = List ;
+ MonitorFreeCount += Tally;
Thread::muxRelease (&ListLock) ;
TEVENT (omFlush) ;
}
@@ -1747,16 +1846,15 @@
// Having a large number of monitors in-circulation negatively
// impacts the performance of some applications (e.g., PointBase).
// Broadly, we want to minimize the # of monitors in circulation.
-// Alternately, we could partition the active monitors into sub-lists
-// of those that need scanning and those that do not.
-// Specifically, we would add a new sub-list of objectmonitors
-// that are in-circulation and potentially active. deflate_idle_monitors()
-// would scan only that list. Other monitors could reside on a quiescent
-// list. Such sequestered monitors wouldn't need to be scanned by
-// deflate_idle_monitors(). omAlloc() would first check the global free list,
-// then the quiescent list, and, failing those, would allocate a new block.
-// Deflate_idle_monitors() would scavenge and move monitors to the
-// quiescent list.
+//
+// We have added a flag, MonitorInUseLists, which creates a list
+// of active monitors for each thread. deflate_idle_monitors()
+// only scans the per-thread inuse lists. omAlloc() puts all
+// assigned monitors on the per-thread list. deflate_idle_monitors()
+// returns the non-busy monitors to the global free list.
+// An alternative could have used a single global inuse list. The
+// downside would have been the additional cost of acquiring the global list lock
+// for every omAlloc().
//
// Perversely, the heap size -- and thus the STW safepoint rate --
// typically drives the scavenge rate. Large heaps can mean infrequent GC,
@@ -1769,18 +1867,100 @@
// An even better solution would be to deflate on-the-fly, aggressively,
// at monitorexit-time as is done in EVM's metalock or Relaxed Locks.
+
+// Deflate a single monitor if not in use
+// Return true if deflated, false if in use
+bool ObjectSynchronizer::deflate_monitor(ObjectMonitor* mid, oop obj,
+ ObjectMonitor** FreeHeadp, ObjectMonitor** FreeTailp) {
+ bool deflated;
+ // Normal case ... The monitor is associated with obj.
+ guarantee (obj->mark() == markOopDesc::encode(mid), "invariant") ;
+ guarantee (mid == obj->mark()->monitor(), "invariant");
+ guarantee (mid->header()->is_neutral(), "invariant");
+
+ if (mid->is_busy()) {
+ if (ClearResponsibleAtSTW) mid->_Responsible = NULL ;
+ deflated = false;
+ } else {
+ // Deflate the monitor if it is no longer being used
+ // It's idle - scavenge and return to the global free list
+ // plain old deflation ...
+ TEVENT (deflate_idle_monitors - scavenge1) ;
+ if (TraceMonitorInflation) {
+ if (obj->is_instance()) {
+ ResourceMark rm;
+ tty->print_cr("Deflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
+ (intptr_t) obj, (intptr_t) obj->mark(), Klass::cast(obj->klass())->external_name());
+ }
+ }
+
+ // Restore the header back to obj
+ obj->release_set_mark(mid->header());
+ mid->clear();
+
+ assert (mid->object() == NULL, "invariant") ;
+
+ // Move the object to the working free list defined by FreeHead,FreeTail.
+ if (*FreeHeadp == NULL) *FreeHeadp = mid;
+ if (*FreeTailp != NULL) {
+ ObjectMonitor * prevtail = *FreeTailp;
+ prevtail->FreeNext = mid;
+ }
+ *FreeTailp = mid;
+ deflated = true;
+ }
+ return deflated;
+}
+
void ObjectSynchronizer::deflate_idle_monitors() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
int nInuse = 0 ; // currently associated with objects
int nInCirculation = 0 ; // extant
int nScavenged = 0 ; // reclaimed
+ bool deflated = false;
ObjectMonitor * FreeHead = NULL ; // Local SLL of scavenged monitors
ObjectMonitor * FreeTail = NULL ;
+ TEVENT (deflate_idle_monitors) ;
+ // Prevent omFlush from changing mids in Thread dtor's during deflation
+ // And in case the vm thread is acquiring a lock during a safepoint
+ // See e.g. 6320749
+ Thread::muxAcquire (&ListLock, "scavenge - return") ;
+
+ if (MonitorInUseLists) {
+ ObjectMonitor* mid;
+ ObjectMonitor* next;
+ ObjectMonitor* curmidinuse;
+ for (JavaThread* cur = Threads::first(); cur != NULL; cur = cur->next()) {
+ curmidinuse = NULL;
+ for (mid = cur->omInUseList; mid != NULL; ) {
+ oop obj = (oop) mid->object();
+ deflated = false;
+ if (obj != NULL) {
+ deflated = deflate_monitor(mid, obj, &FreeHead, &FreeTail);
+ }
+ if (deflated) {
+ // extract from per-thread in-use-list
+ if (mid == cur->omInUseList) {
+ cur->omInUseList = mid->FreeNext;
+ } else if (curmidinuse != NULL) {
+ curmidinuse->FreeNext = mid->FreeNext; // maintain the current thread inuselist
+ }
+ next = mid->FreeNext;
+ mid->FreeNext = NULL; // This mid is current tail in the FreeHead list
+ mid = next;
+ cur->omInUseCount--;
+ nScavenged ++ ;
+ } else {
+ curmidinuse = mid;
+ mid = mid->FreeNext;
+ nInuse ++;
+ }
+ }
+ }
+ } else for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) {
// Iterate over all extant monitors - Scavenge all idle monitors.
- TEVENT (deflate_idle_monitors) ;
- for (ObjectMonitor* block = gBlockList; block != NULL; block = next(block)) {
assert(block->object() == CHAINMARKER, "must be a block header");
nInCirculation += _BLOCKSIZE ;
for (int i = 1 ; i < _BLOCKSIZE; i++) {
@@ -1795,61 +1975,39 @@
guarantee (!mid->is_busy(), "invariant") ;
continue ;
}
-
- // Normal case ... The monitor is associated with obj.
- guarantee (obj->mark() == markOopDesc::encode(mid), "invariant") ;
- guarantee (mid == obj->mark()->monitor(), "invariant");
- guarantee (mid->header()->is_neutral(), "invariant");
-
- if (mid->is_busy()) {
- if (ClearResponsibleAtSTW) mid->_Responsible = NULL ;
- nInuse ++ ;
+ deflated = deflate_monitor(mid, obj, &FreeHead, &FreeTail);
+
+ if (deflated) {
+ mid->FreeNext = NULL ;
+ nScavenged ++ ;
} else {
- // Deflate the monitor if it is no longer being used
- // It's idle - scavenge and return to the global free list
- // plain old deflation ...
- TEVENT (deflate_idle_monitors - scavenge1) ;
- if (TraceMonitorInflation) {
- if (obj->is_instance()) {
- ResourceMark rm;
- tty->print_cr("Deflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
- (intptr_t) obj, (intptr_t) obj->mark(), Klass::cast(obj->klass())->external_name());
- }
- }
-
- // Restore the header back to obj
- obj->release_set_mark(mid->header());
- mid->clear();
-
- assert (mid->object() == NULL, "invariant") ;
-
- // Move the object to the working free list defined by FreeHead,FreeTail.
- mid->FreeNext = NULL ;
- if (FreeHead == NULL) FreeHead = mid ;
- if (FreeTail != NULL) FreeTail->FreeNext = mid ;
- FreeTail = mid ;
- nScavenged ++ ;
+ nInuse ++;
}
}
}
+ MonitorFreeCount += nScavenged;
+
+ // Consider: audit gFreeList to ensure that MonitorFreeCount and list agree.
+
+ if (Knob_Verbose) {
+ ::printf ("Deflate: InCirc=%d InUse=%d Scavenged=%d ForceMonitorScavenge=%d : pop=%d free=%d\n",
+ nInCirculation, nInuse, nScavenged, ForceMonitorScavenge,
+ MonitorPopulation, MonitorFreeCount) ;
+ ::fflush(stdout) ;
+ }
+
+ ForceMonitorScavenge = 0; // Reset
+
// Move the scavenged monitors back to the global free list.
- // In theory we don't need the freelist lock as we're at a STW safepoint.
- // omAlloc() and omFree() can only be called while a thread is _not in safepoint state.
- // But it's remotely possible that omFlush() or release_monitors_owned_by_thread()
- // might be called while not at a global STW safepoint. In the interest of
- // safety we protect the following access with ListLock.
- // An even more conservative and prudent approach would be to guard
- // the main loop in scavenge_idle_monitors() with ListLock.
if (FreeHead != NULL) {
guarantee (FreeTail != NULL && nScavenged > 0, "invariant") ;
assert (FreeTail->FreeNext == NULL, "invariant") ;
// constant-time list splice - prepend scavenged segment to gFreeList
- Thread::muxAcquire (&ListLock, "scavenge - return") ;
FreeTail->FreeNext = gFreeList ;
gFreeList = FreeHead ;
- Thread::muxRelease (&ListLock) ;
}
+ Thread::muxRelease (&ListLock) ;
if (_sync_Deflations != NULL) _sync_Deflations->inc(nScavenged) ;
if (_sync_MonExtant != NULL) _sync_MonExtant ->set_value(nInCirculation);
--- a/hotspot/src/share/vm/runtime/synchronizer.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -150,6 +150,8 @@
// Basically we deflate all monitors that are not busy.
// An adaptive profile-based deflation policy could be used if needed
static void deflate_idle_monitors();
+ static bool deflate_monitor(ObjectMonitor* mid, oop obj, ObjectMonitor** FreeHeadp,
+ ObjectMonitor** FreeTailp);
static void oops_do(OopClosure* f);
// debugging
--- a/hotspot/src/share/vm/runtime/thread.cpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp Fri Jun 18 00:09:22 2010 -0700
@@ -139,6 +139,8 @@
omFreeList = NULL ;
omFreeCount = 0 ;
omFreeProvision = 32 ;
+ omInUseList = NULL ;
+ omInUseCount = 0 ;
_SR_lock = new Monitor(Mutex::suspend_resume, "SR_lock", true);
_suspend_flags = 0;
@@ -2797,6 +2799,7 @@
_task = NULL;
_queue = queue;
_counters = counters;
+ _buffer_blob = NULL;
#ifndef PRODUCT
_ideal_graph_printer = NULL;
--- a/hotspot/src/share/vm/runtime/thread.hpp Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/src/share/vm/runtime/thread.hpp Fri Jun 18 00:09:22 2010 -0700
@@ -225,6 +225,8 @@
ObjectMonitor * omFreeList ;
int omFreeCount ; // length of omFreeList
int omFreeProvision ; // reload chunk size
+ ObjectMonitor * omInUseList; // SLL to track monitors in circulation
+ int omInUseCount; // length of omInUseList
public:
enum {
@@ -493,7 +495,6 @@
static ByteSize stack_base_offset() { return byte_offset_of(Thread, _stack_base ); }
static ByteSize stack_size_offset() { return byte_offset_of(Thread, _stack_size ); }
- static ByteSize omFreeList_offset() { return byte_offset_of(Thread, omFreeList); }
#define TLAB_FIELD_OFFSET(name) \
static ByteSize tlab_##name##_offset() { return byte_offset_of(Thread, _tlab) + ThreadLocalAllocBuffer::name##_offset(); }
@@ -1576,6 +1577,7 @@
CompileLog* _log;
CompileTask* _task;
CompileQueue* _queue;
+ BufferBlob* _buffer_blob;
public:
@@ -1594,6 +1596,9 @@
ciEnv* env() { return _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
CompileLog* log() { return _log; }
void init_log(CompileLog* log) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6958485/Test.java Fri Jun 18 00:09:22 2010 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2010, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 6958485
+ * @summary fix for 6879921 was insufficient
+ *
+ * @run main/othervm -Xbatch -XX:CompileOnly=Test.init Test
+ */
+
+public class Test {
+
+ public static void init(Object src[], boolean[] dst) {
+ // initialize the arrays
+ for (int i =0; i<src.length; i++) {
+ dst[i] = src[i] != null ? false : true;
+ }
+ }
+
+ public static void test() {
+ Object[] src = new Object[34];
+ boolean[] dst = new boolean[34];
+
+ init(src, dst);
+ }
+
+ public static void main(String[] args) {
+ for (int i=0; i< 2000; i++) {
+ test();
+ }
+ }
+}
--- a/hotspot/test/runtime/6888954/vmerrors.sh Thu Jun 17 23:59:24 2010 -0700
+++ b/hotspot/test/runtime/6888954/vmerrors.sh Fri Jun 18 00:09:22 2010 -0700
@@ -65,7 +65,7 @@
done
rm -f $$
- i=$(expr $i + 1)
+ i=`expr $i + 1`
done
exit $rc