src/share/vm/shark/sharkTopLevelBlock.hpp

Tue, 18 Jun 2013 12:31:07 -0700

author
johnc
date
Tue, 18 Jun 2013 12:31:07 -0700
changeset 5277
01522ca68fc7
parent 4314
2cd5e15048e6
child 6876
710a3c8b516e
permissions
-rw-r--r--

8015237: Parallelize string table scanning during strong root processing
Summary: Parallelize the scanning of the intern string table by having each GC worker claim a given number of buckets. Changes were also reviewed by Per Liden <per.liden@oracle.com>.
Reviewed-by: tschatzl, stefank, twisti

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

mercurial