Mercurial > hg > truffle
annotate src/share/vm/shark/sharkNativeWrapper.cpp @ 3762:5c0a3c1858b1
7048782: CMS: assert(last_chunk_index_to_check<= last_chunk_index) failed: parCardTableModRefBS.cpp:359
Summary: The LNC array is sized before the start of a scavenge, while the heap may expand during a scavenge. With CMS, the last block of an arbitrary suffice of the LNC array may expand due to coalition with the expansion delta. We now take care not to attempt access past the end of the LNC array. LNC array code will be cleaned up and suitably encapsulated as part of the forthcoming performance RFE 7043675.
Reviewed-by: brutisso
author | ysr |
---|---|
date | Thu, 02 Jun 2011 10:23:36 -0700 |
parents | 1d1603768966 |
children | 2cd5e15048e6 |
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 oopmap->set_oop(SharkStack::slot2reg(stack()->method_slot_offset())); | |
63 | |
64 // Set up the oop_tmp slot if required: | |
65 // - For static methods we use it to handlize the class argument | |
66 // for the call, and to protect the same during slow path locks | |
67 // (if synchronized). | |
68 // - For methods returning oops, we use it to protect the return | |
69 // value across safepoints or slow path unlocking. | |
70 if (is_static() || is_returning_oop()) { | |
71 _oop_tmp_slot = stack()->slot_addr( | |
72 stack()->oop_tmp_slot_offset(), | |
73 SharkType::oop_type(), | |
74 "oop_tmp_slot"); | |
75 | |
76 oopmap->set_oop(SharkStack::slot2reg(stack()->oop_tmp_slot_offset())); | |
77 } | |
78 | |
79 // Set up the monitor slot, for synchronized methods | |
80 if (is_synchronized()) { | |
81 Unimplemented(); | |
82 _lock_slot_offset = 23; | |
83 } | |
84 | |
85 // Start building the argument list | |
86 std::vector<const Type*> param_types; | |
87 std::vector<Value*> param_values; | |
88 const PointerType *box_type = PointerType::getUnqual(SharkType::oop_type()); | |
89 | |
90 // First argument is the JNIEnv | |
91 param_types.push_back(SharkType::jniEnv_type()); | |
92 param_values.push_back( | |
93 builder()->CreateAddressOfStructEntry( | |
94 thread, | |
95 JavaThread::jni_environment_offset(), | |
96 SharkType::jniEnv_type(), | |
97 "jni_environment")); | |
98 | |
99 // For static methods, the second argument is the class | |
100 if (is_static()) { | |
101 builder()->CreateStore( | |
102 builder()->CreateInlineOop( | |
103 JNIHandles::make_local( | |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
1972
diff
changeset
|
104 target()->method_holder()->java_mirror())), |
1692 | 105 oop_tmp_slot()); |
106 | |
107 param_types.push_back(box_type); | |
108 param_values.push_back(oop_tmp_slot()); | |
109 | |
110 _receiver_slot_offset = stack()->oop_tmp_slot_offset(); | |
111 } | |
112 else if (is_returning_oop()) { | |
113 // The oop_tmp slot is registered in the oopmap, | |
114 // so we need to clear it. This is one of the | |
115 // mild inefficiencies I mentioned earlier. | |
116 builder()->CreateStore(LLVMValue::null(), oop_tmp_slot()); | |
117 } | |
118 | |
119 // Parse the arguments | |
120 for (int i = 0; i < arg_size(); i++) { | |
121 int slot_offset = stack()->locals_slots_offset() + arg_size() - 1 - i; | |
122 int adjusted_offset = slot_offset; | |
123 BasicBlock *null, *not_null, *merge; | |
124 Value *box; | |
125 PHINode *phi; | |
126 | |
127 switch (arg_type(i)) { | |
128 case T_VOID: | |
129 break; | |
130 | |
131 case T_OBJECT: | |
132 case T_ARRAY: | |
133 null = CreateBlock("null"); | |
134 not_null = CreateBlock("not_null"); | |
135 merge = CreateBlock("merge"); | |
136 | |
137 box = stack()->slot_addr(slot_offset, SharkType::oop_type()); | |
138 builder()->CreateCondBr( | |
139 builder()->CreateICmp( | |
140 ICmpInst::ICMP_EQ, | |
141 builder()->CreateLoad(box), | |
142 LLVMValue::null()), | |
143 null, not_null); | |
144 | |
145 builder()->SetInsertPoint(null); | |
146 builder()->CreateBr(merge); | |
147 | |
148 builder()->SetInsertPoint(not_null); | |
149 builder()->CreateBr(merge); | |
150 | |
151 builder()->SetInsertPoint(merge); | |
152 phi = builder()->CreatePHI(box_type, "boxed_object"); | |
153 phi->addIncoming(ConstantPointerNull::get(box_type), null); | |
154 phi->addIncoming(box, not_null); | |
155 box = phi; | |
156 | |
157 param_types.push_back(box_type); | |
158 param_values.push_back(box); | |
159 | |
160 oopmap->set_oop(SharkStack::slot2reg(slot_offset)); | |
161 | |
162 if (i == 0 && !is_static()) | |
163 _receiver_slot_offset = slot_offset; | |
164 | |
165 break; | |
166 | |
167 case T_LONG: | |
168 case T_DOUBLE: | |
169 adjusted_offset--; | |
170 // fall through | |
171 | |
172 default: | |
173 const Type *param_type = SharkType::to_stackType(arg_type(i)); | |
174 | |
175 param_types.push_back(param_type); | |
176 param_values.push_back( | |
177 builder()->CreateLoad(stack()->slot_addr(adjusted_offset, param_type))); | |
178 } | |
179 } | |
180 | |
181 // The oopmap is now complete, and everything is written | |
182 // into the frame except the PC. | |
183 int pc_offset = code_buffer()->create_unique_offset(); | |
184 | |
185 _oop_maps = new OopMapSet(); | |
186 oop_maps()->add_gc_map(pc_offset, oopmap); | |
187 | |
188 builder()->CreateStore( | |
189 builder()->code_buffer_address(pc_offset), | |
190 stack()->slot_addr(stack()->pc_slot_offset())); | |
191 | |
192 // Set up the Java frame anchor | |
193 stack()->CreateSetLastJavaFrame(); | |
194 | |
195 // Lock if necessary | |
196 if (is_synchronized()) | |
197 Unimplemented(); | |
198 | |
199 // Change the thread state to _thread_in_native | |
200 CreateSetThreadState(_thread_in_native); | |
201 | |
202 // Make the call | |
203 BasicType result_type = target()->result_type(); | |
204 const Type* return_type; | |
205 if (result_type == T_VOID) | |
206 return_type = SharkType::void_type(); | |
207 else if (is_returning_oop()) | |
208 return_type = box_type; | |
209 else | |
210 return_type = SharkType::to_arrayType(result_type); | |
211 Value* native_function = builder()->CreateIntToPtr( | |
212 LLVMValue::intptr_constant((intptr_t) target()->native_function()), | |
213 PointerType::getUnqual( | |
214 FunctionType::get(return_type, param_types, false))); | |
215 Value *result = builder()->CreateCall( | |
216 native_function, param_values.begin(), param_values.end()); | |
217 | |
218 // Start the transition back to _thread_in_Java | |
219 CreateSetThreadState(_thread_in_native_trans); | |
220 | |
221 // Make sure new state is visible in the GC thread | |
222 if (os::is_MP()) { | |
223 if (UseMembar) | |
224 builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD); | |
225 else | |
226 CreateWriteMemorySerializePage(); | |
227 } | |
228 | |
229 // Handle safepoint operations, pending suspend requests, | |
230 // and pending asynchronous exceptions. | |
231 BasicBlock *check_thread = CreateBlock("check_thread"); | |
232 BasicBlock *do_safepoint = CreateBlock("do_safepoint"); | |
233 BasicBlock *safepointed = CreateBlock("safepointed"); | |
234 | |
235 Value *global_state = builder()->CreateLoad( | |
236 builder()->CreateIntToPtr( | |
237 LLVMValue::intptr_constant( | |
238 (intptr_t) SafepointSynchronize::address_of_state()), | |
239 PointerType::getUnqual(SharkType::jint_type())), | |
240 "global_state"); | |
241 | |
242 builder()->CreateCondBr( | |
243 builder()->CreateICmpNE( | |
244 global_state, | |
245 LLVMValue::jint_constant(SafepointSynchronize::_not_synchronized)), | |
246 do_safepoint, check_thread); | |
247 | |
248 builder()->SetInsertPoint(check_thread); | |
249 Value *thread_state = builder()->CreateValueOfStructEntry( | |
250 thread, | |
251 JavaThread::suspend_flags_offset(), | |
252 SharkType::jint_type(), | |
253 "thread_state"); | |
254 | |
255 builder()->CreateCondBr( | |
256 builder()->CreateICmpNE( | |
257 thread_state, | |
258 LLVMValue::jint_constant(0)), | |
259 do_safepoint, safepointed); | |
260 | |
261 builder()->SetInsertPoint(do_safepoint); | |
262 builder()->CreateCall( | |
263 builder()->check_special_condition_for_native_trans(), thread); | |
264 builder()->CreateBr(safepointed); | |
265 | |
266 // Finally we can change the thread state to _thread_in_Java | |
267 builder()->SetInsertPoint(safepointed); | |
268 CreateSetThreadState(_thread_in_Java); | |
269 | |
270 // Clear the frame anchor | |
271 stack()->CreateResetLastJavaFrame(); | |
272 | |
273 // If there is a pending exception then we can just unwind and | |
274 // return. It seems totally wrong that unlocking is skipped here | |
275 // but apparently the template interpreter does this so we do too. | |
276 BasicBlock *exception = CreateBlock("exception"); | |
277 BasicBlock *no_exception = CreateBlock("no_exception"); | |
278 | |
279 builder()->CreateCondBr( | |
280 builder()->CreateICmpEQ( | |
281 CreateLoadPendingException(), | |
282 LLVMValue::null()), | |
283 no_exception, exception); | |
284 | |
285 builder()->SetInsertPoint(exception); | |
286 CreateResetHandleBlock(); | |
287 stack()->CreatePopFrame(0); | |
288 builder()->CreateRet(LLVMValue::jint_constant(0)); | |
289 | |
290 builder()->SetInsertPoint(no_exception); | |
291 | |
292 // If the result was an oop then unbox it before | |
293 // releasing the handle it might be protected by | |
294 if (is_returning_oop()) { | |
295 BasicBlock *null = builder()->GetInsertBlock(); | |
296 BasicBlock *not_null = CreateBlock("not_null"); | |
297 BasicBlock *merge = CreateBlock("merge"); | |
298 | |
299 builder()->CreateCondBr( | |
300 builder()->CreateICmpNE(result, ConstantPointerNull::get(box_type)), | |
301 not_null, merge); | |
302 | |
303 builder()->SetInsertPoint(not_null); | |
304 Value *unboxed_result = builder()->CreateLoad(result); | |
305 builder()->CreateBr(merge); | |
306 | |
307 builder()->SetInsertPoint(merge); | |
308 PHINode *phi = builder()->CreatePHI(SharkType::oop_type(), "result"); | |
309 phi->addIncoming(LLVMValue::null(), null); | |
310 phi->addIncoming(unboxed_result, not_null); | |
311 result = phi; | |
312 } | |
313 | |
314 // Reset handle block | |
315 CreateResetHandleBlock(); | |
316 | |
317 // Unlock if necessary. | |
318 if (is_synchronized()) | |
319 Unimplemented(); | |
320 | |
321 // Unwind and return | |
322 Value *result_addr = stack()->CreatePopFrame(type2size[result_type]); | |
323 if (result_type != T_VOID) { | |
324 bool needs_cast = false; | |
325 bool is_signed = false; | |
326 switch (result_type) { | |
327 case T_BOOLEAN: | |
328 result = builder()->CreateICmpNE(result, LLVMValue::jbyte_constant(0)); | |
329 needs_cast = true; | |
330 break; | |
331 | |
332 case T_CHAR: | |
333 needs_cast = true; | |
334 break; | |
335 | |
336 case T_BYTE: | |
337 case T_SHORT: | |
338 needs_cast = true; | |
339 is_signed = true; | |
340 break; | |
341 } | |
342 if (needs_cast) { | |
343 result = builder()->CreateIntCast( | |
344 result, SharkType::to_stackType(result_type), is_signed); | |
345 } | |
346 | |
347 builder()->CreateStore( | |
348 result, | |
349 builder()->CreateIntToPtr( | |
350 result_addr, | |
351 PointerType::getUnqual(SharkType::to_stackType(result_type)))); | |
352 } | |
353 builder()->CreateRet(LLVMValue::jint_constant(0)); | |
354 } |