Mercurial > hg > truffle
comparison src/share/vm/shark/sharkBuilder.cpp @ 1692:d2ede61b7a12
6976186: integrate Shark HotSpot changes
Summary: Shark is a JIT compiler for Zero that uses the LLVM compiler infrastructure.
Reviewed-by: kvn, twisti
Contributed-by: Gary Benson <gbenson@redhat.com>
author | twisti |
---|---|
date | Wed, 11 Aug 2010 05:51:21 -0700 |
parents | |
children | f95d63e2154a |
comparison
equal
deleted
inserted
replaced
1691:4a665be40fd3 | 1692:d2ede61b7a12 |
---|---|
1 /* | |
2 * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. | |
3 * Copyright 2008, 2009, 2010 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 "incls/_precompiled.incl" | |
27 #include "incls/_sharkBuilder.cpp.incl" | |
28 | |
29 using namespace llvm; | |
30 | |
31 SharkBuilder::SharkBuilder(SharkCodeBuffer* code_buffer) | |
32 : IRBuilder<>(SharkContext::current()), | |
33 _code_buffer(code_buffer) { | |
34 } | |
35 | |
36 // Helpers for accessing structures | |
37 Value* SharkBuilder::CreateAddressOfStructEntry(Value* base, | |
38 ByteSize offset, | |
39 const Type* type, | |
40 const char* name) { | |
41 return CreateBitCast(CreateStructGEP(base, in_bytes(offset)), type, name); | |
42 } | |
43 | |
44 LoadInst* SharkBuilder::CreateValueOfStructEntry(Value* base, | |
45 ByteSize offset, | |
46 const Type* type, | |
47 const char* name) { | |
48 return CreateLoad( | |
49 CreateAddressOfStructEntry( | |
50 base, offset, PointerType::getUnqual(type)), | |
51 name); | |
52 } | |
53 | |
54 // Helpers for accessing arrays | |
55 | |
56 LoadInst* SharkBuilder::CreateArrayLength(Value* arrayoop) { | |
57 return CreateValueOfStructEntry( | |
58 arrayoop, in_ByteSize(arrayOopDesc::length_offset_in_bytes()), | |
59 SharkType::jint_type(), "length"); | |
60 } | |
61 | |
62 Value* SharkBuilder::CreateArrayAddress(Value* arrayoop, | |
63 const Type* element_type, | |
64 int element_bytes, | |
65 ByteSize base_offset, | |
66 Value* index, | |
67 const char* name) { | |
68 Value* offset = CreateIntCast(index, SharkType::intptr_type(), false); | |
69 if (element_bytes != 1) | |
70 offset = CreateShl( | |
71 offset, | |
72 LLVMValue::intptr_constant(exact_log2(element_bytes))); | |
73 offset = CreateAdd( | |
74 LLVMValue::intptr_constant(in_bytes(base_offset)), offset); | |
75 | |
76 return CreateIntToPtr( | |
77 CreateAdd(CreatePtrToInt(arrayoop, SharkType::intptr_type()), offset), | |
78 PointerType::getUnqual(element_type), | |
79 name); | |
80 } | |
81 | |
82 Value* SharkBuilder::CreateArrayAddress(Value* arrayoop, | |
83 BasicType basic_type, | |
84 ByteSize base_offset, | |
85 Value* index, | |
86 const char* name) { | |
87 return CreateArrayAddress( | |
88 arrayoop, | |
89 SharkType::to_arrayType(basic_type), | |
90 type2aelembytes(basic_type), | |
91 base_offset, index, name); | |
92 } | |
93 | |
94 Value* SharkBuilder::CreateArrayAddress(Value* arrayoop, | |
95 BasicType basic_type, | |
96 Value* index, | |
97 const char* name) { | |
98 return CreateArrayAddress( | |
99 arrayoop, basic_type, | |
100 in_ByteSize(arrayOopDesc::base_offset_in_bytes(basic_type)), | |
101 index, name); | |
102 } | |
103 | |
104 // Helpers for creating intrinsics and external functions. | |
105 | |
106 const Type* SharkBuilder::make_type(char type, bool void_ok) { | |
107 switch (type) { | |
108 // Primitive types | |
109 case 'c': | |
110 return SharkType::jbyte_type(); | |
111 case 'i': | |
112 return SharkType::jint_type(); | |
113 case 'l': | |
114 return SharkType::jlong_type(); | |
115 case 'x': | |
116 return SharkType::intptr_type(); | |
117 case 'f': | |
118 return SharkType::jfloat_type(); | |
119 case 'd': | |
120 return SharkType::jdouble_type(); | |
121 | |
122 // Pointers to primitive types | |
123 case 'C': | |
124 case 'I': | |
125 case 'L': | |
126 case 'X': | |
127 case 'F': | |
128 case 'D': | |
129 return PointerType::getUnqual(make_type(tolower(type), false)); | |
130 | |
131 // VM objects | |
132 case 'T': | |
133 return SharkType::thread_type(); | |
134 case 'M': | |
135 return PointerType::getUnqual(SharkType::monitor_type()); | |
136 case 'O': | |
137 return SharkType::oop_type(); | |
138 | |
139 // Miscellaneous | |
140 case 'v': | |
141 assert(void_ok, "should be"); | |
142 return SharkType::void_type(); | |
143 case '1': | |
144 return SharkType::bit_type(); | |
145 | |
146 default: | |
147 ShouldNotReachHere(); | |
148 } | |
149 } | |
150 | |
151 const FunctionType* SharkBuilder::make_ftype(const char* params, | |
152 const char* ret) { | |
153 std::vector<const Type*> param_types; | |
154 for (const char* c = params; *c; c++) | |
155 param_types.push_back(make_type(*c, false)); | |
156 | |
157 assert(strlen(ret) == 1, "should be"); | |
158 const Type *return_type = make_type(*ret, true); | |
159 | |
160 return FunctionType::get(return_type, param_types, false); | |
161 } | |
162 | |
163 // Create an object representing an intrinsic or external function by | |
164 // referencing the symbol by name. This is the LLVM-style approach, | |
165 // but it cannot be used on functions within libjvm.so its symbols | |
166 // are not exported. Note that you cannot make this work simply by | |
167 // exporting the symbols, as some symbols have the same names as | |
168 // symbols in the standard libraries (eg, atan2, fabs) and would | |
169 // obscure them were they visible. | |
170 Value* SharkBuilder::make_function(const char* name, | |
171 const char* params, | |
172 const char* ret) { | |
173 return SharkContext::current().get_external(name, make_ftype(params, ret)); | |
174 } | |
175 | |
176 // Create an object representing an external function by inlining a | |
177 // function pointer in the code. This is not the LLVM way, but it's | |
178 // the only way to access functions in libjvm.so and functions like | |
179 // __kernel_dmb on ARM which is accessed via an absolute address. | |
180 Value* SharkBuilder::make_function(address func, | |
181 const char* params, | |
182 const char* ret) { | |
183 return CreateIntToPtr( | |
184 LLVMValue::intptr_constant((intptr_t) func), | |
185 PointerType::getUnqual(make_ftype(params, ret))); | |
186 } | |
187 | |
188 // VM calls | |
189 | |
190 Value* SharkBuilder::find_exception_handler() { | |
191 return make_function( | |
192 (address) SharkRuntime::find_exception_handler, "TIi", "i"); | |
193 } | |
194 | |
195 Value* SharkBuilder::monitorenter() { | |
196 return make_function((address) SharkRuntime::monitorenter, "TM", "v"); | |
197 } | |
198 | |
199 Value* SharkBuilder::monitorexit() { | |
200 return make_function((address) SharkRuntime::monitorexit, "TM", "v"); | |
201 } | |
202 | |
203 Value* SharkBuilder::new_instance() { | |
204 return make_function((address) SharkRuntime::new_instance, "Ti", "v"); | |
205 } | |
206 | |
207 Value* SharkBuilder::newarray() { | |
208 return make_function((address) SharkRuntime::newarray, "Tii", "v"); | |
209 } | |
210 | |
211 Value* SharkBuilder::anewarray() { | |
212 return make_function((address) SharkRuntime::anewarray, "Tii", "v"); | |
213 } | |
214 | |
215 Value* SharkBuilder::multianewarray() { | |
216 return make_function((address) SharkRuntime::multianewarray, "TiiI", "v"); | |
217 } | |
218 | |
219 Value* SharkBuilder::register_finalizer() { | |
220 return make_function((address) SharkRuntime::register_finalizer, "TO", "v"); | |
221 } | |
222 | |
223 Value* SharkBuilder::safepoint() { | |
224 return make_function((address) SafepointSynchronize::block, "T", "v"); | |
225 } | |
226 | |
227 Value* SharkBuilder::throw_ArithmeticException() { | |
228 return make_function( | |
229 (address) SharkRuntime::throw_ArithmeticException, "TCi", "v"); | |
230 } | |
231 | |
232 Value* SharkBuilder::throw_ArrayIndexOutOfBoundsException() { | |
233 return make_function( | |
234 (address) SharkRuntime::throw_ArrayIndexOutOfBoundsException, "TCii", "v"); | |
235 } | |
236 | |
237 Value* SharkBuilder::throw_ClassCastException() { | |
238 return make_function( | |
239 (address) SharkRuntime::throw_ClassCastException, "TCi", "v"); | |
240 } | |
241 | |
242 Value* SharkBuilder::throw_NullPointerException() { | |
243 return make_function( | |
244 (address) SharkRuntime::throw_NullPointerException, "TCi", "v"); | |
245 } | |
246 | |
247 // High-level non-VM calls | |
248 | |
249 Value* SharkBuilder::f2i() { | |
250 return make_function((address) SharedRuntime::f2i, "f", "i"); | |
251 } | |
252 | |
253 Value* SharkBuilder::f2l() { | |
254 return make_function((address) SharedRuntime::f2l, "f", "l"); | |
255 } | |
256 | |
257 Value* SharkBuilder::d2i() { | |
258 return make_function((address) SharedRuntime::d2i, "d", "i"); | |
259 } | |
260 | |
261 Value* SharkBuilder::d2l() { | |
262 return make_function((address) SharedRuntime::d2l, "d", "l"); | |
263 } | |
264 | |
265 Value* SharkBuilder::is_subtype_of() { | |
266 return make_function((address) SharkRuntime::is_subtype_of, "OO", "c"); | |
267 } | |
268 | |
269 Value* SharkBuilder::current_time_millis() { | |
270 return make_function((address) os::javaTimeMillis, "", "l"); | |
271 } | |
272 | |
273 Value* SharkBuilder::sin() { | |
274 return make_function("llvm.sin.f64", "d", "d"); | |
275 } | |
276 | |
277 Value* SharkBuilder::cos() { | |
278 return make_function("llvm.cos.f64", "d", "d"); | |
279 } | |
280 | |
281 Value* SharkBuilder::tan() { | |
282 return make_function((address) ::tan, "d", "d"); | |
283 } | |
284 | |
285 Value* SharkBuilder::atan2() { | |
286 return make_function((address) ::atan2, "dd", "d"); | |
287 } | |
288 | |
289 Value* SharkBuilder::sqrt() { | |
290 return make_function("llvm.sqrt.f64", "d", "d"); | |
291 } | |
292 | |
293 Value* SharkBuilder::log() { | |
294 return make_function("llvm.log.f64", "d", "d"); | |
295 } | |
296 | |
297 Value* SharkBuilder::log10() { | |
298 return make_function("llvm.log10.f64", "d", "d"); | |
299 } | |
300 | |
301 Value* SharkBuilder::pow() { | |
302 return make_function("llvm.pow.f64", "dd", "d"); | |
303 } | |
304 | |
305 Value* SharkBuilder::exp() { | |
306 return make_function("llvm.exp.f64", "d", "d"); | |
307 } | |
308 | |
309 Value* SharkBuilder::fabs() { | |
310 return make_function((address) ::fabs, "d", "d"); | |
311 } | |
312 | |
313 Value* SharkBuilder::unsafe_field_offset_to_byte_offset() { | |
314 extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); | |
315 return make_function((address) Unsafe_field_offset_to_byte_offset, "l", "l"); | |
316 } | |
317 | |
318 Value* SharkBuilder::osr_migration_end() { | |
319 return make_function((address) SharedRuntime::OSR_migration_end, "C", "v"); | |
320 } | |
321 | |
322 // Semi-VM calls | |
323 | |
324 Value* SharkBuilder::throw_StackOverflowError() { | |
325 return make_function((address) ZeroStack::handle_overflow, "T", "v"); | |
326 } | |
327 | |
328 Value* SharkBuilder::uncommon_trap() { | |
329 return make_function((address) SharkRuntime::uncommon_trap, "Ti", "i"); | |
330 } | |
331 | |
332 Value* SharkBuilder::deoptimized_entry_point() { | |
333 return make_function((address) CppInterpreter::main_loop, "iT", "v"); | |
334 } | |
335 | |
336 // Native-Java transition | |
337 | |
338 Value* SharkBuilder::check_special_condition_for_native_trans() { | |
339 return make_function( | |
340 (address) JavaThread::check_special_condition_for_native_trans, | |
341 "T", "v"); | |
342 } | |
343 | |
344 // Low-level non-VM calls | |
345 | |
346 // The ARM-specific code here is to work around unimplemented | |
347 // atomic exchange and memory barrier intrinsics in LLVM. | |
348 // | |
349 // Delegating to external functions for these would normally | |
350 // incur a speed penalty, but Linux on ARM is a special case | |
351 // in that atomic operations on that platform are handled by | |
352 // external functions anyway. It would be *preferable* for | |
353 // the calls to be hidden away in LLVM, but it's not hurting | |
354 // performance so having the calls here is acceptable. | |
355 // | |
356 // If you are building Shark on a platform without atomic | |
357 // exchange and/or memory barrier intrinsics then it is only | |
358 // acceptable to mimic this approach if your platform cannot | |
359 // perform these operations without delegating to a function. | |
360 | |
361 #ifdef ARM | |
362 static jint zero_cmpxchg_int(volatile jint *ptr, jint oldval, jint newval) { | |
363 return Atomic::cmpxchg(newval, ptr, oldval); | |
364 } | |
365 #endif // ARM | |
366 | |
367 Value* SharkBuilder::cmpxchg_int() { | |
368 return make_function( | |
369 #ifdef ARM | |
370 (address) zero_cmpxchg_int, | |
371 #else | |
372 "llvm.atomic.cmp.swap.i32.p0i32", | |
373 #endif // ARM | |
374 "Iii", "i"); | |
375 } | |
376 | |
377 #ifdef ARM | |
378 static intptr_t zero_cmpxchg_ptr(volatile intptr_t* ptr, | |
379 intptr_t oldval, | |
380 intptr_t newval) { | |
381 return Atomic::cmpxchg_ptr(newval, ptr, oldval); | |
382 } | |
383 #endif // ARM | |
384 | |
385 Value* SharkBuilder::cmpxchg_ptr() { | |
386 return make_function( | |
387 #ifdef ARM | |
388 (address) zero_cmpxchg_ptr, | |
389 #else | |
390 "llvm.atomic.cmp.swap.i" LP64_ONLY("64") NOT_LP64("32") ".p0i" LP64_ONLY("64") NOT_LP64("32"), | |
391 #endif // ARM | |
392 "Xxx", "x"); | |
393 } | |
394 | |
395 Value* SharkBuilder::frame_address() { | |
396 return make_function("llvm.frameaddress", "i", "C"); | |
397 } | |
398 | |
399 Value* SharkBuilder::memory_barrier() { | |
400 return make_function( | |
401 #ifdef ARM | |
402 (address) 0xffff0fa0, // __kernel_dmb | |
403 #else | |
404 "llvm.memory.barrier", | |
405 #endif // ARM | |
406 "11111", "v"); | |
407 } | |
408 | |
409 Value* SharkBuilder::memset() { | |
410 #if SHARK_LLVM_VERSION >= 28 | |
411 // LLVM 2.8 added a fifth isVolatile field for memset | |
412 // introduced with LLVM r100304 | |
413 return make_function("llvm.memset.i32", "Cciii", "v"); | |
414 #else | |
415 return make_function("llvm.memset.i32", "Ccii", "v"); | |
416 #endif | |
417 } | |
418 | |
419 Value* SharkBuilder::unimplemented() { | |
420 return make_function((address) report_unimplemented, "Ci", "v"); | |
421 } | |
422 | |
423 Value* SharkBuilder::should_not_reach_here() { | |
424 return make_function((address) report_should_not_reach_here, "Ci", "v"); | |
425 } | |
426 | |
427 Value* SharkBuilder::dump() { | |
428 return make_function((address) SharkRuntime::dump, "Cx", "v"); | |
429 } | |
430 | |
431 // Public interface to low-level non-VM calls | |
432 | |
433 CallInst* SharkBuilder::CreateCmpxchgInt(Value* exchange_value, | |
434 Value* dst, | |
435 Value* compare_value) { | |
436 return CreateCall3(cmpxchg_int(), dst, compare_value, exchange_value); | |
437 } | |
438 | |
439 CallInst* SharkBuilder::CreateCmpxchgPtr(Value* exchange_value, | |
440 Value* dst, | |
441 Value* compare_value) { | |
442 return CreateCall3(cmpxchg_ptr(), dst, compare_value, exchange_value); | |
443 } | |
444 | |
445 CallInst* SharkBuilder::CreateGetFrameAddress() { | |
446 return CreateCall(frame_address(), LLVMValue::jint_constant(0)); | |
447 } | |
448 | |
449 CallInst *SharkBuilder::CreateMemoryBarrier(int flags) { | |
450 Value *args[] = { | |
451 LLVMValue::bit_constant((flags & BARRIER_LOADLOAD) ? 1 : 0), | |
452 LLVMValue::bit_constant((flags & BARRIER_LOADSTORE) ? 1 : 0), | |
453 LLVMValue::bit_constant((flags & BARRIER_STORELOAD) ? 1 : 0), | |
454 LLVMValue::bit_constant((flags & BARRIER_STORESTORE) ? 1 : 0), | |
455 LLVMValue::bit_constant(1)}; | |
456 | |
457 return CreateCall(memory_barrier(), args, args + 5); | |
458 } | |
459 | |
460 CallInst* SharkBuilder::CreateMemset(Value* dst, | |
461 Value* value, | |
462 Value* len, | |
463 Value* align) { | |
464 #if SHARK_LLVM_VERSION >= 28 | |
465 return CreateCall5(memset(), dst, value, len, align, | |
466 LLVMValue::jint_constant(0)); | |
467 #else | |
468 return CreateCall4(memset(), dst, value, len, align); | |
469 #endif | |
470 } | |
471 | |
472 CallInst* SharkBuilder::CreateUnimplemented(const char* file, int line) { | |
473 return CreateCall2( | |
474 unimplemented(), | |
475 CreateIntToPtr( | |
476 LLVMValue::intptr_constant((intptr_t) file), | |
477 PointerType::getUnqual(SharkType::jbyte_type())), | |
478 LLVMValue::jint_constant(line)); | |
479 } | |
480 | |
481 CallInst* SharkBuilder::CreateShouldNotReachHere(const char* file, int line) { | |
482 return CreateCall2( | |
483 should_not_reach_here(), | |
484 CreateIntToPtr( | |
485 LLVMValue::intptr_constant((intptr_t) file), | |
486 PointerType::getUnqual(SharkType::jbyte_type())), | |
487 LLVMValue::jint_constant(line)); | |
488 } | |
489 | |
490 #ifndef PRODUCT | |
491 CallInst* SharkBuilder::CreateDump(Value* value) { | |
492 const char *name; | |
493 if (value->hasName()) | |
494 // XXX this leaks, but it's only debug code | |
495 name = strdup(value->getName().str().c_str()); | |
496 else | |
497 name = "unnamed_value"; | |
498 | |
499 if (isa<PointerType>(value->getType())) | |
500 value = CreatePtrToInt(value, SharkType::intptr_type()); | |
501 else if (value->getType()-> | |
502 #if SHARK_LLVM_VERSION >= 27 | |
503 isIntegerTy() | |
504 #else | |
505 isInteger() | |
506 #endif | |
507 ) | |
508 value = CreateIntCast(value, SharkType::intptr_type(), false); | |
509 else | |
510 Unimplemented(); | |
511 | |
512 return CreateCall2( | |
513 dump(), | |
514 CreateIntToPtr( | |
515 LLVMValue::intptr_constant((intptr_t) name), | |
516 PointerType::getUnqual(SharkType::jbyte_type())), | |
517 value); | |
518 } | |
519 #endif // PRODUCT | |
520 | |
521 // HotSpot memory barriers | |
522 | |
523 void SharkBuilder::CreateUpdateBarrierSet(BarrierSet* bs, Value* field) { | |
524 if (bs->kind() != BarrierSet::CardTableModRef) | |
525 Unimplemented(); | |
526 | |
527 CreateStore( | |
528 LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card), | |
529 CreateIntToPtr( | |
530 CreateAdd( | |
531 LLVMValue::intptr_constant( | |
532 (intptr_t) ((CardTableModRefBS *) bs)->byte_map_base), | |
533 CreateLShr( | |
534 CreatePtrToInt(field, SharkType::intptr_type()), | |
535 LLVMValue::intptr_constant(CardTableModRefBS::card_shift))), | |
536 PointerType::getUnqual(SharkType::jbyte_type()))); | |
537 } | |
538 | |
539 // Helpers for accessing the code buffer | |
540 | |
541 Value* SharkBuilder::code_buffer_address(int offset) { | |
542 return CreateAdd( | |
543 code_buffer()->base_pc(), | |
544 LLVMValue::intptr_constant(offset)); | |
545 } | |
546 | |
547 Value* SharkBuilder::CreateInlineOop(jobject object, const char* name) { | |
548 return CreateLoad( | |
549 CreateIntToPtr( | |
550 code_buffer_address(code_buffer()->inline_oop(object)), | |
551 PointerType::getUnqual(SharkType::oop_type())), | |
552 name); | |
553 } | |
554 | |
555 Value* SharkBuilder::CreateInlineData(void* data, | |
556 size_t size, | |
557 const Type* type, | |
558 const char* name) { | |
559 return CreateIntToPtr( | |
560 code_buffer_address(code_buffer()->inline_data(data, size)), | |
561 type, | |
562 name); | |
563 } | |
564 | |
565 // Helpers for creating basic blocks. | |
566 | |
567 BasicBlock* SharkBuilder::GetBlockInsertionPoint() const { | |
568 BasicBlock *cur = GetInsertBlock(); | |
569 | |
570 // BasicBlock::Create takes an insertBefore argument, so | |
571 // we need to find the block _after_ the current block | |
572 Function::iterator iter = cur->getParent()->begin(); | |
573 Function::iterator end = cur->getParent()->end(); | |
574 while (iter != end) { | |
575 iter++; | |
576 if (&*iter == cur) { | |
577 iter++; | |
578 break; | |
579 } | |
580 } | |
581 | |
582 if (iter == end) | |
583 return NULL; | |
584 else | |
585 return iter; | |
586 } | |
587 | |
588 BasicBlock* SharkBuilder::CreateBlock(BasicBlock* ip, const char* name) const { | |
589 return BasicBlock::Create( | |
590 SharkContext::current(), name, GetInsertBlock()->getParent(), ip); | |
591 } |