changeset 1538:48889816f448

Try again
author Gary Benson <gbenson@redhat.com>
date Wed, 19 May 2010 13:09:40 +0100
parents 6fd1ffad34e2
children 3b5edc5db51a
files src/share/vm/shark/sharkInvariants.hpp src/share/vm/shark/sharkTopLevelBlock.cpp src/share/vm/shark/sharkTopLevelBlock.hpp
diffstat 3 files changed, 135 insertions(+), 79 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/shark/sharkInvariants.hpp	Tue May 18 15:39:15 2010 +0100
+++ b/src/share/vm/shark/sharkInvariants.hpp	Wed May 19 13:09:40 2010 +0100
@@ -93,11 +93,14 @@
     return builder()->code_buffer();
   }
 
-  // That well-known class...
+  // Commonly used classes
  protected:
   ciInstanceKlass* java_lang_Object_klass() const {
     return env()->Object_klass();
   }
+  ciInstanceKlass* java_lang_Throwable_klass() const {
+    return env()->Throwable_klass();
+  }
 };
 
 class SharkTargetInvariants : public SharkCompileInvariants {
--- a/src/share/vm/shark/sharkTopLevelBlock.cpp	Tue May 18 15:39:15 2010 +0100
+++ b/src/share/vm/shark/sharkTopLevelBlock.cpp	Wed May 19 13:09:40 2010 +0100
@@ -221,8 +221,11 @@
         successor(i)->enter(this, false);
       }
     }
+    compute_exceptions();
     for (int i = 0; i < num_exceptions(); i++) {
-      exception(i)->enter(this, true);
+      SharkTopLevelBlock *handler = exception(i);
+      if (handler)
+        handler->enter(this, true);
     }
   }
 }
@@ -438,84 +441,123 @@
   builder()->SetInsertPoint(no_exception);
 }
 
-void SharkTopLevelBlock::handle_exception(Value* exception, int action) {
-  if (action & EAM_HANDLE) {
-    // Build a list of exception handlers for this block
-    ciExceptionHandlerStream str(target(), bci());
-    GrowableArray<ciExceptionHandler*>* handlers =
-      new GrowableArray<ciExceptionHandler*>(str.count());
-    for (; !str.is_done(); str.next()) {
-      ciExceptionHandler* handler = str.handler();
-      if (handler->handler_bci() == -1)
+void SharkTopLevelBlock::compute_exceptions() {
+  ciExceptionHandlerStream str(target(), start());
+
+  int exc_count = str.count();
+  _exc_handlers = new GrowableArray<ciExceptionHandler*>(exc_count);
+  _exceptions   = new GrowableArray<SharkTopLevelBlock*>(exc_count);
+
+  int index = 0;
+  for (; !str.is_done(); str.next()) {
+    ciExceptionHandler *handler = str.handler();
+    if (handler->handler_bci() == -1)
+      break;
+    _exc_handlers->append(handler);
+
+    // Try and get this exception's handler from typeflow
+    SharkTopLevelBlock *block = NULL;
+    ciInstanceKlass* klass;
+    if (handler->is_catch_all()) {
+      klass = java_lang_Throwable_klass();
+    }
+    else {
+      klass = handler->catch_klass();
+    }
+    for (int i = 0; i < ciblock()->exceptions()->length(); i++) {
+      if (klass == ciblock()->exc_klasses()->at(i)) {
+        block = function()->block(ciblock()->exceptions()->at(i)->pre_order());
+        assert(block->start() == handler->handler_bci(), "should do");
         break;
-      handlers->append(handler);
+      }
     }
 
-    if (handlers->length() != 0) {
-      // Clear the stack and push the exception onto it.
-      // We do this now to protect it across the VM call
-      // we may be about to make.
-      while (xstack_depth())
-        pop();
-      push(SharkValue::create_jobject(exception, true));
-  
-      int *indexes = NEW_RESOURCE_ARRAY(int, num_exceptions());
-      bool has_catch_all = false;
-  
-      ciExceptionHandlerStream eh_iter(target(), bci());
-      for (int i = 0; i < num_exceptions(); i++, eh_iter.next()) {
-        ciExceptionHandler* handler = eh_iter.handler();
-  
-        if (handler->is_catch_all()) {
-          assert(i == num_exceptions() - 1, "catch-all should be last");
-          has_catch_all = true;
-        }
-        else {
-          indexes[i] = handler->catch_klass_index();
+    // If typeflow let us down then try and figure it out ourselves
+    if (block == NULL) {
+      for (int i = 0; i < function()->block_count(); i++) {
+        SharkTopLevelBlock *candidate = function()->block(i);
+        if (candidate->start() == handler->handler_bci()) {
+          if (block != NULL) {
+            NOT_PRODUCT(warning("there may be trouble ahead"));
+            block = NULL;
+            break;
+          }
+          block = candidate;
         }
       }
-  
-      int num_options = num_exceptions();
-      if (has_catch_all)
-        num_options--;
-  
-      // Drop into the runtime if there are non-catch-all options
-      if (num_options > 0) {
-        Value *index = call_vm(
-          builder()->find_exception_handler(),
-          builder()->CreateInlineData(
-            indexes,
-            num_options * sizeof(int),
-            PointerType::getUnqual(SharkType::jint_type())),
-          LLVMValue::jint_constant(num_options),
-          EX_CHECK_NO_CATCH);
-  
-        // Jump to the exception handler, if found
-        BasicBlock *no_handler = function()->CreateBlock("no_handler");
-        SwitchInst *switchinst = builder()->CreateSwitch(
-          index, no_handler, num_options);
-  
-        for (int i = 0; i < num_options; i++) {
-          SharkTopLevelBlock* handler = this->exception(i);
-  
-          switchinst->addCase(
-            LLVMValue::jint_constant(i),
-            handler->entry_block());
-  
-          handler->add_incoming(current_state());
-        }
-  
-        builder()->SetInsertPoint(no_handler);
+    }
+    _exceptions->append(block);
+  }
+}
+
+void SharkTopLevelBlock::handle_exception(Value* exception, int action) {
+  if (action & EAM_HANDLE && num_exceptions() != 0) {
+    // Clear the stack and push the exception onto it.
+    // We do this now to protect it across the VM call
+    // we may be about to make.
+    while (xstack_depth())
+      pop();
+    push(SharkValue::create_jobject(exception, true));
+
+    int *indexes = NEW_RESOURCE_ARRAY(int, num_exceptions());
+    bool has_catch_all = false;
+
+    ciExceptionHandlerStream eh_iter(target(), bci());
+    for (int i = 0; i < num_exceptions(); i++, eh_iter.next()) {
+      ciExceptionHandler* handler = eh_iter.handler();
+
+      if (handler->is_catch_all()) {
+        assert(i == num_exceptions() - 1, "catch-all should be last");
+        has_catch_all = true;
+      }
+      else {
+        indexes[i] = handler->catch_klass_index();
       }
-  
-      // No specific handler exists, but maybe there's a catch-all
-      if (has_catch_all) {
-        SharkTopLevelBlock* handler = this->exception(num_options);
-  
-        builder()->CreateBr(handler->entry_block());
+    }
+
+    int num_options = num_exceptions();
+    if (has_catch_all)
+      num_options--;
+
+    // Drop into the runtime if there are non-catch-all options
+    if (num_options > 0) {
+      Value *index = call_vm(
+        builder()->find_exception_handler(),
+        builder()->CreateInlineData(
+          indexes,
+          num_options * sizeof(int),
+          PointerType::getUnqual(SharkType::jint_type())),
+        LLVMValue::jint_constant(num_options),
+        EX_CHECK_NO_CATCH);
+
+      // Jump to the exception handler, if found
+      BasicBlock *no_handler = function()->CreateBlock("no_handler");
+      SwitchInst *switchinst = builder()->CreateSwitch(
+        index, no_handler, num_options);
+
+      for (int i = 0; i < num_options; i++) {
+        SharkTopLevelBlock* handler = this->exception(i);
+        if (handler == NULL)
+          Unimplemented();
+
+        switchinst->addCase(
+          LLVMValue::jint_constant(i),
+          handler->entry_block());
+
         handler->add_incoming(current_state());
-        return;
       }
+
+      builder()->SetInsertPoint(no_handler);
+    }
+
+    // No specific handler exists, but maybe there's a catch-all
+    if (has_catch_all) {
+      SharkTopLevelBlock* handler = this->exception(num_options);
+      assert(handler, "no catch all handler?");
+
+      builder()->CreateBr(handler->entry_block());
+      handler->add_incoming(current_state());
+      return;
     }
   }
 
@@ -592,7 +634,8 @@
   }
 
   for (int i = 0; i < num_exceptions(); i++) {
-    if (exception(i)->can_reach_helper(other))
+    SharkTopLevelBlock *handler = exception(i);
+    if (handler && handler->can_reach_helper(other))
       return true;
   }
 
--- a/src/share/vm/shark/sharkTopLevelBlock.hpp	Tue May 18 15:39:15 2010 +0100
+++ b/src/share/vm/shark/sharkTopLevelBlock.hpp	Wed May 19 13:09:40 2010 +0100
@@ -79,12 +79,6 @@
   bool falls_through() const {
     return ciblock()->control() == ciBlock::fall_through_bci;
   }
-  int num_exceptions() const {
-    return ciblock()->exceptions()->length();
-  }
-  SharkTopLevelBlock* exception(int index) const {
-    return function()->block(ciblock()->exceptions()->at(index)->pre_order());
-  }
   int num_successors() const {
     return ciblock()->successors()->length();
   }
@@ -93,6 +87,22 @@
   }
   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 _exceptions->length();
+  }
+  SharkTopLevelBlock* exception(int index) const {
+    return _exceptions->at(index);
+  }
+
   // Traps
  private:
   bool _has_trap;