Thu, 10 Oct 2013 15:44:12 +0200
8023014: CodeSweeperSweepNoFlushTest.java fails with HS crash
Summary: Ensure ensure correct initialization of compiler runtime
Reviewed-by: kvn, twisti
1.1 --- a/src/share/vm/c1/c1_Compiler.cpp Fri Oct 11 10:14:02 2013 -0700 1.2 +++ b/src/share/vm/c1/c1_Compiler.cpp Thu Oct 10 15:44:12 2013 +0200 1.3 @@ -42,26 +42,16 @@ 1.4 #include "runtime/interfaceSupport.hpp" 1.5 #include "runtime/sharedRuntime.hpp" 1.6 1.7 -volatile int Compiler::_runtimes = uninitialized; 1.8 1.9 -Compiler::Compiler() { 1.10 -} 1.11 +Compiler::Compiler () {} 1.12 1.13 - 1.14 -Compiler::~Compiler() { 1.15 - Unimplemented(); 1.16 -} 1.17 - 1.18 - 1.19 -void Compiler::initialize_all() { 1.20 +void Compiler::init_c1_runtime() { 1.21 BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob(); 1.22 Arena* arena = new (mtCompiler) Arena(); 1.23 Runtime1::initialize(buffer_blob); 1.24 FrameMap::initialize(); 1.25 // initialize data structures 1.26 ValueType::initialize(arena); 1.27 - // Instruction::initialize(); 1.28 - // BlockBegin::initialize(); 1.29 GraphBuilder::initialize(); 1.30 // note: to use more than one instance of LinearScan at a time this function call has to 1.31 // be moved somewhere outside of this constructor: 1.32 @@ -70,32 +60,33 @@ 1.33 1.34 1.35 void Compiler::initialize() { 1.36 - if (_runtimes != initialized) { 1.37 - initialize_runtimes( initialize_all, &_runtimes); 1.38 + // Buffer blob must be allocated per C1 compiler thread at startup 1.39 + BufferBlob* buffer_blob = init_buffer_blob(); 1.40 + 1.41 + if (should_perform_init()) { 1.42 + if (buffer_blob == NULL) { 1.43 + // When we come here we are in state 'initializing'; entire C1 compilation 1.44 + // can be shut down. 1.45 + set_state(failed); 1.46 + } else { 1.47 + init_c1_runtime(); 1.48 + set_state(initialized); 1.49 + } 1.50 } 1.51 - mark_initialized(); 1.52 } 1.53 1.54 - 1.55 -BufferBlob* Compiler::get_buffer_blob(ciEnv* env) { 1.56 +BufferBlob* Compiler::init_buffer_blob() { 1.57 // Allocate buffer blob once at startup since allocation for each 1.58 // compilation seems to be too expensive (at least on Intel win32). 1.59 - BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob(); 1.60 - if (buffer_blob != NULL) { 1.61 - return buffer_blob; 1.62 - } 1.63 + assert (CompilerThread::current()->get_buffer_blob() == NULL, "Should initialize only once"); 1.64 1.65 // setup CodeBuffer. Preallocate a BufferBlob of size 1.66 // NMethodSizeLimit plus some extra space for constants. 1.67 int code_buffer_size = Compilation::desired_max_code_buffer_size() + 1.68 Compilation::desired_max_constant_size(); 1.69 1.70 - buffer_blob = BufferBlob::create("Compiler1 temporary CodeBuffer", 1.71 - code_buffer_size); 1.72 - if (buffer_blob == NULL) { 1.73 - CompileBroker::handle_full_code_cache(); 1.74 - env->record_failure("CodeCache is full"); 1.75 - } else { 1.76 + BufferBlob* buffer_blob = BufferBlob::create("C1 temporary CodeBuffer", code_buffer_size); 1.77 + if (buffer_blob != NULL) { 1.78 CompilerThread::current()->set_buffer_blob(buffer_blob); 1.79 } 1.80 1.81 @@ -104,15 +95,8 @@ 1.82 1.83 1.84 void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) { 1.85 - BufferBlob* buffer_blob = Compiler::get_buffer_blob(env); 1.86 - if (buffer_blob == NULL) { 1.87 - return; 1.88 - } 1.89 - 1.90 - if (!is_initialized()) { 1.91 - initialize(); 1.92 - } 1.93 - 1.94 + BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob(); 1.95 + assert(buffer_blob != NULL, "Must exist"); 1.96 // invoke compilation 1.97 { 1.98 // We are nested here because we need for the destructor
2.1 --- a/src/share/vm/c1/c1_Compiler.hpp Fri Oct 11 10:14:02 2013 -0700 2.2 +++ b/src/share/vm/c1/c1_Compiler.hpp Thu Oct 10 15:44:12 2013 +0200 2.3 @@ -30,11 +30,9 @@ 2.4 // There is one instance of the Compiler per CompilerThread. 2.5 2.6 class Compiler: public AbstractCompiler { 2.7 - 2.8 private: 2.9 - 2.10 - // Tracks whether runtime has been initialized 2.11 - static volatile int _runtimes; 2.12 + static void init_c1_runtime(); 2.13 + BufferBlob* init_buffer_blob(); 2.14 2.15 public: 2.16 // Creation 2.17 @@ -46,19 +44,12 @@ 2.18 2.19 virtual bool is_c1() { return true; }; 2.20 2.21 - BufferBlob* get_buffer_blob(ciEnv* env); 2.22 - 2.23 // Missing feature tests 2.24 virtual bool supports_native() { return true; } 2.25 virtual bool supports_osr () { return true; } 2.26 2.27 - // Customization 2.28 - virtual bool needs_adapters () { return false; } 2.29 - virtual bool needs_stubs () { return false; } 2.30 - 2.31 // Initialization 2.32 virtual void initialize(); 2.33 - static void initialize_all(); 2.34 2.35 // Compilation entry point for methods 2.36 virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
3.1 --- a/src/share/vm/code/codeBlob.cpp Fri Oct 11 10:14:02 2013 -0700 3.2 +++ b/src/share/vm/code/codeBlob.cpp Thu Oct 10 15:44:12 2013 +0200 3.3 @@ -245,8 +245,8 @@ 3.4 } 3.5 3.6 3.7 -void* BufferBlob::operator new(size_t s, unsigned size) throw() { 3.8 - void* p = CodeCache::allocate(size); 3.9 +void* BufferBlob::operator new(size_t s, unsigned size, bool is_critical) throw() { 3.10 + void* p = CodeCache::allocate(size, is_critical); 3.11 return p; 3.12 } 3.13 3.14 @@ -277,7 +277,10 @@ 3.15 unsigned int size = allocation_size(cb, sizeof(AdapterBlob)); 3.16 { 3.17 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 3.18 - blob = new (size) AdapterBlob(size, cb); 3.19 + // The parameter 'true' indicates a critical memory allocation. 3.20 + // This means that CodeCacheMinimumFreeSpace is used, if necessary 3.21 + const bool is_critical = true; 3.22 + blob = new (size, is_critical) AdapterBlob(size, cb); 3.23 } 3.24 // Track memory usage statistic after releasing CodeCache_lock 3.25 MemoryService::track_code_cache_memory_usage(); 3.26 @@ -299,7 +302,10 @@ 3.27 size += round_to(buffer_size, oopSize); 3.28 { 3.29 MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 3.30 - blob = new (size) MethodHandlesAdapterBlob(size); 3.31 + // The parameter 'true' indicates a critical memory allocation. 3.32 + // This means that CodeCacheMinimumFreeSpace is used, if necessary 3.33 + const bool is_critical = true; 3.34 + blob = new (size, is_critical) MethodHandlesAdapterBlob(size); 3.35 } 3.36 // Track memory usage statistic after releasing CodeCache_lock 3.37 MemoryService::track_code_cache_memory_usage();
4.1 --- a/src/share/vm/code/codeBlob.hpp Fri Oct 11 10:14:02 2013 -0700 4.2 +++ b/src/share/vm/code/codeBlob.hpp Thu Oct 10 15:44:12 2013 +0200 4.3 @@ -209,7 +209,7 @@ 4.4 BufferBlob(const char* name, int size); 4.5 BufferBlob(const char* name, int size, CodeBuffer* cb); 4.6 4.7 - void* operator new(size_t s, unsigned size) throw(); 4.8 + void* operator new(size_t s, unsigned size, bool is_critical = false) throw(); 4.9 4.10 public: 4.11 // Creation 4.12 @@ -253,7 +253,6 @@ 4.13 class MethodHandlesAdapterBlob: public BufferBlob { 4.14 private: 4.15 MethodHandlesAdapterBlob(int size) : BufferBlob("MethodHandles adapters", size) {} 4.16 - MethodHandlesAdapterBlob(int size, CodeBuffer* cb) : BufferBlob("MethodHandles adapters", size, cb) {} 4.17 4.18 public: 4.19 // Creation
5.1 --- a/src/share/vm/compiler/abstractCompiler.cpp Fri Oct 11 10:14:02 2013 -0700 5.2 +++ b/src/share/vm/compiler/abstractCompiler.cpp Thu Oct 10 15:44:12 2013 +0200 5.3 @@ -24,41 +24,42 @@ 5.4 5.5 #include "precompiled.hpp" 5.6 #include "compiler/abstractCompiler.hpp" 5.7 +#include "compiler/compileBroker.hpp" 5.8 #include "runtime/mutexLocker.hpp" 5.9 -void AbstractCompiler::initialize_runtimes(initializer f, volatile int* state) { 5.10 - if (*state != initialized) { 5.11 5.12 - // We are thread in native here... 5.13 - CompilerThread* thread = CompilerThread::current(); 5.14 - bool do_initialization = false; 5.15 - { 5.16 - ThreadInVMfromNative tv(thread); 5.17 - ResetNoHandleMark rnhm; 5.18 - MutexLocker only_one(CompileThread_lock, thread); 5.19 - if ( *state == uninitialized) { 5.20 - do_initialization = true; 5.21 - *state = initializing; 5.22 - } else { 5.23 - while (*state == initializing ) { 5.24 - CompileThread_lock->wait(); 5.25 - } 5.26 +bool AbstractCompiler::should_perform_init() { 5.27 + if (_compiler_state != initialized) { 5.28 + MutexLocker only_one(CompileThread_lock); 5.29 + 5.30 + if (_compiler_state == uninitialized) { 5.31 + _compiler_state = initializing; 5.32 + return true; 5.33 + } else { 5.34 + while (_compiler_state == initializing) { 5.35 + CompileThread_lock->wait(); 5.36 } 5.37 } 5.38 - if (do_initialization) { 5.39 - // We can not hold any locks here since JVMTI events may call agents 5.40 + } 5.41 + return false; 5.42 +} 5.43 5.44 - // Compiler(s) run as native 5.45 +bool AbstractCompiler::should_perform_shutdown() { 5.46 + // Since this method can be called by multiple threads, the lock ensures atomicity of 5.47 + // decrementing '_num_compiler_threads' and the following operations. 5.48 + MutexLocker only_one(CompileThread_lock); 5.49 + _num_compiler_threads--; 5.50 + assert (CompileBroker::is_compilation_disabled_forever(), "Must be set, otherwise thread waits forever"); 5.51 5.52 - (*f)(); 5.53 + // Only the last thread will perform shutdown operations 5.54 + if (_num_compiler_threads == 0) { 5.55 + return true; 5.56 + } 5.57 + return false; 5.58 +} 5.59 5.60 - // To in_vm so we can use the lock 5.61 - 5.62 - ThreadInVMfromNative tv(thread); 5.63 - ResetNoHandleMark rnhm; 5.64 - MutexLocker only_one(CompileThread_lock, thread); 5.65 - assert(*state == initializing, "wrong state"); 5.66 - *state = initialized; 5.67 - CompileThread_lock->notify_all(); 5.68 - } 5.69 - } 5.70 +void AbstractCompiler::set_state(int state) { 5.71 + // Ensure that ste is only set by one thread at a time 5.72 + MutexLocker only_one(CompileThread_lock); 5.73 + _compiler_state = state; 5.74 + CompileThread_lock->notify_all(); 5.75 }
6.1 --- a/src/share/vm/compiler/abstractCompiler.hpp Fri Oct 11 10:14:02 2013 -0700 6.2 +++ b/src/share/vm/compiler/abstractCompiler.hpp Thu Oct 10 15:44:12 2013 +0200 6.3 @@ -27,22 +27,25 @@ 6.4 6.5 #include "ci/compilerInterface.hpp" 6.6 6.7 -typedef void (*initializer)(void); 6.8 - 6.9 class AbstractCompiler : public CHeapObj<mtCompiler> { 6.10 private: 6.11 - bool _is_initialized; // Mark whether compiler object is initialized 6.12 + volatile int _num_compiler_threads; 6.13 6.14 protected: 6.15 + volatile int _compiler_state; 6.16 // Used for tracking global state of compiler runtime initialization 6.17 - enum { uninitialized, initializing, initialized }; 6.18 + enum { uninitialized, initializing, initialized, failed, shut_down }; 6.19 6.20 - // This method will call the initialization method "f" once (per compiler class/subclass) 6.21 - // and do so without holding any locks 6.22 - void initialize_runtimes(initializer f, volatile int* state); 6.23 + // This method returns true for the first compiler thread that reaches that methods. 6.24 + // This thread will initialize the compiler runtime. 6.25 + bool should_perform_init(); 6.26 6.27 public: 6.28 - AbstractCompiler() : _is_initialized(false) {} 6.29 + AbstractCompiler() : _compiler_state(uninitialized), _num_compiler_threads(0) {} 6.30 + 6.31 + // This function determines the compiler thread that will perform the 6.32 + // shutdown of the corresponding compiler runtime. 6.33 + bool should_perform_shutdown(); 6.34 6.35 // Name of this compiler 6.36 virtual const char* name() = 0; 6.37 @@ -74,17 +77,18 @@ 6.38 #endif // TIERED 6.39 6.40 // Customization 6.41 - virtual bool needs_stubs () = 0; 6.42 + virtual void initialize () = 0; 6.43 6.44 - void mark_initialized() { _is_initialized = true; } 6.45 - bool is_initialized() { return _is_initialized; } 6.46 + void set_num_compiler_threads(int num) { _num_compiler_threads = num; } 6.47 + int num_compiler_threads() { return _num_compiler_threads; } 6.48 6.49 - virtual void initialize() = 0; 6.50 - 6.51 + // Get/set state of compiler objects 6.52 + bool is_initialized() { return _compiler_state == initialized; } 6.53 + bool is_failed () { return _compiler_state == failed;} 6.54 + void set_state (int state); 6.55 + void set_shut_down () { set_state(shut_down); } 6.56 // Compilation entry point for methods 6.57 - virtual void compile_method(ciEnv* env, 6.58 - ciMethod* target, 6.59 - int entry_bci) { 6.60 + virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci) { 6.61 ShouldNotReachHere(); 6.62 } 6.63
7.1 --- a/src/share/vm/compiler/compileBroker.cpp Fri Oct 11 10:14:02 2013 -0700 7.2 +++ b/src/share/vm/compiler/compileBroker.cpp Thu Oct 10 15:44:12 2013 +0200 7.3 @@ -186,7 +186,7 @@ 7.4 CompileQueue* CompileBroker::_c1_method_queue = NULL; 7.5 CompileTask* CompileBroker::_task_free_list = NULL; 7.6 7.7 -GrowableArray<CompilerThread*>* CompileBroker::_method_threads = NULL; 7.8 +GrowableArray<CompilerThread*>* CompileBroker::_compiler_threads = NULL; 7.9 7.10 7.11 class CompilationLog : public StringEventLog { 7.12 @@ -587,9 +587,6 @@ 7.13 7.14 7.15 7.16 -// ------------------------------------------------------------------ 7.17 -// CompileQueue::add 7.18 -// 7.19 // Add a CompileTask to a CompileQueue 7.20 void CompileQueue::add(CompileTask* task) { 7.21 assert(lock()->owned_by_self(), "must own lock"); 7.22 @@ -626,6 +623,16 @@ 7.23 lock()->notify_all(); 7.24 } 7.25 7.26 +void CompileQueue::delete_all() { 7.27 + assert(lock()->owned_by_self(), "must own lock"); 7.28 + if (_first != NULL) { 7.29 + for (CompileTask* task = _first; task != NULL; task = task->next()) { 7.30 + delete task; 7.31 + } 7.32 + _first = NULL; 7.33 + } 7.34 +} 7.35 + 7.36 // ------------------------------------------------------------------ 7.37 // CompileQueue::get 7.38 // 7.39 @@ -640,6 +647,11 @@ 7.40 // case we perform code cache sweeps to free memory such that we can re-enable 7.41 // compilation. 7.42 while (_first == NULL) { 7.43 + // Exit loop if compilation is disabled forever 7.44 + if (CompileBroker::is_compilation_disabled_forever()) { 7.45 + return NULL; 7.46 + } 7.47 + 7.48 if (UseCodeCacheFlushing && !CompileBroker::should_compile_new_jobs()) { 7.49 // Wait a certain amount of time to possibly do another sweep. 7.50 // We must wait until stack scanning has happened so that we can 7.51 @@ -664,9 +676,17 @@ 7.52 // remains unchanged. This behavior is desired, since we want to keep 7.53 // the stable state, i.e., we do not want to evict methods from the 7.54 // code cache if it is unnecessary. 7.55 - lock()->wait(); 7.56 + // We need a timed wait here, since compiler threads can exit if compilation 7.57 + // is disabled forever. We use 5 seconds wait time; the exiting of compiler threads 7.58 + // is not critical and we do not want idle compiler threads to wake up too often. 7.59 + lock()->wait(!Mutex::_no_safepoint_check_flag, 5*1000); 7.60 } 7.61 } 7.62 + 7.63 + if (CompileBroker::is_compilation_disabled_forever()) { 7.64 + return NULL; 7.65 + } 7.66 + 7.67 CompileTask* task = CompilationPolicy::policy()->select_task(this); 7.68 remove(task); 7.69 return task; 7.70 @@ -891,10 +911,8 @@ 7.71 } 7.72 7.73 7.74 - 7.75 -// ------------------------------------------------------------------ 7.76 -// CompileBroker::make_compiler_thread 7.77 -CompilerThread* CompileBroker::make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, TRAPS) { 7.78 +CompilerThread* CompileBroker::make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, 7.79 + AbstractCompiler* comp, TRAPS) { 7.80 CompilerThread* compiler_thread = NULL; 7.81 7.82 Klass* k = 7.83 @@ -961,6 +979,7 @@ 7.84 java_lang_Thread::set_daemon(thread_oop()); 7.85 7.86 compiler_thread->set_threadObj(thread_oop()); 7.87 + compiler_thread->set_compiler(comp); 7.88 Threads::add(compiler_thread); 7.89 Thread::start(compiler_thread); 7.90 } 7.91 @@ -972,25 +991,24 @@ 7.92 } 7.93 7.94 7.95 -// ------------------------------------------------------------------ 7.96 -// CompileBroker::init_compiler_threads 7.97 -// 7.98 -// Initialize the compilation queue 7.99 void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler_count) { 7.100 EXCEPTION_MARK; 7.101 #if !defined(ZERO) && !defined(SHARK) 7.102 assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?"); 7.103 #endif // !ZERO && !SHARK 7.104 + // Initialize the compilation queue 7.105 if (c2_compiler_count > 0) { 7.106 _c2_method_queue = new CompileQueue("C2MethodQueue", MethodCompileQueue_lock); 7.107 + _compilers[1]->set_num_compiler_threads(c2_compiler_count); 7.108 } 7.109 if (c1_compiler_count > 0) { 7.110 _c1_method_queue = new CompileQueue("C1MethodQueue", MethodCompileQueue_lock); 7.111 + _compilers[0]->set_num_compiler_threads(c1_compiler_count); 7.112 } 7.113 7.114 int compiler_count = c1_compiler_count + c2_compiler_count; 7.115 7.116 - _method_threads = 7.117 + _compiler_threads = 7.118 new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<CompilerThread*>(compiler_count, true); 7.119 7.120 char name_buffer[256]; 7.121 @@ -998,21 +1016,22 @@ 7.122 // Create a name for our thread. 7.123 sprintf(name_buffer, "C2 CompilerThread%d", i); 7.124 CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK); 7.125 - CompilerThread* new_thread = make_compiler_thread(name_buffer, _c2_method_queue, counters, CHECK); 7.126 - _method_threads->append(new_thread); 7.127 + // Shark and C2 7.128 + CompilerThread* new_thread = make_compiler_thread(name_buffer, _c2_method_queue, counters, _compilers[1], CHECK); 7.129 + _compiler_threads->append(new_thread); 7.130 } 7.131 7.132 for (int i = c2_compiler_count; i < compiler_count; i++) { 7.133 // Create a name for our thread. 7.134 sprintf(name_buffer, "C1 CompilerThread%d", i); 7.135 CompilerCounters* counters = new CompilerCounters("compilerThread", i, CHECK); 7.136 - CompilerThread* new_thread = make_compiler_thread(name_buffer, _c1_method_queue, counters, CHECK); 7.137 - _method_threads->append(new_thread); 7.138 + // C1 7.139 + CompilerThread* new_thread = make_compiler_thread(name_buffer, _c1_method_queue, counters, _compilers[0], CHECK); 7.140 + _compiler_threads->append(new_thread); 7.141 } 7.142 7.143 if (UsePerfData) { 7.144 - PerfDataManager::create_constant(SUN_CI, "threads", PerfData::U_Bytes, 7.145 - compiler_count, CHECK); 7.146 + PerfDataManager::create_constant(SUN_CI, "threads", PerfData::U_Bytes, compiler_count, CHECK); 7.147 } 7.148 } 7.149 7.150 @@ -1029,27 +1048,6 @@ 7.151 } 7.152 7.153 // ------------------------------------------------------------------ 7.154 -// CompileBroker::is_idle 7.155 -bool CompileBroker::is_idle() { 7.156 - if (_c2_method_queue != NULL && !_c2_method_queue->is_empty()) { 7.157 - return false; 7.158 - } else if (_c1_method_queue != NULL && !_c1_method_queue->is_empty()) { 7.159 - return false; 7.160 - } else { 7.161 - int num_threads = _method_threads->length(); 7.162 - for (int i=0; i<num_threads; i++) { 7.163 - if (_method_threads->at(i)->task() != NULL) { 7.164 - return false; 7.165 - } 7.166 - } 7.167 - 7.168 - // No pending or active compilations. 7.169 - return true; 7.170 - } 7.171 -} 7.172 - 7.173 - 7.174 -// ------------------------------------------------------------------ 7.175 // CompileBroker::compile_method 7.176 // 7.177 // Request compilation of a method. 7.178 @@ -1551,6 +1549,101 @@ 7.179 free_task(task); 7.180 } 7.181 7.182 +// Initialize compiler thread(s) + compiler object(s). The postcondition 7.183 +// of this function is that the compiler runtimes are initialized and that 7.184 +//compiler threads can start compiling. 7.185 +bool CompileBroker::init_compiler_runtime() { 7.186 + CompilerThread* thread = CompilerThread::current(); 7.187 + AbstractCompiler* comp = thread->compiler(); 7.188 + // Final sanity check - the compiler object must exist 7.189 + guarantee(comp != NULL, "Compiler object must exist"); 7.190 + 7.191 + int system_dictionary_modification_counter; 7.192 + { 7.193 + MutexLocker locker(Compile_lock, thread); 7.194 + system_dictionary_modification_counter = SystemDictionary::number_of_modifications(); 7.195 + } 7.196 + 7.197 + { 7.198 + // Must switch to native to allocate ci_env 7.199 + ThreadToNativeFromVM ttn(thread); 7.200 + ciEnv ci_env(NULL, system_dictionary_modification_counter); 7.201 + // Cache Jvmti state 7.202 + ci_env.cache_jvmti_state(); 7.203 + // Cache DTrace flags 7.204 + ci_env.cache_dtrace_flags(); 7.205 + 7.206 + // Switch back to VM state to do compiler initialization 7.207 + ThreadInVMfromNative tv(thread); 7.208 + ResetNoHandleMark rnhm; 7.209 + 7.210 + 7.211 + if (!comp->is_shark()) { 7.212 + // Perform per-thread and global initializations 7.213 + comp->initialize(); 7.214 + } 7.215 + } 7.216 + 7.217 + if (comp->is_failed()) { 7.218 + disable_compilation_forever(); 7.219 + // If compiler initialization failed, no compiler thread that is specific to a 7.220 + // particular compiler runtime will ever start to compile methods. 7.221 + 7.222 + shutdown_compiler_runtime(comp, thread); 7.223 + return false; 7.224 + } 7.225 + 7.226 + // C1 specific check 7.227 + if (comp->is_c1() && (thread->get_buffer_blob() == NULL)) { 7.228 + warning("Initialization of %s thread failed (no space to run compilers)", thread->name()); 7.229 + return false; 7.230 + } 7.231 + 7.232 + return true; 7.233 +} 7.234 + 7.235 +// If C1 and/or C2 initialization failed, we shut down all compilation. 7.236 +// We do this to keep things simple. This can be changed if it ever turns out to be 7.237 +// a problem. 7.238 +void CompileBroker::shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread) { 7.239 + // Free buffer blob, if allocated 7.240 + if (thread->get_buffer_blob() != NULL) { 7.241 + MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); 7.242 + CodeCache::free(thread->get_buffer_blob()); 7.243 + } 7.244 + 7.245 + if (comp->should_perform_shutdown()) { 7.246 + // There are two reasons for shutting down the compiler 7.247 + // 1) compiler runtime initialization failed 7.248 + // 2) The code cache is full and the following flag is set: -XX:-UseCodeCacheFlushing 7.249 + warning("Shutting down compiler %s (no space to run compilers)", comp->name()); 7.250 + 7.251 + // Only one thread per compiler runtime object enters here 7.252 + // Set state to shut down 7.253 + comp->set_shut_down(); 7.254 + 7.255 + MutexLocker mu(MethodCompileQueue_lock, thread); 7.256 + CompileQueue* queue; 7.257 + if (_c1_method_queue != NULL) { 7.258 + _c1_method_queue->delete_all(); 7.259 + queue = _c1_method_queue; 7.260 + _c1_method_queue = NULL; 7.261 + delete _c1_method_queue; 7.262 + } 7.263 + 7.264 + if (_c2_method_queue != NULL) { 7.265 + _c2_method_queue->delete_all(); 7.266 + queue = _c2_method_queue; 7.267 + _c2_method_queue = NULL; 7.268 + delete _c2_method_queue; 7.269 + } 7.270 + 7.271 + // We could delete compiler runtimes also. However, there are references to 7.272 + // the compiler runtime(s) (e.g., nmethod::is_compiled_by_c1()) which then 7.273 + // fail. This can be done later if necessary. 7.274 + } 7.275 +} 7.276 + 7.277 // ------------------------------------------------------------------ 7.278 // CompileBroker::compiler_thread_loop 7.279 // 7.280 @@ -1558,7 +1651,6 @@ 7.281 void CompileBroker::compiler_thread_loop() { 7.282 CompilerThread* thread = CompilerThread::current(); 7.283 CompileQueue* queue = thread->queue(); 7.284 - 7.285 // For the thread that initializes the ciObjectFactory 7.286 // this resource mark holds all the shared objects 7.287 ResourceMark rm; 7.288 @@ -1587,65 +1679,78 @@ 7.289 log->end_elem(); 7.290 } 7.291 7.292 - while (true) { 7.293 - { 7.294 - // We need this HandleMark to avoid leaking VM handles. 7.295 - HandleMark hm(thread); 7.296 + // If compiler thread/runtime initialization fails, exit the compiler thread 7.297 + if (!init_compiler_runtime()) { 7.298 + return; 7.299 + } 7.300 7.301 - if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) { 7.302 - // the code cache is really full 7.303 - handle_full_code_cache(); 7.304 - } 7.305 + // Poll for new compilation tasks as long as the JVM runs. Compilation 7.306 + // should only be disabled if something went wrong while initializing the 7.307 + // compiler runtimes. This, in turn, should not happen. The only known case 7.308 + // when compiler runtime initialization fails is if there is not enough free 7.309 + // space in the code cache to generate the necessary stubs, etc. 7.310 + while (!is_compilation_disabled_forever()) { 7.311 + // We need this HandleMark to avoid leaking VM handles. 7.312 + HandleMark hm(thread); 7.313 7.314 - CompileTask* task = queue->get(); 7.315 + if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) { 7.316 + // the code cache is really full 7.317 + handle_full_code_cache(); 7.318 + } 7.319 7.320 - // Give compiler threads an extra quanta. They tend to be bursty and 7.321 - // this helps the compiler to finish up the job. 7.322 - if( CompilerThreadHintNoPreempt ) 7.323 - os::hint_no_preempt(); 7.324 + CompileTask* task = queue->get(); 7.325 + if (task == NULL) { 7.326 + continue; 7.327 + } 7.328 7.329 - // trace per thread time and compile statistics 7.330 - CompilerCounters* counters = ((CompilerThread*)thread)->counters(); 7.331 - PerfTraceTimedEvent(counters->time_counter(), counters->compile_counter()); 7.332 + // Give compiler threads an extra quanta. They tend to be bursty and 7.333 + // this helps the compiler to finish up the job. 7.334 + if( CompilerThreadHintNoPreempt ) 7.335 + os::hint_no_preempt(); 7.336 7.337 - // Assign the task to the current thread. Mark this compilation 7.338 - // thread as active for the profiler. 7.339 - CompileTaskWrapper ctw(task); 7.340 - nmethodLocker result_handle; // (handle for the nmethod produced by this task) 7.341 - task->set_code_handle(&result_handle); 7.342 - methodHandle method(thread, task->method()); 7.343 + // trace per thread time and compile statistics 7.344 + CompilerCounters* counters = ((CompilerThread*)thread)->counters(); 7.345 + PerfTraceTimedEvent(counters->time_counter(), counters->compile_counter()); 7.346 7.347 - // Never compile a method if breakpoints are present in it 7.348 - if (method()->number_of_breakpoints() == 0) { 7.349 - // Compile the method. 7.350 - if ((UseCompiler || AlwaysCompileLoopMethods) && CompileBroker::should_compile_new_jobs()) { 7.351 + // Assign the task to the current thread. Mark this compilation 7.352 + // thread as active for the profiler. 7.353 + CompileTaskWrapper ctw(task); 7.354 + nmethodLocker result_handle; // (handle for the nmethod produced by this task) 7.355 + task->set_code_handle(&result_handle); 7.356 + methodHandle method(thread, task->method()); 7.357 + 7.358 + // Never compile a method if breakpoints are present in it 7.359 + if (method()->number_of_breakpoints() == 0) { 7.360 + // Compile the method. 7.361 + if ((UseCompiler || AlwaysCompileLoopMethods) && CompileBroker::should_compile_new_jobs()) { 7.362 #ifdef COMPILER1 7.363 - // Allow repeating compilations for the purpose of benchmarking 7.364 - // compile speed. This is not useful for customers. 7.365 - if (CompilationRepeat != 0) { 7.366 - int compile_count = CompilationRepeat; 7.367 - while (compile_count > 0) { 7.368 - invoke_compiler_on_method(task); 7.369 - nmethod* nm = method->code(); 7.370 - if (nm != NULL) { 7.371 - nm->make_zombie(); 7.372 - method->clear_code(); 7.373 - } 7.374 - compile_count--; 7.375 + // Allow repeating compilations for the purpose of benchmarking 7.376 + // compile speed. This is not useful for customers. 7.377 + if (CompilationRepeat != 0) { 7.378 + int compile_count = CompilationRepeat; 7.379 + while (compile_count > 0) { 7.380 + invoke_compiler_on_method(task); 7.381 + nmethod* nm = method->code(); 7.382 + if (nm != NULL) { 7.383 + nm->make_zombie(); 7.384 + method->clear_code(); 7.385 } 7.386 + compile_count--; 7.387 } 7.388 + } 7.389 #endif /* COMPILER1 */ 7.390 - invoke_compiler_on_method(task); 7.391 - } else { 7.392 - // After compilation is disabled, remove remaining methods from queue 7.393 - method->clear_queued_for_compilation(); 7.394 - } 7.395 + invoke_compiler_on_method(task); 7.396 + } else { 7.397 + // After compilation is disabled, remove remaining methods from queue 7.398 + method->clear_queued_for_compilation(); 7.399 } 7.400 } 7.401 } 7.402 + 7.403 + // Shut down compiler runtime 7.404 + shutdown_compiler_runtime(thread->compiler(), thread); 7.405 } 7.406 7.407 - 7.408 // ------------------------------------------------------------------ 7.409 // CompileBroker::init_compiler_thread_log 7.410 // 7.411 @@ -1960,8 +2065,7 @@ 7.412 NMethodSweeper::possibly_sweep(); 7.413 } 7.414 } else { 7.415 - UseCompiler = false; 7.416 - AlwaysCompileLoopMethods = false; 7.417 + disable_compilation_forever(); 7.418 } 7.419 } 7.420 codecache_print(/* detailed= */ true);
8.1 --- a/src/share/vm/compiler/compileBroker.hpp Fri Oct 11 10:14:02 2013 -0700 8.2 +++ b/src/share/vm/compiler/compileBroker.hpp Thu Oct 10 15:44:12 2013 +0200 8.3 @@ -213,8 +213,12 @@ 8.4 8.5 // Redefine Classes support 8.6 void mark_on_stack(); 8.7 + void delete_all(); 8.8 + void print(); 8.9 8.10 - void print(); 8.11 + ~CompileQueue() { 8.12 + assert (is_empty(), " Compile Queue must be empty"); 8.13 + } 8.14 }; 8.15 8.16 // CompileTaskWrapper 8.17 @@ -266,7 +270,7 @@ 8.18 static CompileQueue* _c1_method_queue; 8.19 static CompileTask* _task_free_list; 8.20 8.21 - static GrowableArray<CompilerThread*>* _method_threads; 8.22 + static GrowableArray<CompilerThread*>* _compiler_threads; 8.23 8.24 // performance counters 8.25 static PerfCounter* _perf_total_compilation; 8.26 @@ -311,7 +315,7 @@ 8.27 static int _sum_nmethod_code_size; 8.28 static long _peak_compilation_time; 8.29 8.30 - static CompilerThread* make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, TRAPS); 8.31 + static CompilerThread* make_compiler_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, TRAPS); 8.32 static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count); 8.33 static bool compilation_is_complete (methodHandle method, int osr_bci, int comp_level); 8.34 static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level); 8.35 @@ -351,6 +355,9 @@ 8.36 if (is_c1_compile(comp_level)) return _c1_method_queue; 8.37 return NULL; 8.38 } 8.39 + static bool init_compiler_runtime(); 8.40 + static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread); 8.41 + 8.42 public: 8.43 enum { 8.44 // The entry bci used for non-OSR compilations. 8.45 @@ -378,9 +385,7 @@ 8.46 const char* comment, Thread* thread); 8.47 8.48 static void compiler_thread_loop(); 8.49 - 8.50 static uint get_compilation_id() { return _compilation_id; } 8.51 - static bool is_idle(); 8.52 8.53 // Set _should_block. 8.54 // Call this from the VM, with Threads_lock held and a safepoint requested. 8.55 @@ -391,8 +396,9 @@ 8.56 8.57 enum { 8.58 // Flags for toggling compiler activity 8.59 - stop_compilation = 0, 8.60 - run_compilation = 1 8.61 + stop_compilation = 0, 8.62 + run_compilation = 1, 8.63 + shutdown_compilaton = 2 8.64 }; 8.65 8.66 static bool should_compile_new_jobs() { return UseCompiler && (_should_compile_new_jobs == run_compilation); } 8.67 @@ -401,6 +407,16 @@ 8.68 jint old = Atomic::cmpxchg(new_state, &_should_compile_new_jobs, 1-new_state); 8.69 return (old == (1-new_state)); 8.70 } 8.71 + 8.72 + static void disable_compilation_forever() { 8.73 + UseCompiler = false; 8.74 + AlwaysCompileLoopMethods = false; 8.75 + Atomic::xchg(shutdown_compilaton, &_should_compile_new_jobs); 8.76 + } 8.77 + 8.78 + static bool is_compilation_disabled_forever() { 8.79 + return _should_compile_new_jobs == shutdown_compilaton; 8.80 + } 8.81 static void handle_full_code_cache(); 8.82 8.83 // Return total compilation ticks
9.1 --- a/src/share/vm/opto/c2compiler.cpp Fri Oct 11 10:14:02 2013 -0700 9.2 +++ b/src/share/vm/opto/c2compiler.cpp Thu Oct 10 15:44:12 2013 +0200 9.3 @@ -44,9 +44,6 @@ 9.4 # include "adfiles/ad_ppc.hpp" 9.5 #endif 9.6 9.7 - 9.8 -volatile int C2Compiler::_runtimes = uninitialized; 9.9 - 9.10 // register information defined by ADLC 9.11 extern const char register_save_policy[]; 9.12 extern const int register_save_type[]; 9.13 @@ -57,7 +54,7 @@ 9.14 const char* C2Compiler::retry_no_escape_analysis() { 9.15 return "retry without escape analysis"; 9.16 } 9.17 -void C2Compiler::initialize_runtime() { 9.18 +bool C2Compiler::init_c2_runtime() { 9.19 9.20 // Check assumptions used while running ADLC 9.21 Compile::adlc_verification(); 9.22 @@ -90,41 +87,31 @@ 9.23 9.24 CompilerThread* thread = CompilerThread::current(); 9.25 9.26 - HandleMark handle_mark(thread); 9.27 - 9.28 - OptoRuntime::generate(thread->env()); 9.29 - 9.30 + HandleMark handle_mark(thread); 9.31 + return OptoRuntime::generate(thread->env()); 9.32 } 9.33 9.34 9.35 void C2Compiler::initialize() { 9.36 - 9.37 - // This method can only be called once per C2Compiler object 9.38 // The first compiler thread that gets here will initialize the 9.39 - // small amount of global state (and runtime stubs) that c2 needs. 9.40 + // small amount of global state (and runtime stubs) that C2 needs. 9.41 9.42 // There is a race possible once at startup and then we're fine 9.43 9.44 // Note that this is being called from a compiler thread not the 9.45 // main startup thread. 9.46 - 9.47 - if (_runtimes != initialized) { 9.48 - initialize_runtimes( initialize_runtime, &_runtimes); 9.49 + if (should_perform_init()) { 9.50 + bool successful = C2Compiler::init_c2_runtime(); 9.51 + int new_state = (successful) ? initialized : failed; 9.52 + set_state(new_state); 9.53 } 9.54 - 9.55 - // Mark this compiler object as ready to roll 9.56 - mark_initialized(); 9.57 } 9.58 9.59 -void C2Compiler::compile_method(ciEnv* env, 9.60 - ciMethod* target, 9.61 - int entry_bci) { 9.62 - if (!is_initialized()) { 9.63 - initialize(); 9.64 - } 9.65 +void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) { 9.66 + assert(is_initialized(), "Compiler thread must be initialized"); 9.67 + 9.68 bool subsume_loads = SubsumeLoads; 9.69 - bool do_escape_analysis = DoEscapeAnalysis && 9.70 - !env->jvmti_can_access_local_variables(); 9.71 + bool do_escape_analysis = DoEscapeAnalysis && !env->jvmti_can_access_local_variables(); 9.72 bool eliminate_boxing = EliminateAutoBox; 9.73 while (!env->failing()) { 9.74 // Attempt to compile while subsuming loads into machine instructions.
10.1 --- a/src/share/vm/opto/c2compiler.hpp Fri Oct 11 10:14:02 2013 -0700 10.2 +++ b/src/share/vm/opto/c2compiler.hpp Thu Oct 10 15:44:12 2013 +0200 10.3 @@ -28,24 +28,17 @@ 10.4 #include "compiler/abstractCompiler.hpp" 10.5 10.6 class C2Compiler : public AbstractCompiler { 10.7 -private: 10.8 - 10.9 - static void initialize_runtime(); 10.10 + private: 10.11 + static bool init_c2_runtime(); 10.12 10.13 public: 10.14 // Name 10.15 const char *name() { return "C2"; } 10.16 10.17 - static volatile int _runtimes; 10.18 - 10.19 #ifdef TIERED 10.20 virtual bool is_c2() { return true; }; 10.21 #endif // TIERED 10.22 10.23 - // Customization 10.24 - bool needs_adapters () { return true; } 10.25 - bool needs_stubs () { return true; } 10.26 - 10.27 void initialize(); 10.28 10.29 // Compilation entry point for methods
11.1 --- a/src/share/vm/opto/runtime.cpp Fri Oct 11 10:14:02 2013 -0700 11.2 +++ b/src/share/vm/opto/runtime.cpp Thu Oct 10 15:44:12 2013 +0200 11.3 @@ -138,9 +138,10 @@ 11.4 11.5 11.6 #define gen(env, var, type_func_gen, c_func, fancy_jump, pass_tls, save_arg_regs, return_pc) \ 11.7 - var = generate_stub(env, type_func_gen, CAST_FROM_FN_PTR(address, c_func), #var, fancy_jump, pass_tls, save_arg_regs, return_pc) 11.8 + var = generate_stub(env, type_func_gen, CAST_FROM_FN_PTR(address, c_func), #var, fancy_jump, pass_tls, save_arg_regs, return_pc); \ 11.9 + if (var == NULL) { return false; } 11.10 11.11 -void OptoRuntime::generate(ciEnv* env) { 11.12 +bool OptoRuntime::generate(ciEnv* env) { 11.13 11.14 generate_exception_blob(); 11.15 11.16 @@ -158,7 +159,7 @@ 11.17 gen(env, _multianewarrayN_Java , multianewarrayN_Type , multianewarrayN_C , 0 , true , false, false); 11.18 gen(env, _g1_wb_pre_Java , g1_wb_pre_Type , SharedRuntime::g1_wb_pre , 0 , false, false, false); 11.19 gen(env, _g1_wb_post_Java , g1_wb_post_Type , SharedRuntime::g1_wb_post , 0 , false, false, false); 11.20 - gen(env, _complete_monitor_locking_Java , complete_monitor_enter_Type , SharedRuntime::complete_monitor_locking_C , 0 , false, false, false); 11.21 + gen(env, _complete_monitor_locking_Java , complete_monitor_enter_Type , SharedRuntime::complete_monitor_locking_C, 0, false, false, false); 11.22 gen(env, _rethrow_Java , rethrow_Type , rethrow_C , 2 , true , false, true ); 11.23 11.24 gen(env, _slow_arraycopy_Java , slow_arraycopy_Type , SharedRuntime::slow_arraycopy_C , 0 , false, false, false); 11.25 @@ -168,7 +169,7 @@ 11.26 gen(env, _zap_dead_Java_locals_Java , zap_dead_locals_Type , zap_dead_Java_locals_C , 0 , false, true , false ); 11.27 gen(env, _zap_dead_native_locals_Java , zap_dead_locals_Type , zap_dead_native_locals_C , 0 , false, true , false ); 11.28 # endif 11.29 - 11.30 + return true; 11.31 } 11.32 11.33 #undef gen
12.1 --- a/src/share/vm/opto/runtime.hpp Fri Oct 11 10:14:02 2013 -0700 12.2 +++ b/src/share/vm/opto/runtime.hpp Thu Oct 10 15:44:12 2013 +0200 12.3 @@ -203,8 +203,10 @@ 12.4 12.5 static bool is_callee_saved_register(MachRegisterNumbers reg); 12.6 12.7 - // One time only generate runtime code stubs 12.8 - static void generate(ciEnv* env); 12.9 + // One time only generate runtime code stubs. Returns true 12.10 + // when runtime stubs have been generated successfully and 12.11 + // false otherwise. 12.12 + static bool generate(ciEnv* env); 12.13 12.14 // Returns the name of a stub 12.15 static const char* stub_name(address entry);
13.1 --- a/src/share/vm/runtime/thread.cpp Fri Oct 11 10:14:02 2013 -0700 13.2 +++ b/src/share/vm/runtime/thread.cpp Thu Oct 10 15:44:12 2013 +0200 13.3 @@ -1454,7 +1454,6 @@ 13.4 _interp_only_mode = 0; 13.5 _special_runtime_exit_condition = _no_async_condition; 13.6 _pending_async_exception = NULL; 13.7 - _is_compiling = false; 13.8 _thread_stat = NULL; 13.9 _thread_stat = new ThreadStatistics(); 13.10 _blocked_on_compilation = false; 13.11 @@ -1815,7 +1814,8 @@ 13.12 // Call Thread.exit(). We try 3 times in case we got another Thread.stop during 13.13 // the execution of the method. If that is not enough, then we don't really care. Thread.stop 13.14 // is deprecated anyhow. 13.15 - { int count = 3; 13.16 + if (!is_Compiler_thread()) { 13.17 + int count = 3; 13.18 while (java_lang_Thread::threadGroup(threadObj()) != NULL && (count-- > 0)) { 13.19 EXCEPTION_MARK; 13.20 JavaValue result(T_VOID); 13.21 @@ -1828,7 +1828,6 @@ 13.22 CLEAR_PENDING_EXCEPTION; 13.23 } 13.24 } 13.25 - 13.26 // notify JVMTI 13.27 if (JvmtiExport::should_post_thread_life()) { 13.28 JvmtiExport::post_thread_end(this); 13.29 @@ -3239,6 +3238,7 @@ 13.30 _counters = counters; 13.31 _buffer_blob = NULL; 13.32 _scanned_nmethod = NULL; 13.33 + _compiler = NULL; 13.34 13.35 #ifndef PRODUCT 13.36 _ideal_graph_printer = NULL; 13.37 @@ -3255,6 +3255,7 @@ 13.38 } 13.39 } 13.40 13.41 + 13.42 // ======= Threads ======== 13.43 13.44 // The Threads class links together all active threads, and provides 13.45 @@ -3275,8 +3276,6 @@ 13.46 // All JavaThreads 13.47 #define ALL_JAVA_THREADS(X) for (JavaThread* X = _thread_list; X; X = X->next()) 13.48 13.49 -void os_stream(); 13.50 - 13.51 // All JavaThreads + all non-JavaThreads (i.e., every thread in the system) 13.52 void Threads::threads_do(ThreadClosure* tc) { 13.53 assert_locked_or_safepoint(Threads_lock);
14.1 --- a/src/share/vm/runtime/thread.hpp Fri Oct 11 10:14:02 2013 -0700 14.2 +++ b/src/share/vm/runtime/thread.hpp Thu Oct 10 15:44:12 2013 +0200 14.3 @@ -923,9 +923,6 @@ 14.4 volatile address _exception_handler_pc; // PC for handler of exception 14.5 volatile int _is_method_handle_return; // true (== 1) if the current exception PC is a MethodHandle call site. 14.6 14.7 - // support for compilation 14.8 - bool _is_compiling; // is true if a compilation is active inthis thread (one compilation per thread possible) 14.9 - 14.10 // support for JNI critical regions 14.11 jint _jni_active_critical; // count of entries into JNI critical region 14.12 14.13 @@ -1005,10 +1002,6 @@ 14.14 // Testers 14.15 virtual bool is_Java_thread() const { return true; } 14.16 14.17 - // compilation 14.18 - void set_is_compiling(bool f) { _is_compiling = f; } 14.19 - bool is_compiling() const { return _is_compiling; } 14.20 - 14.21 // Thread chain operations 14.22 JavaThread* next() const { return _next; } 14.23 void set_next(JavaThread* p) { _next = p; } 14.24 @@ -1816,13 +1809,14 @@ 14.25 private: 14.26 CompilerCounters* _counters; 14.27 14.28 - ciEnv* _env; 14.29 - CompileLog* _log; 14.30 - CompileTask* _task; 14.31 - CompileQueue* _queue; 14.32 - BufferBlob* _buffer_blob; 14.33 + ciEnv* _env; 14.34 + CompileLog* _log; 14.35 + CompileTask* _task; 14.36 + CompileQueue* _queue; 14.37 + BufferBlob* _buffer_blob; 14.38 14.39 - nmethod* _scanned_nmethod; // nmethod being scanned by the sweeper 14.40 + nmethod* _scanned_nmethod; // nmethod being scanned by the sweeper 14.41 + AbstractCompiler* _compiler; 14.42 14.43 public: 14.44 14.45 @@ -1834,14 +1828,17 @@ 14.46 // Hide this compiler thread from external view. 14.47 bool is_hidden_from_external_view() const { return true; } 14.48 14.49 - CompileQueue* queue() { return _queue; } 14.50 - CompilerCounters* counters() { return _counters; } 14.51 + void set_compiler(AbstractCompiler* c) { _compiler = c; } 14.52 + AbstractCompiler* compiler() const { return _compiler; } 14.53 + 14.54 + CompileQueue* queue() const { return _queue; } 14.55 + CompilerCounters* counters() const { return _counters; } 14.56 14.57 // Get/set the thread's compilation environment. 14.58 ciEnv* env() { return _env; } 14.59 void set_env(ciEnv* env) { _env = env; } 14.60 14.61 - BufferBlob* get_buffer_blob() { return _buffer_blob; } 14.62 + BufferBlob* get_buffer_blob() const { return _buffer_blob; } 14.63 void set_buffer_blob(BufferBlob* b) { _buffer_blob = b; }; 14.64 14.65 // Get/set the thread's logging information
15.1 --- a/src/share/vm/runtime/vmStructs.cpp Fri Oct 11 10:14:02 2013 -0700 15.2 +++ b/src/share/vm/runtime/vmStructs.cpp Thu Oct 10 15:44:12 2013 +0200 15.3 @@ -910,7 +910,6 @@ 15.4 volatile_nonstatic_field(JavaThread, _exception_oop, oop) \ 15.5 volatile_nonstatic_field(JavaThread, _exception_pc, address) \ 15.6 volatile_nonstatic_field(JavaThread, _is_method_handle_return, int) \ 15.7 - nonstatic_field(JavaThread, _is_compiling, bool) \ 15.8 nonstatic_field(JavaThread, _special_runtime_exit_condition, JavaThread::AsyncRequests) \ 15.9 nonstatic_field(JavaThread, _saved_exception_pc, address) \ 15.10 volatile_nonstatic_field(JavaThread, _thread_state, JavaThreadState) \
16.1 --- a/src/share/vm/shark/sharkCompiler.cpp Fri Oct 11 10:14:02 2013 -0700 16.2 +++ b/src/share/vm/shark/sharkCompiler.cpp Thu Oct 10 15:44:12 2013 +0200 16.3 @@ -133,11 +133,10 @@ 16.4 exit(1); 16.5 } 16.6 16.7 - execution_engine()->addModule( 16.8 - _native_context->module()); 16.9 + execution_engine()->addModule(_native_context->module()); 16.10 16.11 // All done 16.12 - mark_initialized(); 16.13 + set_state(initialized); 16.14 } 16.15 16.16 void SharkCompiler::initialize() {
17.1 --- a/src/share/vm/shark/sharkCompiler.hpp Fri Oct 11 10:14:02 2013 -0700 17.2 +++ b/src/share/vm/shark/sharkCompiler.hpp Thu Oct 10 15:44:12 2013 +0200 17.3 @@ -50,10 +50,6 @@ 17.4 return ! (method->is_method_handle_intrinsic() || method->is_compiled_lambda_form()); 17.5 } 17.6 17.7 - // Customization 17.8 - bool needs_adapters() { return false; } 17.9 - bool needs_stubs() { return false; } 17.10 - 17.11 // Initialization 17.12 void initialize(); 17.13
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/test/compiler/startup/SmallCodeCacheStartup.java Thu Oct 10 15:44:12 2013 +0200 18.3 @@ -0,0 +1,43 @@ 18.4 +/* 18.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 18.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 18.7 + * 18.8 + * This code is free software; you can redistribute it and/or modify it 18.9 + * under the terms of the GNU General Public License version 2 only, as 18.10 + * published by the Free Software Foundation. 18.11 + * 18.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 18.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 18.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18.15 + * version 2 for more details (a copy is included in the LICENSE file that 18.16 + * accompanied this code). 18.17 + * 18.18 + * You should have received a copy of the GNU General Public License version 18.19 + * 2 along with this work; if not, write to the Free Software Foundation, 18.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18.21 + * 18.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 18.23 + * or visit www.oracle.com if you need additional information or have any 18.24 + * questions. 18.25 + */ 18.26 + 18.27 +/* 18.28 + * @test 18.29 + * @bug 8023014 18.30 + * @summary Test ensures that there is no crash when compiler initialization fails 18.31 + * @library /testlibrary 18.32 + * 18.33 + */ 18.34 +import com.oracle.java.testlibrary.*; 18.35 + 18.36 +public class SmallCodeCacheStartup { 18.37 + public static void main(String[] args) throws Exception { 18.38 + ProcessBuilder pb; 18.39 + OutputAnalyzer out; 18.40 + 18.41 + pb = ProcessTools.createJavaProcessBuilder("-XX:ReservedCodeCacheSize=3m", "-XX:CICompilerCount=64", "-version"); 18.42 + out = new OutputAnalyzer(pb.start()); 18.43 + out.shouldContain("no space to run compiler"); 18.44 + out.shouldHaveExitValue(0); 18.45 + } 18.46 +}