src/share/vm/shark/sharkTopLevelBlock.hpp

Wed, 11 Aug 2010 05:51:21 -0700

author
twisti
date
Wed, 11 Aug 2010 05:51:21 -0700
changeset 2047
d2ede61b7a12
child 2314
f95d63e2154a
permissions
-rw-r--r--

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>

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

mercurial