Mercurial > hg > graal-compiler
annotate src/share/vm/shark/sharkNativeWrapper.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 |
rev | line source |
---|---|
1692 | 1 /* |
2426
1d1603768966
7010070: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - second pass
trims
parents:
2376
diff
changeset
|
2 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. |
1692 | 3 * Copyright 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 "shark/llvmHeaders.hpp" | |
28 #include "shark/sharkNativeWrapper.hpp" | |
29 #include "shark/sharkType.hpp" | |
1692 | 30 |
31 using namespace llvm; | |
32 | |
33 void SharkNativeWrapper::initialize(const char *name) { | |
34 // Create the function | |
35 _function = Function::Create( | |
36 SharkType::entry_point_type(), | |
37 GlobalVariable::InternalLinkage, | |
38 name); | |
39 | |
40 // Get our arguments | |
41 Function::arg_iterator ai = function()->arg_begin(); | |
42 Argument *method = ai++; | |
43 method->setName("method"); | |
44 Argument *base_pc = ai++; | |
45 base_pc->setName("base_pc"); | |
46 code_buffer()->set_base_pc(base_pc); | |
47 Argument *thread = ai++; | |
48 thread->setName("thread"); | |
49 set_thread(thread); | |
50 | |
51 // Create and push our stack frame | |
52 builder()->SetInsertPoint(CreateBlock()); | |
53 _stack = SharkStack::CreateBuildAndPushFrame(this, method); | |
54 NOT_PRODUCT(method = NULL); | |
55 | |
56 // Create the oopmap. We use the one oopmap for every call site in | |
57 // the wrapper, which results in the odd mild inefficiency but is a | |
58 // damn sight easier to code. | |
59 OopMap *oopmap = new OopMap( | |
60 SharkStack::oopmap_slot_munge(stack()->oopmap_frame_size()), | |
61 SharkStack::oopmap_slot_munge(arg_size())); | |
62 | |
63 // Set up the oop_tmp slot if required: | |
64 // - For static methods we use it to handlize the class argument | |
65 // for the call, and to protect the same during slow path locks | |
66 // (if synchronized). | |
67 // - For methods returning oops, we use it to protect the return | |
68 // value across safepoints or slow path unlocking. | |
69 if (is_static() || is_returning_oop()) { | |
70 _oop_tmp_slot = stack()->slot_addr( | |
71 stack()->oop_tmp_slot_offset(), | |
72 SharkType::oop_type(), | |
73 "oop_tmp_slot"); | |
74 | |
75 oopmap->set_oop(SharkStack::slot2reg(stack()->oop_tmp_slot_offset())); | |
76 } | |
77 | |
78 // Set up the monitor slot, for synchronized methods | |
79 if (is_synchronized()) { | |
80 Unimplemented(); | |
81 _lock_slot_offset = 23; | |
82 } | |
83 | |
84 // Start building the argument list | |
7195 | 85 std::vector<Type*> param_types; |
1692 | 86 std::vector<Value*> param_values; |
7195 | 87 PointerType *box_type = PointerType::getUnqual(SharkType::oop_type()); |
1692 | 88 |
89 // First argument is the JNIEnv | |
90 param_types.push_back(SharkType::jniEnv_type()); | |
91 param_values.push_back( | |
92 builder()->CreateAddressOfStructEntry( | |
93 thread, | |
94 JavaThread::jni_environment_offset(), | |
95 SharkType::jniEnv_type(), | |
96 "jni_environment")); | |
97 | |
98 // For static methods, the second argument is the class | |
99 if (is_static()) { | |
100 builder()->CreateStore( | |
101 builder()->CreateInlineOop( | |
102 JNIHandles::make_local( | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
1972
diff
changeset
|
103 target()->method_holder()->java_mirror())), |
1692 | 104 oop_tmp_slot()); |
105 | |
106 param_types.push_back(box_type); | |
107 param_values.push_back(oop_tmp_slot()); | |
108 | |
109 _receiver_slot_offset = stack()->oop_tmp_slot_offset(); | |
110 } | |
111 else if (is_returning_oop()) { | |
112 // The oop_tmp slot is registered in the oopmap, | |
113 // so we need to clear it. This is one of the | |
114 // mild inefficiencies I mentioned earlier. | |
115 builder()->CreateStore(LLVMValue::null(), oop_tmp_slot()); | |
116 } | |
117 | |
118 // Parse the arguments | |
119 for (int i = 0; i < arg_size(); i++) { | |
120 int slot_offset = stack()->locals_slots_offset() + arg_size() - 1 - i; | |
121 int adjusted_offset = slot_offset; | |
122 BasicBlock *null, *not_null, *merge; | |
123 Value *box; | |
124 PHINode *phi; | |
125 | |
126 switch (arg_type(i)) { | |
127 case T_VOID: | |
128 break; | |
129 | |
130 case T_OBJECT: | |
131 case T_ARRAY: | |
132 null = CreateBlock("null"); | |
133 not_null = CreateBlock("not_null"); | |
134 merge = CreateBlock("merge"); | |
135 | |
136 box = stack()->slot_addr(slot_offset, SharkType::oop_type()); | |
137 builder()->CreateCondBr( | |
138 builder()->CreateICmp( | |
139 ICmpInst::ICMP_EQ, | |
140 builder()->CreateLoad(box), | |
141 LLVMValue::null()), | |
142 null, not_null); | |
143 | |
144 builder()->SetInsertPoint(null); | |
145 builder()->CreateBr(merge); | |
146 | |
147 builder()->SetInsertPoint(not_null); | |
148 builder()->CreateBr(merge); | |
149 | |
150 builder()->SetInsertPoint(merge); | |
7195 | 151 phi = builder()->CreatePHI(box_type, 0, "boxed_object"); |
1692 | 152 phi->addIncoming(ConstantPointerNull::get(box_type), null); |
153 phi->addIncoming(box, not_null); | |
154 box = phi; | |
155 | |
156 param_types.push_back(box_type); | |
157 param_values.push_back(box); | |
158 | |
159 oopmap->set_oop(SharkStack::slot2reg(slot_offset)); | |
160 | |
161 if (i == 0 && !is_static()) | |
162 _receiver_slot_offset = slot_offset; | |
163 | |
164 break; | |
165 | |
166 case T_LONG: | |
167 case T_DOUBLE: | |
168 adjusted_offset--; | |
169 // fall through | |
170 | |
171 default: | |
7195 | 172 Type *param_type = SharkType::to_stackType(arg_type(i)); |
1692 | 173 |
174 param_types.push_back(param_type); | |
175 param_values.push_back( | |
176 builder()->CreateLoad(stack()->slot_addr(adjusted_offset, param_type))); | |
177 } | |
178 } | |
179 | |
180 // The oopmap is now complete, and everything is written | |
181 // into the frame except the PC. | |
182 int pc_offset = code_buffer()->create_unique_offset(); | |
183 | |
184 _oop_maps = new OopMapSet(); | |
185 oop_maps()->add_gc_map(pc_offset, oopmap); | |
186 | |
187 builder()->CreateStore( | |
188 builder()->code_buffer_address(pc_offset), | |
189 stack()->slot_addr(stack()->pc_slot_offset())); | |
190 | |
191 // Set up the Java frame anchor | |
192 stack()->CreateSetLastJavaFrame(); | |
193 | |
194 // Lock if necessary | |
195 if (is_synchronized()) | |
196 Unimplemented(); | |
197 | |
198 // Change the thread state to _thread_in_native | |
199 CreateSetThreadState(_thread_in_native); | |
200 | |
201 // Make the call | |
202 BasicType result_type = target()->result_type(); | |
7195 | 203 Type* return_type; |
1692 | 204 if (result_type == T_VOID) |
205 return_type = SharkType::void_type(); | |
206 else if (is_returning_oop()) | |
207 return_type = box_type; | |
208 else | |
209 return_type = SharkType::to_arrayType(result_type); | |
210 Value* native_function = builder()->CreateIntToPtr( | |
211 LLVMValue::intptr_constant((intptr_t) target()->native_function()), | |
212 PointerType::getUnqual( | |
213 FunctionType::get(return_type, param_types, false))); | |
214 Value *result = builder()->CreateCall( | |
7195 | 215 native_function, llvm::makeArrayRef(param_values)); |
1692 | 216 |
217 // Start the transition back to _thread_in_Java | |
218 CreateSetThreadState(_thread_in_native_trans); | |
219 | |
220 // Make sure new state is visible in the GC thread | |
221 if (os::is_MP()) { | |
222 if (UseMembar) | |
7195 | 223 builder()->CreateFence(llvm::SequentiallyConsistent, llvm::CrossThread); |
1692 | 224 else |
225 CreateWriteMemorySerializePage(); | |
226 } | |
227 | |
228 // Handle safepoint operations, pending suspend requests, | |
229 // and pending asynchronous exceptions. | |
230 BasicBlock *check_thread = CreateBlock("check_thread"); | |
231 BasicBlock *do_safepoint = CreateBlock("do_safepoint"); | |
232 BasicBlock *safepointed = CreateBlock("safepointed"); | |
233 | |
234 Value *global_state = builder()->CreateLoad( | |
235 builder()->CreateIntToPtr( | |
236 LLVMValue::intptr_constant( | |
237 (intptr_t) SafepointSynchronize::address_of_state()), | |
238 PointerType::getUnqual(SharkType::jint_type())), | |
239 "global_state"); | |
240 | |
241 builder()->CreateCondBr( | |
242 builder()->CreateICmpNE( | |
243 global_state, | |
244 LLVMValue::jint_constant(SafepointSynchronize::_not_synchronized)), | |
245 do_safepoint, check_thread); | |
246 | |
247 builder()->SetInsertPoint(check_thread); | |
248 Value *thread_state = builder()->CreateValueOfStructEntry( | |
249 thread, | |
250 JavaThread::suspend_flags_offset(), | |
251 SharkType::jint_type(), | |
252 "thread_state"); | |
253 | |
254 builder()->CreateCondBr( | |
255 builder()->CreateICmpNE( | |
256 thread_state, | |
257 LLVMValue::jint_constant(0)), | |
258 do_safepoint, safepointed); | |
259 | |
260 builder()->SetInsertPoint(do_safepoint); | |
261 builder()->CreateCall( | |
262 builder()->check_special_condition_for_native_trans(), thread); | |
263 builder()->CreateBr(safepointed); | |
264 | |
265 // Finally we can change the thread state to _thread_in_Java | |
266 builder()->SetInsertPoint(safepointed); | |
267 CreateSetThreadState(_thread_in_Java); | |
268 | |
269 // Clear the frame anchor | |
270 stack()->CreateResetLastJavaFrame(); | |
271 | |
272 // If there is a pending exception then we can just unwind and | |
273 // return. It seems totally wrong that unlocking is skipped here | |
274 // but apparently the template interpreter does this so we do too. | |
275 BasicBlock *exception = CreateBlock("exception"); | |
276 BasicBlock *no_exception = CreateBlock("no_exception"); | |
277 | |
278 builder()->CreateCondBr( | |
279 builder()->CreateICmpEQ( | |
280 CreateLoadPendingException(), | |
281 LLVMValue::null()), | |
282 no_exception, exception); | |
283 | |
284 builder()->SetInsertPoint(exception); | |
285 CreateResetHandleBlock(); | |
286 stack()->CreatePopFrame(0); | |
287 builder()->CreateRet(LLVMValue::jint_constant(0)); | |
288 | |
289 builder()->SetInsertPoint(no_exception); | |
290 | |
291 // If the result was an oop then unbox it before | |
292 // releasing the handle it might be protected by | |
293 if (is_returning_oop()) { | |
294 BasicBlock *null = builder()->GetInsertBlock(); | |
295 BasicBlock *not_null = CreateBlock("not_null"); | |
296 BasicBlock *merge = CreateBlock("merge"); | |
297 | |
298 builder()->CreateCondBr( | |
299 builder()->CreateICmpNE(result, ConstantPointerNull::get(box_type)), | |
300 not_null, merge); | |
301 | |
302 builder()->SetInsertPoint(not_null); | |
303 Value *unboxed_result = builder()->CreateLoad(result); | |
304 builder()->CreateBr(merge); | |
305 | |
306 builder()->SetInsertPoint(merge); | |
7195 | 307 PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), 0, "result"); |
1692 | 308 phi->addIncoming(LLVMValue::null(), null); |
309 phi->addIncoming(unboxed_result, not_null); | |
310 result = phi; | |
311 } | |
312 | |
313 // Reset handle block | |
314 CreateResetHandleBlock(); | |
315 | |
316 // Unlock if necessary. | |
317 if (is_synchronized()) | |
318 Unimplemented(); | |
319 | |
320 // Unwind and return | |
321 Value *result_addr = stack()->CreatePopFrame(type2size[result_type]); | |
322 if (result_type != T_VOID) { | |
323 bool needs_cast = false; | |
324 bool is_signed = false; | |
325 switch (result_type) { | |
326 case T_BOOLEAN: | |
327 result = builder()->CreateICmpNE(result, LLVMValue::jbyte_constant(0)); | |
328 needs_cast = true; | |
329 break; | |
330 | |
331 case T_CHAR: | |
332 needs_cast = true; | |
333 break; | |
334 | |
335 case T_BYTE: | |
336 case T_SHORT: | |
337 needs_cast = true; | |
338 is_signed = true; | |
339 break; | |
340 } | |
341 if (needs_cast) { | |
342 result = builder()->CreateIntCast( | |
343 result, SharkType::to_stackType(result_type), is_signed); | |
344 } | |
345 | |
346 builder()->CreateStore( | |
347 result, | |
348 builder()->CreateIntToPtr( | |
349 result_addr, | |
350 PointerType::getUnqual(SharkType::to_stackType(result_type)))); | |
351 } | |
352 builder()->CreateRet(LLVMValue::jint_constant(0)); | |
353 } |