Mercurial > hg > graal-compiler
annotate src/share/vm/shark/sharkBuilder.cpp @ 10185:d50cc62e94ff
8012715: G1: GraphKit accesses PtrQueue::_index as int but is size_t
Summary: In graphKit INT operations were generated to access PtrQueue::_index which has type size_t. This is 64 bit on 64-bit machines. No problems occur on little endian machines as long as the index fits into 32 bit, but on big endian machines the upper part is read, which is zero. This leads to unnecessary branches to the slow path in the runtime.
Reviewed-by: twisti, johnc
Contributed-by: Martin Doerr <martin.doerr@sap.com>
author | johnc |
---|---|
date | Wed, 24 Apr 2013 14:48:43 -0700 |
parents | 2cd5e15048e6 |
children | e0c9a1d29eb4 |
rev | line source |
---|---|
1692 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
1972
diff
changeset
|
2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. |
1692 | 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 | |
1972 | 26 #include "precompiled.hpp" |
27 #include "ci/ciMethod.hpp" | |
28 #include "memory/resourceArea.hpp" | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
1972
diff
changeset
|
29 #include "oops/method.hpp" |
1972 | 30 #include "runtime/os.hpp" |
31 #include "runtime/synchronizer.hpp" | |
32 #include "runtime/thread.hpp" | |
33 #include "shark/llvmHeaders.hpp" | |
34 #include "shark/llvmValue.hpp" | |
35 #include "shark/sharkBuilder.hpp" | |
36 #include "shark/sharkContext.hpp" | |
37 #include "shark/sharkRuntime.hpp" | |
38 #include "utilities/debug.hpp" | |
1692 | 39 |
40 using namespace llvm; | |
41 | |
42 SharkBuilder::SharkBuilder(SharkCodeBuffer* code_buffer) | |
43 : IRBuilder<>(SharkContext::current()), | |
44 _code_buffer(code_buffer) { | |
45 } | |
46 | |
47 // Helpers for accessing structures | |
48 Value* SharkBuilder::CreateAddressOfStructEntry(Value* base, | |
49 ByteSize offset, | |
7195 | 50 Type* type, |
1692 | 51 const char* name) { |
52 return CreateBitCast(CreateStructGEP(base, in_bytes(offset)), type, name); | |
53 } | |
54 | |
55 LoadInst* SharkBuilder::CreateValueOfStructEntry(Value* base, | |
56 ByteSize offset, | |
7195 | 57 Type* type, |
1692 | 58 const char* name) { |
59 return CreateLoad( | |
60 CreateAddressOfStructEntry( | |
61 base, offset, PointerType::getUnqual(type)), | |
62 name); | |
63 } | |
64 | |
65 // Helpers for accessing arrays | |
66 | |
67 LoadInst* SharkBuilder::CreateArrayLength(Value* arrayoop) { | |
68 return CreateValueOfStructEntry( | |
69 arrayoop, in_ByteSize(arrayOopDesc::length_offset_in_bytes()), | |
70 SharkType::jint_type(), "length"); | |
71 } | |
72 | |
73 Value* SharkBuilder::CreateArrayAddress(Value* arrayoop, | |
7195 | 74 Type* element_type, |
1692 | 75 int element_bytes, |
76 ByteSize base_offset, | |
77 Value* index, | |
78 const char* name) { | |
79 Value* offset = CreateIntCast(index, SharkType::intptr_type(), false); | |
80 if (element_bytes != 1) | |
81 offset = CreateShl( | |
82 offset, | |
83 LLVMValue::intptr_constant(exact_log2(element_bytes))); | |
84 offset = CreateAdd( | |
85 LLVMValue::intptr_constant(in_bytes(base_offset)), offset); | |
86 | |
87 return CreateIntToPtr( | |
88 CreateAdd(CreatePtrToInt(arrayoop, SharkType::intptr_type()), offset), | |
89 PointerType::getUnqual(element_type), | |
90 name); | |
91 } | |
92 | |
93 Value* SharkBuilder::CreateArrayAddress(Value* arrayoop, | |
94 BasicType basic_type, | |
95 ByteSize base_offset, | |
96 Value* index, | |
97 const char* name) { | |
98 return CreateArrayAddress( | |
99 arrayoop, | |
100 SharkType::to_arrayType(basic_type), | |
101 type2aelembytes(basic_type), | |
102 base_offset, index, name); | |
103 } | |
104 | |
105 Value* SharkBuilder::CreateArrayAddress(Value* arrayoop, | |
106 BasicType basic_type, | |
107 Value* index, | |
108 const char* name) { | |
109 return CreateArrayAddress( | |
110 arrayoop, basic_type, | |
111 in_ByteSize(arrayOopDesc::base_offset_in_bytes(basic_type)), | |
112 index, name); | |
113 } | |
114 | |
115 // Helpers for creating intrinsics and external functions. | |
116 | |
7195 | 117 Type* SharkBuilder::make_type(char type, bool void_ok) { |
1692 | 118 switch (type) { |
119 // Primitive types | |
120 case 'c': | |
121 return SharkType::jbyte_type(); | |
122 case 'i': | |
123 return SharkType::jint_type(); | |
124 case 'l': | |
125 return SharkType::jlong_type(); | |
126 case 'x': | |
127 return SharkType::intptr_type(); | |
128 case 'f': | |
129 return SharkType::jfloat_type(); | |
130 case 'd': | |
131 return SharkType::jdouble_type(); | |
132 | |
133 // Pointers to primitive types | |
134 case 'C': | |
135 case 'I': | |
136 case 'L': | |
137 case 'X': | |
138 case 'F': | |
139 case 'D': | |
140 return PointerType::getUnqual(make_type(tolower(type), false)); | |
141 | |
142 // VM objects | |
143 case 'T': | |
144 return SharkType::thread_type(); | |
145 case 'M': | |
146 return PointerType::getUnqual(SharkType::monitor_type()); | |
147 case 'O': | |
148 return SharkType::oop_type(); | |
7195 | 149 case 'K': |
150 return SharkType::klass_type(); | |
1692 | 151 |
152 // Miscellaneous | |
153 case 'v': | |
154 assert(void_ok, "should be"); | |
155 return SharkType::void_type(); | |
156 case '1': | |
157 return SharkType::bit_type(); | |
158 | |
159 default: | |
160 ShouldNotReachHere(); | |
161 } | |
162 } | |
163 | |
7195 | 164 FunctionType* SharkBuilder::make_ftype(const char* params, |
1692 | 165 const char* ret) { |
7195 | 166 std::vector<Type*> param_types; |
1692 | 167 for (const char* c = params; *c; c++) |
168 param_types.push_back(make_type(*c, false)); | |
169 | |
170 assert(strlen(ret) == 1, "should be"); | |
7195 | 171 Type *return_type = make_type(*ret, true); |
1692 | 172 |
173 return FunctionType::get(return_type, param_types, false); | |
174 } | |
175 | |
176 // Create an object representing an intrinsic or external function by | |
177 // referencing the symbol by name. This is the LLVM-style approach, | |
178 // but it cannot be used on functions within libjvm.so its symbols | |
179 // are not exported. Note that you cannot make this work simply by | |
180 // exporting the symbols, as some symbols have the same names as | |
181 // symbols in the standard libraries (eg, atan2, fabs) and would | |
182 // obscure them were they visible. | |
183 Value* SharkBuilder::make_function(const char* name, | |
184 const char* params, | |
185 const char* ret) { | |
186 return SharkContext::current().get_external(name, make_ftype(params, ret)); | |
187 } | |
188 | |
189 // Create an object representing an external function by inlining a | |
190 // function pointer in the code. This is not the LLVM way, but it's | |
191 // the only way to access functions in libjvm.so and functions like | |
192 // __kernel_dmb on ARM which is accessed via an absolute address. | |
193 Value* SharkBuilder::make_function(address func, | |
194 const char* params, | |
195 const char* ret) { | |
196 return CreateIntToPtr( | |
197 LLVMValue::intptr_constant((intptr_t) func), | |
198 PointerType::getUnqual(make_ftype(params, ret))); | |
199 } | |
200 | |
201 // VM calls | |
202 | |
203 Value* SharkBuilder::find_exception_handler() { | |
204 return make_function( | |
205 (address) SharkRuntime::find_exception_handler, "TIi", "i"); | |
206 } | |
207 | |
208 Value* SharkBuilder::monitorenter() { | |
209 return make_function((address) SharkRuntime::monitorenter, "TM", "v"); | |
210 } | |
211 | |
212 Value* SharkBuilder::monitorexit() { | |
213 return make_function((address) SharkRuntime::monitorexit, "TM", "v"); | |
214 } | |
215 | |
216 Value* SharkBuilder::new_instance() { | |
217 return make_function((address) SharkRuntime::new_instance, "Ti", "v"); | |
218 } | |
219 | |
220 Value* SharkBuilder::newarray() { | |
221 return make_function((address) SharkRuntime::newarray, "Tii", "v"); | |
222 } | |
223 | |
224 Value* SharkBuilder::anewarray() { | |
225 return make_function((address) SharkRuntime::anewarray, "Tii", "v"); | |
226 } | |
227 | |
228 Value* SharkBuilder::multianewarray() { | |
229 return make_function((address) SharkRuntime::multianewarray, "TiiI", "v"); | |
230 } | |
231 | |
232 Value* SharkBuilder::register_finalizer() { | |
233 return make_function((address) SharkRuntime::register_finalizer, "TO", "v"); | |
234 } | |
235 | |
236 Value* SharkBuilder::safepoint() { | |
237 return make_function((address) SafepointSynchronize::block, "T", "v"); | |
238 } | |
239 | |
240 Value* SharkBuilder::throw_ArithmeticException() { | |
241 return make_function( | |
242 (address) SharkRuntime::throw_ArithmeticException, "TCi", "v"); | |
243 } | |
244 | |
245 Value* SharkBuilder::throw_ArrayIndexOutOfBoundsException() { | |
246 return make_function( | |
247 (address) SharkRuntime::throw_ArrayIndexOutOfBoundsException, "TCii", "v"); | |
248 } | |
249 | |
250 Value* SharkBuilder::throw_ClassCastException() { | |
251 return make_function( | |
252 (address) SharkRuntime::throw_ClassCastException, "TCi", "v"); | |
253 } | |
254 | |
255 Value* SharkBuilder::throw_NullPointerException() { | |
256 return make_function( | |
257 (address) SharkRuntime::throw_NullPointerException, "TCi", "v"); | |
258 } | |
259 | |
260 // High-level non-VM calls | |
261 | |
262 Value* SharkBuilder::f2i() { | |
263 return make_function((address) SharedRuntime::f2i, "f", "i"); | |
264 } | |
265 | |
266 Value* SharkBuilder::f2l() { | |
267 return make_function((address) SharedRuntime::f2l, "f", "l"); | |
268 } | |
269 | |
270 Value* SharkBuilder::d2i() { | |
271 return make_function((address) SharedRuntime::d2i, "d", "i"); | |
272 } | |
273 | |
274 Value* SharkBuilder::d2l() { | |
275 return make_function((address) SharedRuntime::d2l, "d", "l"); | |
276 } | |
277 | |
278 Value* SharkBuilder::is_subtype_of() { | |
7195 | 279 return make_function((address) SharkRuntime::is_subtype_of, "KK", "c"); |
1692 | 280 } |
281 | |
282 Value* SharkBuilder::current_time_millis() { | |
283 return make_function((address) os::javaTimeMillis, "", "l"); | |
284 } | |
285 | |
286 Value* SharkBuilder::sin() { | |
287 return make_function("llvm.sin.f64", "d", "d"); | |
288 } | |
289 | |
290 Value* SharkBuilder::cos() { | |
291 return make_function("llvm.cos.f64", "d", "d"); | |
292 } | |
293 | |
294 Value* SharkBuilder::tan() { | |
295 return make_function((address) ::tan, "d", "d"); | |
296 } | |
297 | |
298 Value* SharkBuilder::atan2() { | |
299 return make_function((address) ::atan2, "dd", "d"); | |
300 } | |
301 | |
302 Value* SharkBuilder::sqrt() { | |
303 return make_function("llvm.sqrt.f64", "d", "d"); | |
304 } | |
305 | |
306 Value* SharkBuilder::log() { | |
307 return make_function("llvm.log.f64", "d", "d"); | |
308 } | |
309 | |
310 Value* SharkBuilder::log10() { | |
311 return make_function("llvm.log10.f64", "d", "d"); | |
312 } | |
313 | |
314 Value* SharkBuilder::pow() { | |
315 return make_function("llvm.pow.f64", "dd", "d"); | |
316 } | |
317 | |
318 Value* SharkBuilder::exp() { | |
319 return make_function("llvm.exp.f64", "d", "d"); | |
320 } | |
321 | |
322 Value* SharkBuilder::fabs() { | |
323 return make_function((address) ::fabs, "d", "d"); | |
324 } | |
325 | |
326 Value* SharkBuilder::unsafe_field_offset_to_byte_offset() { | |
327 extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); | |
328 return make_function((address) Unsafe_field_offset_to_byte_offset, "l", "l"); | |
329 } | |
330 | |
331 Value* SharkBuilder::osr_migration_end() { | |
332 return make_function((address) SharedRuntime::OSR_migration_end, "C", "v"); | |
333 } | |
334 | |
335 // Semi-VM calls | |
336 | |
337 Value* SharkBuilder::throw_StackOverflowError() { | |
338 return make_function((address) ZeroStack::handle_overflow, "T", "v"); | |
339 } | |
340 | |
341 Value* SharkBuilder::uncommon_trap() { | |
342 return make_function((address) SharkRuntime::uncommon_trap, "Ti", "i"); | |
343 } | |
344 | |
345 Value* SharkBuilder::deoptimized_entry_point() { | |
346 return make_function((address) CppInterpreter::main_loop, "iT", "v"); | |
347 } | |
348 | |
349 // Native-Java transition | |
350 | |
351 Value* SharkBuilder::check_special_condition_for_native_trans() { | |
352 return make_function( | |
353 (address) JavaThread::check_special_condition_for_native_trans, | |
354 "T", "v"); | |
355 } | |
356 | |
357 Value* SharkBuilder::frame_address() { | |
358 return make_function("llvm.frameaddress", "i", "C"); | |
359 } | |
360 | |
361 Value* SharkBuilder::memset() { | |
362 // LLVM 2.8 added a fifth isVolatile field for memset | |
363 // introduced with LLVM r100304 | |
7195 | 364 return make_function("llvm.memset.p0i8.i32", "Cciii", "v"); |
1692 | 365 } |
366 | |
367 Value* SharkBuilder::unimplemented() { | |
368 return make_function((address) report_unimplemented, "Ci", "v"); | |
369 } | |
370 | |
371 Value* SharkBuilder::should_not_reach_here() { | |
372 return make_function((address) report_should_not_reach_here, "Ci", "v"); | |
373 } | |
374 | |
375 Value* SharkBuilder::dump() { | |
376 return make_function((address) SharkRuntime::dump, "Cx", "v"); | |
377 } | |
378 | |
379 // Public interface to low-level non-VM calls | |
380 | |
381 CallInst* SharkBuilder::CreateGetFrameAddress() { | |
382 return CreateCall(frame_address(), LLVMValue::jint_constant(0)); | |
383 } | |
384 | |
385 CallInst* SharkBuilder::CreateMemset(Value* dst, | |
386 Value* value, | |
387 Value* len, | |
388 Value* align) { | |
389 return CreateCall5(memset(), dst, value, len, align, | |
390 LLVMValue::jint_constant(0)); | |
391 } | |
392 | |
393 CallInst* SharkBuilder::CreateUnimplemented(const char* file, int line) { | |
394 return CreateCall2( | |
395 unimplemented(), | |
396 CreateIntToPtr( | |
397 LLVMValue::intptr_constant((intptr_t) file), | |
398 PointerType::getUnqual(SharkType::jbyte_type())), | |
399 LLVMValue::jint_constant(line)); | |
400 } | |
401 | |
402 CallInst* SharkBuilder::CreateShouldNotReachHere(const char* file, int line) { | |
403 return CreateCall2( | |
404 should_not_reach_here(), | |
405 CreateIntToPtr( | |
406 LLVMValue::intptr_constant((intptr_t) file), | |
407 PointerType::getUnqual(SharkType::jbyte_type())), | |
408 LLVMValue::jint_constant(line)); | |
409 } | |
410 | |
411 #ifndef PRODUCT | |
412 CallInst* SharkBuilder::CreateDump(Value* value) { | |
413 const char *name; | |
414 if (value->hasName()) | |
415 // XXX this leaks, but it's only debug code | |
416 name = strdup(value->getName().str().c_str()); | |
417 else | |
418 name = "unnamed_value"; | |
419 | |
420 if (isa<PointerType>(value->getType())) | |
421 value = CreatePtrToInt(value, SharkType::intptr_type()); | |
422 else if (value->getType()-> | |
423 isIntegerTy() | |
424 ) | |
425 value = CreateIntCast(value, SharkType::intptr_type(), false); | |
426 else | |
427 Unimplemented(); | |
428 | |
429 return CreateCall2( | |
430 dump(), | |
431 CreateIntToPtr( | |
432 LLVMValue::intptr_constant((intptr_t) name), | |
433 PointerType::getUnqual(SharkType::jbyte_type())), | |
434 value); | |
435 } | |
436 #endif // PRODUCT | |
437 | |
438 // HotSpot memory barriers | |
439 | |
440 void SharkBuilder::CreateUpdateBarrierSet(BarrierSet* bs, Value* field) { | |
441 if (bs->kind() != BarrierSet::CardTableModRef) | |
442 Unimplemented(); | |
443 | |
444 CreateStore( | |
445 LLVMValue::jbyte_constant(CardTableModRefBS::dirty_card), | |
446 CreateIntToPtr( | |
447 CreateAdd( | |
448 LLVMValue::intptr_constant( | |
449 (intptr_t) ((CardTableModRefBS *) bs)->byte_map_base), | |
450 CreateLShr( | |
451 CreatePtrToInt(field, SharkType::intptr_type()), | |
452 LLVMValue::intptr_constant(CardTableModRefBS::card_shift))), | |
453 PointerType::getUnqual(SharkType::jbyte_type()))); | |
454 } | |
455 | |
456 // Helpers for accessing the code buffer | |
457 | |
458 Value* SharkBuilder::code_buffer_address(int offset) { | |
459 return CreateAdd( | |
460 code_buffer()->base_pc(), | |
461 LLVMValue::intptr_constant(offset)); | |
462 } | |
463 | |
464 Value* SharkBuilder::CreateInlineOop(jobject object, const char* name) { | |
465 return CreateLoad( | |
466 CreateIntToPtr( | |
467 code_buffer_address(code_buffer()->inline_oop(object)), | |
468 PointerType::getUnqual(SharkType::oop_type())), | |
469 name); | |
470 } | |
471 | |
7195 | 472 Value* SharkBuilder::CreateInlineMetadata(Metadata* metadata, llvm::PointerType* type, const char* name) { |
473 assert(metadata != NULL, "inlined metadata must not be NULL"); | |
474 assert(metadata->is_metadata(), "sanity check"); | |
475 return CreateLoad( | |
476 CreateIntToPtr( | |
477 code_buffer_address(code_buffer()->inline_Metadata(metadata)), | |
478 PointerType::getUnqual(type)), | |
479 name); | |
480 } | |
481 | |
1692 | 482 Value* SharkBuilder::CreateInlineData(void* data, |
483 size_t size, | |
7195 | 484 Type* type, |
1692 | 485 const char* name) { |
486 return CreateIntToPtr( | |
487 code_buffer_address(code_buffer()->inline_data(data, size)), | |
488 type, | |
489 name); | |
490 } | |
491 | |
492 // Helpers for creating basic blocks. | |
493 | |
494 BasicBlock* SharkBuilder::GetBlockInsertionPoint() const { | |
495 BasicBlock *cur = GetInsertBlock(); | |
496 | |
497 // BasicBlock::Create takes an insertBefore argument, so | |
498 // we need to find the block _after_ the current block | |
499 Function::iterator iter = cur->getParent()->begin(); | |
500 Function::iterator end = cur->getParent()->end(); | |
501 while (iter != end) { | |
502 iter++; | |
503 if (&*iter == cur) { | |
504 iter++; | |
505 break; | |
506 } | |
507 } | |
508 | |
509 if (iter == end) | |
510 return NULL; | |
511 else | |
512 return iter; | |
513 } | |
514 | |
515 BasicBlock* SharkBuilder::CreateBlock(BasicBlock* ip, const char* name) const { | |
516 return BasicBlock::Create( | |
517 SharkContext::current(), name, GetInsertBlock()->getParent(), ip); | |
518 } | |
7195 | 519 |
520 LoadInst* SharkBuilder::CreateAtomicLoad(Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) { | |
521 return Insert(new LoadInst(ptr, name, isVolatile, align, ordering, synchScope), name); | |
522 } | |
523 | |
524 StoreInst* SharkBuilder::CreateAtomicStore(Value* val, Value* ptr, unsigned align, AtomicOrdering ordering, SynchronizationScope synchScope, bool isVolatile, const char* name) { | |
525 return Insert(new StoreInst(val, ptr, isVolatile, align, ordering, synchScope), name); | |
526 } |