Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/shark/sharkCompiler.cpp
32285 views
1
/*
2
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3
* Copyright 2008, 2009, 2010, 2011 Red Hat, Inc.
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
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"
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
73
// MCJIT require a native AsmPrinter
74
InitializeNativeTargetAsmPrinter();
75
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);
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 :-)
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
136
execution_engine()->addModule(_native_context->module());
137
138
// All done
139
set_state(initialized);
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);
187
if (env->failing()) {
188
return;
189
}
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,
226
int compile_id,
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,
250
compile_id,
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
269
if (SharkVerifyFunction != NULL) {
270
if (!fnmatch(SharkVerifyFunction, name, 0)) {
271
verifyFunction(*function);
272
}
273
}
274
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
282
#ifndef NDEBUG
283
#if SHARK_LLVM_VERSION <= 31
284
#define setCurrentDebugType SetCurrentDebugType
285
#endif
286
if (SharkPrintAsmOf != NULL) {
287
if (!fnmatch(SharkPrintAsmOf, name, 0)) {
288
llvm::setCurrentDebugType(X86_ONLY("x86-emitter") NOT_X86("jit"));
289
llvm::DebugFlag = true;
290
}
291
else {
292
llvm::setCurrentDebugType("");
293
llvm::DebugFlag = false;
294
}
295
}
296
#ifdef setCurrentDebugType
297
#undef setCurrentDebugType
298
#endif
299
#endif // !NDEBUG
300
memory_manager()->set_entry_for_function(function, entry);
301
code = (address) execution_engine()->getPointerToFunction(function);
302
}
303
assert(code != NULL, "code must be != NULL");
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.
328
assert(Thread::current()->is_Compiler_thread(), "must be called by compiler thread");
329
assert_locked_or_safepoint(CodeCache_lock);
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
}
367
368