hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp
changeset 6187 4fa7845f7c14
child 7397 5b173b4ca846
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp	Wed Aug 11 05:51:21 2010 -0700
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2008, 2009, 2010 Red Hat, Inc.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+class SharkTopLevelBlock : public SharkBlock {
+ public:
+  SharkTopLevelBlock(SharkFunction* function, ciTypeFlow::Block* ciblock)
+    : SharkBlock(function),
+      _function(function),
+      _ciblock(ciblock),
+      _entered(false),
+      _has_trap(false),
+      _needs_phis(false),
+      _entry_state(NULL),
+      _entry_block(NULL) {}
+
+ private:
+  SharkFunction*     _function;
+  ciTypeFlow::Block* _ciblock;
+
+ public:
+  SharkFunction* function() const {
+    return _function;
+  }
+  ciTypeFlow::Block* ciblock() const {
+    return _ciblock;
+  }
+
+  // Function properties
+ public:
+  SharkStack* stack() const {
+    return function()->stack();
+  }
+
+  // Typeflow properties
+ public:
+  int index() const {
+    return ciblock()->pre_order();
+  }
+  bool is_backedge_copy() const {
+    return ciblock()->is_backedge_copy();
+  }
+  int stack_depth_at_entry() const {
+    return ciblock()->stack_size();
+  }
+  ciType* local_type_at_entry(int index) const {
+    return ciblock()->local_type_at(index);
+  }
+  ciType* stack_type_at_entry(int slot) const {
+    return ciblock()->stack_type_at(slot);
+  }
+  int start() const {
+    return ciblock()->start();
+  }
+  int limit() const {
+    return ciblock()->limit();
+  }
+  bool falls_through() const {
+    return ciblock()->control() == ciBlock::fall_through_bci;
+  }
+  int num_successors() const {
+    return ciblock()->successors()->length();
+  }
+  SharkTopLevelBlock* successor(int index) const {
+    return function()->block(ciblock()->successors()->at(index)->pre_order());
+  }
+  SharkTopLevelBlock* bci_successor(int bci) const;
+
+  // Exceptions
+ private:
+  GrowableArray<ciExceptionHandler*>* _exc_handlers;
+  GrowableArray<SharkTopLevelBlock*>* _exceptions;
+
+ private:
+  void compute_exceptions();
+
+ private:
+  int num_exceptions() const {
+    return _exc_handlers->length();
+  }
+  ciExceptionHandler* exc_handler(int index) const {
+    return _exc_handlers->at(index);
+  }
+  SharkTopLevelBlock* exception(int index) const {
+    return _exceptions->at(index);
+  }
+
+  // Traps
+ private:
+  bool _has_trap;
+  int  _trap_request;
+  int  _trap_bci;
+
+  void set_trap(int trap_request, int trap_bci) {
+    assert(!has_trap(), "shouldn't have");
+    _has_trap     = true;
+    _trap_request = trap_request;
+    _trap_bci     = trap_bci;
+  }
+
+ private:
+  bool has_trap() {
+    return _has_trap;
+  }
+  int trap_request() {
+    assert(has_trap(), "should have");
+    return _trap_request;
+  }
+  int trap_bci() {
+    assert(has_trap(), "should have");
+    return _trap_bci;
+  }
+
+ private:
+  void scan_for_traps();
+
+ private:
+  bool static_field_ok_in_clinit(ciField* field);
+
+  // Entry state
+ private:
+  bool _entered;
+  bool _needs_phis;
+
+ public:
+  bool entered() const {
+    return _entered;
+  }
+  bool needs_phis() const {
+    return _needs_phis;
+  }
+
+ private:
+  void enter(SharkTopLevelBlock* predecessor, bool is_exception);
+
+ public:
+  void enter() {
+    enter(NULL, false);
+  }
+
+ private:
+  SharkState* _entry_state;
+
+ private:
+  SharkState* entry_state();
+
+ private:
+  llvm::BasicBlock* _entry_block;
+
+ public:
+  llvm::BasicBlock* entry_block() const {
+    return _entry_block;
+  }
+
+ public:
+  void initialize();
+
+ public:
+  void add_incoming(SharkState* incoming_state);
+
+  // Method
+ public:
+  llvm::Value* method() {
+    return current_state()->method();
+  }
+
+  // Temporary oop storage
+ public:
+  void set_oop_tmp(llvm::Value* value) {
+    assert(value, "value must be non-NULL (will be reset by get_oop_tmp)");
+    assert(!current_state()->oop_tmp(), "oop_tmp gets and sets must match");
+    current_state()->set_oop_tmp(value);
+  }
+  llvm::Value* get_oop_tmp() {
+    llvm::Value* value = current_state()->oop_tmp();
+    assert(value, "oop_tmp gets and sets must match");
+    current_state()->set_oop_tmp(NULL);
+    return value;
+  }
+
+  // Cache and decache
+ private:
+  void decache_for_Java_call(ciMethod* callee);
+  void cache_after_Java_call(ciMethod* callee);
+  void decache_for_VM_call();
+  void cache_after_VM_call();
+  void decache_for_trap();
+
+  // Monitors
+ private:
+  int num_monitors() {
+    return current_state()->num_monitors();
+  }
+  int set_num_monitors(int num_monitors) {
+    current_state()->set_num_monitors(num_monitors);
+  }
+
+  // Code generation
+ public:
+  void emit_IR();
+
+  // Branch helpers
+ private:
+  void do_branch(int successor_index);
+
+  // Zero checks
+ private:
+  void do_zero_check(SharkValue* value);
+  void zero_check_value(SharkValue* value, llvm::BasicBlock* continue_block);
+
+ public:
+  void do_deferred_zero_check(SharkValue*       value,
+                              int               bci,
+                              SharkState*       saved_state,
+                              llvm::BasicBlock* continue_block);
+  // Exceptions
+ private:
+  llvm::Value* pending_exception_address() const {
+    return builder()->CreateAddressOfStructEntry(
+      thread(), Thread::pending_exception_offset(),
+      llvm::PointerType::getUnqual(SharkType::oop_type()),
+      "pending_exception_addr");
+  }
+  llvm::LoadInst* get_pending_exception() const {
+    return builder()->CreateLoad(
+      pending_exception_address(), "pending_exception");
+  }
+  void clear_pending_exception() const {
+    builder()->CreateStore(LLVMValue::null(), pending_exception_address());
+  }
+ public:
+  enum ExceptionActionMask {
+    // The actual bitmasks that things test against
+    EAM_CHECK         = 1, // whether to check for pending exceptions
+    EAM_HANDLE        = 2, // whether to attempt to handle pending exceptions
+    EAM_MONITOR_FUDGE = 4, // whether the monitor count needs adjusting
+
+    // More convenient values for passing
+    EX_CHECK_NONE     = 0,
+    EX_CHECK_NO_CATCH = EAM_CHECK,
+    EX_CHECK_FULL     = EAM_CHECK | EAM_HANDLE
+  };
+  void check_pending_exception(int action);
+  void handle_exception(llvm::Value* exception, int action);
+  void marshal_exception_fast(int num_options);
+  void marshal_exception_slow(int num_options);
+  llvm::BasicBlock* handler_for_exception(int index);
+
+  // VM calls
+ private:
+  llvm::CallInst* call_vm(llvm::Value*  callee,
+                          llvm::Value** args_start,
+                          llvm::Value** args_end,
+                          int           exception_action) {
+    decache_for_VM_call();
+    stack()->CreateSetLastJavaFrame();
+    llvm::CallInst *res = builder()->CreateCall(callee, args_start, args_end);
+    stack()->CreateResetLastJavaFrame();
+    cache_after_VM_call();
+    if (exception_action & EAM_CHECK) {
+      check_pending_exception(exception_action);
+      current_state()->set_has_safepointed(true);
+    }
+    return res;
+  }
+
+ public:
+  llvm::CallInst* call_vm(llvm::Value* callee,
+                          int          exception_action) {
+    llvm::Value *args[] = {thread()};
+    return call_vm(callee, args, args + 1, exception_action);
+  }
+  llvm::CallInst* call_vm(llvm::Value* callee,
+                          llvm::Value* arg1,
+                          int          exception_action) {
+    llvm::Value *args[] = {thread(), arg1};
+    return call_vm(callee, args, args + 2, exception_action);
+  }
+  llvm::CallInst* call_vm(llvm::Value* callee,
+                          llvm::Value* arg1,
+                          llvm::Value* arg2,
+                          int          exception_action) {
+    llvm::Value *args[] = {thread(), arg1, arg2};
+    return call_vm(callee, args, args + 3, exception_action);
+  }
+  llvm::CallInst* call_vm(llvm::Value* callee,
+                          llvm::Value* arg1,
+                          llvm::Value* arg2,
+                          llvm::Value* arg3,
+                          int          exception_action) {
+    llvm::Value *args[] = {thread(), arg1, arg2, arg3};
+    return call_vm(callee, args, args + 4, exception_action);
+  }
+
+  // VM call oop return handling
+ private:
+  llvm::LoadInst* get_vm_result() const {
+    llvm::Value *addr = builder()->CreateAddressOfStructEntry(
+      thread(), JavaThread::vm_result_offset(),
+      llvm::PointerType::getUnqual(SharkType::oop_type()),
+      "vm_result_addr");
+    llvm::LoadInst *result = builder()->CreateLoad(addr, "vm_result");
+    builder()->CreateStore(LLVMValue::null(), addr);
+    return result;
+  }
+
+  // Synchronization
+ private:
+  void acquire_lock(llvm::Value* lockee, int exception_action);
+  void release_lock(int exception_action);
+
+ public:
+  void acquire_method_lock();
+
+  // Bounds checks
+ private:
+  void check_bounds(SharkValue* array, SharkValue* index);
+
+  // Safepoints
+ private:
+  void maybe_add_safepoint();
+  void maybe_add_backedge_safepoint();
+
+  // Loop safepoint removal
+ private:
+  bool _can_reach_visited;
+
+  bool can_reach(SharkTopLevelBlock* other);
+  bool can_reach_helper(SharkTopLevelBlock* other);
+
+  // Traps
+ private:
+  llvm::BasicBlock* make_trap(int trap_bci, int trap_request);
+  void do_trap(int trap_request);
+
+  // Returns
+ private:
+  void call_register_finalizer(llvm::Value* receiver);
+  void handle_return(BasicType type, llvm::Value* exception);
+
+  // arraylength
+ private:
+  void do_arraylength();
+
+  // *aload and *astore
+ private:
+  void do_aload(BasicType basic_type);
+  void do_astore(BasicType basic_type);
+
+  // *return and athrow
+ private:
+  void do_return(BasicType type);
+  void do_athrow();
+
+  // goto*
+ private:
+  void do_goto();
+
+  // jsr* and ret
+ private:
+  void do_jsr();
+  void do_ret();
+
+  // if*
+ private:
+  void do_if_helper(llvm::ICmpInst::Predicate p,
+                    llvm::Value*              b,
+                    llvm::Value*              a,
+                    SharkState*               if_taken_state,
+                    SharkState*               not_taken_state);
+  void do_if(llvm::ICmpInst::Predicate p, SharkValue* b, SharkValue* a);
+
+  // tableswitch and lookupswitch
+ private:
+  void do_switch();
+
+  // invoke*
+ private:
+  ciMethod* improve_virtual_call(ciMethod*        caller,
+                                 ciInstanceKlass* klass,
+                                 ciMethod*        dest_method,
+                                 ciType*          receiver_type);
+  llvm::Value* get_direct_callee(ciMethod* method);
+  llvm::Value* get_virtual_callee(SharkValue* receiver, int vtable_index);
+  llvm::Value* get_interface_callee(SharkValue* receiver, ciMethod* method);
+
+  void do_call();
+
+  // checkcast and instanceof
+ private:
+  bool static_subtype_check(ciKlass* check_klass, ciKlass* object_klass);
+  void do_full_instance_check(ciKlass* klass);
+  void do_trapping_instance_check(ciKlass* klass);
+
+  void do_instance_check();
+  bool maybe_do_instanceof_if();
+
+  // new and *newarray
+ private:
+  void do_new();
+  void do_newarray();
+  void do_anewarray();
+  void do_multianewarray();
+
+  // monitorenter and monitorexit
+ private:
+  void do_monitorenter();
+  void do_monitorexit();
+};