Mercurial > hg > truffle
annotate src/share/vm/shark/sharkCompiler.cpp @ 17716:cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | 55fb97c4c58d |
children | 16e101c8691f |
rev | line source |
---|---|
1692 | 1 /* |
17467
55fb97c4c58d
8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents:
12880
diff
changeset
|
2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. |
2447 | 3 * Copyright 2008, 2009, 2010, 2011 Red Hat, Inc. |
1692 | 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
5 * | |
6 * This code is free software; you can redistribute it and/or modify it | |
7 * under the terms of the GNU General Public License version 2 only, as | |
8 * published by the Free Software Foundation. | |
9 * | |
10 * This code is distributed in the hope that it will be useful, but WITHOUT | |
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
13 * version 2 for more details (a copy is included in the LICENSE file that | |
14 * accompanied this code). | |
15 * | |
16 * You should have received a copy of the GNU General Public License version | |
17 * 2 along with this work; if not, write to the Free Software Foundation, | |
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
19 * | |
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
21 * or visit www.oracle.com if you need additional information or have any | |
22 * questions. | |
23 * | |
24 */ | |
25 | |
1972 | 26 #include "precompiled.hpp" |
27 #include "ci/ciEnv.hpp" | |
28 #include "ci/ciMethod.hpp" | |
29 #include "code/debugInfoRec.hpp" | |
30 #include "code/dependencies.hpp" | |
31 #include "code/exceptionHandlerTable.hpp" | |
32 #include "code/oopRecorder.hpp" | |
33 #include "compiler/abstractCompiler.hpp" | |
34 #include "compiler/oopMap.hpp" | |
35 #include "shark/llvmHeaders.hpp" | |
36 #include "shark/sharkBuilder.hpp" | |
37 #include "shark/sharkCodeBuffer.hpp" | |
38 #include "shark/sharkCompiler.hpp" | |
39 #include "shark/sharkContext.hpp" | |
40 #include "shark/sharkEntry.hpp" | |
41 #include "shark/sharkFunction.hpp" | |
42 #include "shark/sharkMemoryManager.hpp" | |
43 #include "shark/sharkNativeWrapper.hpp" | |
44 #include "shark/shark_globals.hpp" | |
45 #include "utilities/debug.hpp" | |
1692 | 46 |
47 #include <fnmatch.h> | |
48 | |
49 using namespace llvm; | |
50 | |
51 namespace { | |
52 cl::opt<std::string> | |
53 MCPU("mcpu"); | |
54 | |
55 cl::list<std::string> | |
56 MAttrs("mattr", | |
57 cl::CommaSeparated); | |
58 } | |
59 | |
60 SharkCompiler::SharkCompiler() | |
61 : AbstractCompiler() { | |
62 // Create the lock to protect the memory manager and execution engine | |
63 _execution_engine_lock = new Monitor(Mutex::leaf, "SharkExecutionEngineLock"); | |
64 MutexLocker locker(execution_engine_lock()); | |
65 | |
66 // Make LLVM safe for multithreading | |
67 if (!llvm_start_multithreaded()) | |
68 fatal("llvm_start_multithreaded() failed"); | |
69 | |
70 // Initialize the native target | |
71 InitializeNativeTarget(); | |
72 | |
7195 | 73 // MCJIT require a native AsmPrinter |
74 InitializeNativeTargetAsmPrinter(); | |
75 | |
1692 | 76 // Create the two contexts which we'll use |
77 _normal_context = new SharkContext("normal"); | |
78 _native_context = new SharkContext("native"); | |
79 | |
80 // Create the memory manager | |
81 _memory_manager = new SharkMemoryManager(); | |
82 | |
83 // Finetune LLVM for the current host CPU. | |
84 StringMap<bool> Features; | |
85 bool gotCpuFeatures = llvm::sys::getHostCPUFeatures(Features); | |
86 std::string cpu("-mcpu=" + llvm::sys::getHostCPUName()); | |
87 | |
88 std::vector<const char*> args; | |
89 args.push_back(""); // program name | |
90 args.push_back(cpu.c_str()); | |
91 | |
92 std::string mattr("-mattr="); | |
93 if(gotCpuFeatures){ | |
94 for(StringMap<bool>::iterator I = Features.begin(), | |
95 E = Features.end(); I != E; ++I){ | |
96 if(I->second){ | |
97 std::string attr(I->first()); | |
98 mattr+="+"+attr+","; | |
99 } | |
100 } | |
101 args.push_back(mattr.c_str()); | |
102 } | |
103 | |
104 args.push_back(0); // terminator | |
105 cl::ParseCommandLineOptions(args.size() - 1, (char **) &args[0]); | |
106 | |
107 // Create the JIT | |
108 std::string ErrorMsg; | |
109 | |
110 EngineBuilder builder(_normal_context->module()); | |
111 builder.setMCPU(MCPU); | |
112 builder.setMAttrs(MAttrs); | |
113 builder.setJITMemoryManager(memory_manager()); | |
114 builder.setEngineKind(EngineKind::JIT); | |
115 builder.setErrorStr(&ErrorMsg); | |
7195 | 116 if (! fnmatch(SharkOptimizationLevel, "None", 0)) { |
117 tty->print_cr("Shark optimization level set to: None"); | |
118 builder.setOptLevel(llvm::CodeGenOpt::None); | |
119 } else if (! fnmatch(SharkOptimizationLevel, "Less", 0)) { | |
120 tty->print_cr("Shark optimization level set to: Less"); | |
121 builder.setOptLevel(llvm::CodeGenOpt::Less); | |
122 } else if (! fnmatch(SharkOptimizationLevel, "Aggressive", 0)) { | |
123 tty->print_cr("Shark optimization level set to: Aggressive"); | |
124 builder.setOptLevel(llvm::CodeGenOpt::Aggressive); | |
125 } // else Default is selected by, well, default :-) | |
1692 | 126 _execution_engine = builder.create(); |
127 | |
128 if (!execution_engine()) { | |
129 if (!ErrorMsg.empty()) | |
130 printf("Error while creating Shark JIT: %s\n",ErrorMsg.c_str()); | |
131 else | |
132 printf("Unknown error while creating Shark JIT\n"); | |
133 exit(1); | |
134 } | |
135 | |
12880
469216acdb28
8023014: CodeSweeperSweepNoFlushTest.java fails with HS crash
anoll
parents:
7600
diff
changeset
|
136 execution_engine()->addModule(_native_context->module()); |
1692 | 137 |
138 // All done | |
12880
469216acdb28
8023014: CodeSweeperSweepNoFlushTest.java fails with HS crash
anoll
parents:
7600
diff
changeset
|
139 set_state(initialized); |
1692 | 140 } |
141 | |
142 void SharkCompiler::initialize() { | |
143 ShouldNotCallThis(); | |
144 } | |
145 | |
146 void SharkCompiler::compile_method(ciEnv* env, | |
147 ciMethod* target, | |
148 int entry_bci) { | |
149 assert(is_initialized(), "should be"); | |
150 ResourceMark rm; | |
151 const char *name = methodname( | |
152 target->holder()->name()->as_utf8(), target->name()->as_utf8()); | |
153 | |
154 // Do the typeflow analysis | |
155 ciTypeFlow *flow; | |
156 if (entry_bci == InvocationEntryBci) | |
157 flow = target->get_flow_analysis(); | |
158 else | |
159 flow = target->get_osr_flow_analysis(entry_bci); | |
160 if (flow->failing()) | |
161 return; | |
162 if (SharkPrintTypeflowOf != NULL) { | |
163 if (!fnmatch(SharkPrintTypeflowOf, name, 0)) | |
164 flow->print_on(tty); | |
165 } | |
166 | |
167 // Create the recorders | |
168 Arena arena; | |
169 env->set_oop_recorder(new OopRecorder(&arena)); | |
170 OopMapSet oopmaps; | |
171 env->set_debug_info(new DebugInformationRecorder(env->oop_recorder())); | |
172 env->debug_info()->set_oopmaps(&oopmaps); | |
173 env->set_dependencies(new Dependencies(env)); | |
174 | |
175 // Create the code buffer and builder | |
176 CodeBuffer hscb("Shark", 256 * K, 64 * K); | |
177 hscb.initialize_oop_recorder(env->oop_recorder()); | |
178 MacroAssembler *masm = new MacroAssembler(&hscb); | |
179 SharkCodeBuffer cb(masm); | |
180 SharkBuilder builder(&cb); | |
181 | |
182 // Emit the entry point | |
183 SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry)); | |
184 | |
185 // Build the LLVM IR for the method | |
186 Function *function = SharkFunction::build(env, &builder, flow, name); | |
7600
c095a7f289aa
8005818: Shark: fix OSR for non-empty incoming stack
twisti
parents:
7195
diff
changeset
|
187 if (env->failing()) { |
c095a7f289aa
8005818: Shark: fix OSR for non-empty incoming stack
twisti
parents:
7195
diff
changeset
|
188 return; |
c095a7f289aa
8005818: Shark: fix OSR for non-empty incoming stack
twisti
parents:
7195
diff
changeset
|
189 } |
1692 | 190 |
191 // Generate native code. It's unpleasant that we have to drop into | |
192 // the VM to do this -- it blocks safepoints -- but I can't see any | |
193 // other way to handle the locking. | |
194 { | |
195 ThreadInVMfromNative tiv(JavaThread::current()); | |
196 generate_native_code(entry, function, name); | |
197 } | |
198 | |
199 // Install the method into the VM | |
200 CodeOffsets offsets; | |
201 offsets.set_value(CodeOffsets::Deopt, 0); | |
202 offsets.set_value(CodeOffsets::Exceptions, 0); | |
203 offsets.set_value(CodeOffsets::Verified_Entry, | |
204 target->is_static() ? 0 : wordSize); | |
205 | |
206 ExceptionHandlerTable handler_table; | |
207 ImplicitExceptionTable inc_table; | |
208 | |
209 env->register_method(target, | |
210 entry_bci, | |
211 &offsets, | |
212 0, | |
213 &hscb, | |
214 0, | |
215 &oopmaps, | |
216 &handler_table, | |
217 &inc_table, | |
218 this, | |
219 env->comp_level(), | |
220 false, | |
221 false); | |
222 } | |
223 | |
224 nmethod* SharkCompiler::generate_native_wrapper(MacroAssembler* masm, | |
225 methodHandle target, | |
2447 | 226 int compile_id, |
1692 | 227 BasicType* arg_types, |
228 BasicType return_type) { | |
229 assert(is_initialized(), "should be"); | |
230 ResourceMark rm; | |
231 const char *name = methodname( | |
232 target->klass_name()->as_utf8(), target->name()->as_utf8()); | |
233 | |
234 // Create the code buffer and builder | |
235 SharkCodeBuffer cb(masm); | |
236 SharkBuilder builder(&cb); | |
237 | |
238 // Emit the entry point | |
239 SharkEntry *entry = (SharkEntry *) cb.malloc(sizeof(SharkEntry)); | |
240 | |
241 // Build the LLVM IR for the method | |
242 SharkNativeWrapper *wrapper = SharkNativeWrapper::build( | |
243 &builder, target, name, arg_types, return_type); | |
244 | |
245 // Generate native code | |
246 generate_native_code(entry, wrapper->function(), name); | |
247 | |
248 // Return the nmethod for installation in the VM | |
249 return nmethod::new_native_nmethod(target, | |
2447 | 250 compile_id, |
1692 | 251 masm->code(), |
252 0, | |
253 0, | |
254 wrapper->frame_size(), | |
255 wrapper->receiver_offset(), | |
256 wrapper->lock_offset(), | |
257 wrapper->oop_maps()); | |
258 } | |
259 | |
260 void SharkCompiler::generate_native_code(SharkEntry* entry, | |
261 Function* function, | |
262 const char* name) { | |
263 // Print the LLVM bitcode, if requested | |
264 if (SharkPrintBitcodeOf != NULL) { | |
265 if (!fnmatch(SharkPrintBitcodeOf, name, 0)) | |
266 function->dump(); | |
267 } | |
268 | |
7195 | 269 if (SharkVerifyFunction != NULL) { |
270 if (!fnmatch(SharkVerifyFunction, name, 0)) { | |
271 verifyFunction(*function); | |
272 } | |
273 } | |
274 | |
1692 | 275 // Compile to native code |
276 address code = NULL; | |
277 context()->add_function(function); | |
278 { | |
279 MutexLocker locker(execution_engine_lock()); | |
280 free_queued_methods(); | |
281 | |
7195 | 282 #ifndef NDEBUG |
283 #if SHARK_LLVM_VERSION <= 31 | |
284 #define setCurrentDebugType SetCurrentDebugType | |
285 #endif | |
1692 | 286 if (SharkPrintAsmOf != NULL) { |
287 if (!fnmatch(SharkPrintAsmOf, name, 0)) { | |
7195 | 288 llvm::setCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit")); |
1692 | 289 llvm::DebugFlag = true; |
290 } | |
291 else { | |
7195 | 292 llvm::setCurrentDebugType(""); |
1692 | 293 llvm::DebugFlag = false; |
294 } | |
7195 | 295 } |
296 #ifdef setCurrentDebugType | |
297 #undef setCurrentDebugType | |
298 #endif | |
1692 | 299 #endif // !NDEBUG |
300 memory_manager()->set_entry_for_function(function, entry); | |
301 code = (address) execution_engine()->getPointerToFunction(function); | |
302 } | |
7195 | 303 assert(code != NULL, "code must be != NULL"); |
1692 | 304 entry->set_entry_point(code); |
305 entry->set_function(function); | |
306 entry->set_context(context()); | |
307 address code_start = entry->code_start(); | |
308 address code_limit = entry->code_limit(); | |
309 | |
310 // Register generated code for profiling, etc | |
311 if (JvmtiExport::should_post_dynamic_code_generated()) | |
312 JvmtiExport::post_dynamic_code_generated(name, code_start, code_limit); | |
313 | |
314 // Print debug information, if requested | |
315 if (SharkTraceInstalls) { | |
316 tty->print_cr( | |
317 " [%p-%p): %s (%d bytes code)", | |
318 code_start, code_limit, name, code_limit - code_start); | |
319 } | |
320 } | |
321 | |
322 void SharkCompiler::free_compiled_method(address code) { | |
323 // This method may only be called when the VM is at a safepoint. | |
324 // All _thread_in_vm threads will be waiting for the safepoint to | |
325 // finish with the exception of the VM thread, so we can consider | |
326 // ourself the owner of the execution engine lock even though we | |
327 // can't actually acquire it at this time. | |
7195 | 328 assert(Thread::current()->is_Compiler_thread(), "must be called by compiler thread"); |
329 assert_locked_or_safepoint(CodeCache_lock); | |
1692 | 330 |
331 SharkEntry *entry = (SharkEntry *) code; | |
332 entry->context()->push_to_free_queue(entry->function()); | |
333 } | |
334 | |
335 void SharkCompiler::free_queued_methods() { | |
336 // The free queue is protected by the execution engine lock | |
337 assert(execution_engine_lock()->owned_by_self(), "should be"); | |
338 | |
339 while (true) { | |
340 Function *function = context()->pop_from_free_queue(); | |
341 if (function == NULL) | |
342 break; | |
343 | |
344 execution_engine()->freeMachineCodeForFunction(function); | |
345 function->eraseFromParent(); | |
346 } | |
347 } | |
348 | |
349 const char* SharkCompiler::methodname(const char* klass, const char* method) { | |
350 char *buf = NEW_RESOURCE_ARRAY(char, strlen(klass) + 2 + strlen(method) + 1); | |
351 | |
352 char *dst = buf; | |
353 for (const char *c = klass; *c; c++) { | |
354 if (*c == '/') | |
355 *(dst++) = '.'; | |
356 else | |
357 *(dst++) = *c; | |
358 } | |
359 *(dst++) = ':'; | |
360 *(dst++) = ':'; | |
361 for (const char *c = method; *c; c++) { | |
362 *(dst++) = *c; | |
363 } | |
364 *(dst++) = '\0'; | |
365 return buf; | |
366 } |