Mercurial > hg > truffle
comparison src/share/vm/shark/sharkTopLevelBlock.hpp @ 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 class SharkTopLevelBlock : public SharkBlock { | |
27 public: | |
28 SharkTopLevelBlock(SharkFunction* function, ciTypeFlow::Block* ciblock) | |
29 : SharkBlock(function), | |
30 _function(function), | |
31 _ciblock(ciblock), | |
32 _entered(false), | |
33 _has_trap(false), | |
34 _needs_phis(false), | |
35 _entry_state(NULL), | |
36 _entry_block(NULL) {} | |
37 | |
38 private: | |
39 SharkFunction* _function; | |
40 ciTypeFlow::Block* _ciblock; | |
41 | |
42 public: | |
43 SharkFunction* function() const { | |
44 return _function; | |
45 } | |
46 ciTypeFlow::Block* ciblock() const { | |
47 return _ciblock; | |
48 } | |
49 | |
50 // Function properties | |
51 public: | |
52 SharkStack* stack() const { | |
53 return function()->stack(); | |
54 } | |
55 | |
56 // Typeflow properties | |
57 public: | |
58 int index() const { | |
59 return ciblock()->pre_order(); | |
60 } | |
61 bool is_backedge_copy() const { | |
62 return ciblock()->is_backedge_copy(); | |
63 } | |
64 int stack_depth_at_entry() const { | |
65 return ciblock()->stack_size(); | |
66 } | |
67 ciType* local_type_at_entry(int index) const { | |
68 return ciblock()->local_type_at(index); | |
69 } | |
70 ciType* stack_type_at_entry(int slot) const { | |
71 return ciblock()->stack_type_at(slot); | |
72 } | |
73 int start() const { | |
74 return ciblock()->start(); | |
75 } | |
76 int limit() const { | |
77 return ciblock()->limit(); | |
78 } | |
79 bool falls_through() const { | |
80 return ciblock()->control() == ciBlock::fall_through_bci; | |
81 } | |
82 int num_successors() const { | |
83 return ciblock()->successors()->length(); | |
84 } | |
85 SharkTopLevelBlock* successor(int index) const { | |
86 return function()->block(ciblock()->successors()->at(index)->pre_order()); | |
87 } | |
88 SharkTopLevelBlock* bci_successor(int bci) const; | |
89 | |
90 // Exceptions | |
91 private: | |
92 GrowableArray<ciExceptionHandler*>* _exc_handlers; | |
93 GrowableArray<SharkTopLevelBlock*>* _exceptions; | |
94 | |
95 private: | |
96 void compute_exceptions(); | |
97 | |
98 private: | |
99 int num_exceptions() const { | |
100 return _exc_handlers->length(); | |
101 } | |
102 ciExceptionHandler* exc_handler(int index) const { | |
103 return _exc_handlers->at(index); | |
104 } | |
105 SharkTopLevelBlock* exception(int index) const { | |
106 return _exceptions->at(index); | |
107 } | |
108 | |
109 // Traps | |
110 private: | |
111 bool _has_trap; | |
112 int _trap_request; | |
113 int _trap_bci; | |
114 | |
115 void set_trap(int trap_request, int trap_bci) { | |
116 assert(!has_trap(), "shouldn't have"); | |
117 _has_trap = true; | |
118 _trap_request = trap_request; | |
119 _trap_bci = trap_bci; | |
120 } | |
121 | |
122 private: | |
123 bool has_trap() { | |
124 return _has_trap; | |
125 } | |
126 int trap_request() { | |
127 assert(has_trap(), "should have"); | |
128 return _trap_request; | |
129 } | |
130 int trap_bci() { | |
131 assert(has_trap(), "should have"); | |
132 return _trap_bci; | |
133 } | |
134 | |
135 private: | |
136 void scan_for_traps(); | |
137 | |
138 private: | |
139 bool static_field_ok_in_clinit(ciField* field); | |
140 | |
141 // Entry state | |
142 private: | |
143 bool _entered; | |
144 bool _needs_phis; | |
145 | |
146 public: | |
147 bool entered() const { | |
148 return _entered; | |
149 } | |
150 bool needs_phis() const { | |
151 return _needs_phis; | |
152 } | |
153 | |
154 private: | |
155 void enter(SharkTopLevelBlock* predecessor, bool is_exception); | |
156 | |
157 public: | |
158 void enter() { | |
159 enter(NULL, false); | |
160 } | |
161 | |
162 private: | |
163 SharkState* _entry_state; | |
164 | |
165 private: | |
166 SharkState* entry_state(); | |
167 | |
168 private: | |
169 llvm::BasicBlock* _entry_block; | |
170 | |
171 public: | |
172 llvm::BasicBlock* entry_block() const { | |
173 return _entry_block; | |
174 } | |
175 | |
176 public: | |
177 void initialize(); | |
178 | |
179 public: | |
180 void add_incoming(SharkState* incoming_state); | |
181 | |
182 // Method | |
183 public: | |
184 llvm::Value* method() { | |
185 return current_state()->method(); | |
186 } | |
187 | |
188 // Temporary oop storage | |
189 public: | |
190 void set_oop_tmp(llvm::Value* value) { | |
191 assert(value, "value must be non-NULL (will be reset by get_oop_tmp)"); | |
192 assert(!current_state()->oop_tmp(), "oop_tmp gets and sets must match"); | |
193 current_state()->set_oop_tmp(value); | |
194 } | |
195 llvm::Value* get_oop_tmp() { | |
196 llvm::Value* value = current_state()->oop_tmp(); | |
197 assert(value, "oop_tmp gets and sets must match"); | |
198 current_state()->set_oop_tmp(NULL); | |
199 return value; | |
200 } | |
201 | |
202 // Cache and decache | |
203 private: | |
204 void decache_for_Java_call(ciMethod* callee); | |
205 void cache_after_Java_call(ciMethod* callee); | |
206 void decache_for_VM_call(); | |
207 void cache_after_VM_call(); | |
208 void decache_for_trap(); | |
209 | |
210 // Monitors | |
211 private: | |
212 int num_monitors() { | |
213 return current_state()->num_monitors(); | |
214 } | |
215 int set_num_monitors(int num_monitors) { | |
216 current_state()->set_num_monitors(num_monitors); | |
217 } | |
218 | |
219 // Code generation | |
220 public: | |
221 void emit_IR(); | |
222 | |
223 // Branch helpers | |
224 private: | |
225 void do_branch(int successor_index); | |
226 | |
227 // Zero checks | |
228 private: | |
229 void do_zero_check(SharkValue* value); | |
230 void zero_check_value(SharkValue* value, llvm::BasicBlock* continue_block); | |
231 | |
232 public: | |
233 void do_deferred_zero_check(SharkValue* value, | |
234 int bci, | |
235 SharkState* saved_state, | |
236 llvm::BasicBlock* continue_block); | |
237 // Exceptions | |
238 private: | |
239 llvm::Value* pending_exception_address() const { | |
240 return builder()->CreateAddressOfStructEntry( | |
241 thread(), Thread::pending_exception_offset(), | |
242 llvm::PointerType::getUnqual(SharkType::oop_type()), | |
243 "pending_exception_addr"); | |
244 } | |
245 llvm::LoadInst* get_pending_exception() const { | |
246 return builder()->CreateLoad( | |
247 pending_exception_address(), "pending_exception"); | |
248 } | |
249 void clear_pending_exception() const { | |
250 builder()->CreateStore(LLVMValue::null(), pending_exception_address()); | |
251 } | |
252 public: | |
253 enum ExceptionActionMask { | |
254 // The actual bitmasks that things test against | |
255 EAM_CHECK = 1, // whether to check for pending exceptions | |
256 EAM_HANDLE = 2, // whether to attempt to handle pending exceptions | |
257 EAM_MONITOR_FUDGE = 4, // whether the monitor count needs adjusting | |
258 | |
259 // More convenient values for passing | |
260 EX_CHECK_NONE = 0, | |
261 EX_CHECK_NO_CATCH = EAM_CHECK, | |
262 EX_CHECK_FULL = EAM_CHECK | EAM_HANDLE | |
263 }; | |
264 void check_pending_exception(int action); | |
265 void handle_exception(llvm::Value* exception, int action); | |
266 void marshal_exception_fast(int num_options); | |
267 void marshal_exception_slow(int num_options); | |
268 llvm::BasicBlock* handler_for_exception(int index); | |
269 | |
270 // VM calls | |
271 private: | |
272 llvm::CallInst* call_vm(llvm::Value* callee, | |
273 llvm::Value** args_start, | |
274 llvm::Value** args_end, | |
275 int exception_action) { | |
276 decache_for_VM_call(); | |
277 stack()->CreateSetLastJavaFrame(); | |
278 llvm::CallInst *res = builder()->CreateCall(callee, args_start, args_end); | |
279 stack()->CreateResetLastJavaFrame(); | |
280 cache_after_VM_call(); | |
281 if (exception_action & EAM_CHECK) { | |
282 check_pending_exception(exception_action); | |
283 current_state()->set_has_safepointed(true); | |
284 } | |
285 return res; | |
286 } | |
287 | |
288 public: | |
289 llvm::CallInst* call_vm(llvm::Value* callee, | |
290 int exception_action) { | |
291 llvm::Value *args[] = {thread()}; | |
292 return call_vm(callee, args, args + 1, exception_action); | |
293 } | |
294 llvm::CallInst* call_vm(llvm::Value* callee, | |
295 llvm::Value* arg1, | |
296 int exception_action) { | |
297 llvm::Value *args[] = {thread(), arg1}; | |
298 return call_vm(callee, args, args + 2, exception_action); | |
299 } | |
300 llvm::CallInst* call_vm(llvm::Value* callee, | |
301 llvm::Value* arg1, | |
302 llvm::Value* arg2, | |
303 int exception_action) { | |
304 llvm::Value *args[] = {thread(), arg1, arg2}; | |
305 return call_vm(callee, args, args + 3, exception_action); | |
306 } | |
307 llvm::CallInst* call_vm(llvm::Value* callee, | |
308 llvm::Value* arg1, | |
309 llvm::Value* arg2, | |
310 llvm::Value* arg3, | |
311 int exception_action) { | |
312 llvm::Value *args[] = {thread(), arg1, arg2, arg3}; | |
313 return call_vm(callee, args, args + 4, exception_action); | |
314 } | |
315 | |
316 // VM call oop return handling | |
317 private: | |
318 llvm::LoadInst* get_vm_result() const { | |
319 llvm::Value *addr = builder()->CreateAddressOfStructEntry( | |
320 thread(), JavaThread::vm_result_offset(), | |
321 llvm::PointerType::getUnqual(SharkType::oop_type()), | |
322 "vm_result_addr"); | |
323 llvm::LoadInst *result = builder()->CreateLoad(addr, "vm_result"); | |
324 builder()->CreateStore(LLVMValue::null(), addr); | |
325 return result; | |
326 } | |
327 | |
328 // Synchronization | |
329 private: | |
330 void acquire_lock(llvm::Value* lockee, int exception_action); | |
331 void release_lock(int exception_action); | |
332 | |
333 public: | |
334 void acquire_method_lock(); | |
335 | |
336 // Bounds checks | |
337 private: | |
338 void check_bounds(SharkValue* array, SharkValue* index); | |
339 | |
340 // Safepoints | |
341 private: | |
342 void maybe_add_safepoint(); | |
343 void maybe_add_backedge_safepoint(); | |
344 | |
345 // Loop safepoint removal | |
346 private: | |
347 bool _can_reach_visited; | |
348 | |
349 bool can_reach(SharkTopLevelBlock* other); | |
350 bool can_reach_helper(SharkTopLevelBlock* other); | |
351 | |
352 // Traps | |
353 private: | |
354 llvm::BasicBlock* make_trap(int trap_bci, int trap_request); | |
355 void do_trap(int trap_request); | |
356 | |
357 // Returns | |
358 private: | |
359 void call_register_finalizer(llvm::Value* receiver); | |
360 void handle_return(BasicType type, llvm::Value* exception); | |
361 | |
362 // arraylength | |
363 private: | |
364 void do_arraylength(); | |
365 | |
366 // *aload and *astore | |
367 private: | |
368 void do_aload(BasicType basic_type); | |
369 void do_astore(BasicType basic_type); | |
370 | |
371 // *return and athrow | |
372 private: | |
373 void do_return(BasicType type); | |
374 void do_athrow(); | |
375 | |
376 // goto* | |
377 private: | |
378 void do_goto(); | |
379 | |
380 // jsr* and ret | |
381 private: | |
382 void do_jsr(); | |
383 void do_ret(); | |
384 | |
385 // if* | |
386 private: | |
387 void do_if_helper(llvm::ICmpInst::Predicate p, | |
388 llvm::Value* b, | |
389 llvm::Value* a, | |
390 SharkState* if_taken_state, | |
391 SharkState* not_taken_state); | |
392 void do_if(llvm::ICmpInst::Predicate p, SharkValue* b, SharkValue* a); | |
393 | |
394 // tableswitch and lookupswitch | |
395 private: | |
396 void do_switch(); | |
397 | |
398 // invoke* | |
399 private: | |
400 ciMethod* improve_virtual_call(ciMethod* caller, | |
401 ciInstanceKlass* klass, | |
402 ciMethod* dest_method, | |
403 ciType* receiver_type); | |
404 llvm::Value* get_direct_callee(ciMethod* method); | |
405 llvm::Value* get_virtual_callee(SharkValue* receiver, int vtable_index); | |
406 llvm::Value* get_interface_callee(SharkValue* receiver, ciMethod* method); | |
407 | |
408 void do_call(); | |
409 | |
410 // checkcast and instanceof | |
411 private: | |
412 bool static_subtype_check(ciKlass* check_klass, ciKlass* object_klass); | |
413 void do_full_instance_check(ciKlass* klass); | |
414 void do_trapping_instance_check(ciKlass* klass); | |
415 | |
416 void do_instance_check(); | |
417 bool maybe_do_instanceof_if(); | |
418 | |
419 // new and *newarray | |
420 private: | |
421 void do_new(); | |
422 void do_newarray(); | |
423 void do_anewarray(); | |
424 void do_multianewarray(); | |
425 | |
426 // monitorenter and monitorexit | |
427 private: | |
428 void do_monitorenter(); | |
429 void do_monitorexit(); | |
430 }; |