changeset 1716:b593d3ef9dce

2009-03-04 Gary Benson <gbenson@redhat.com> * ports/hotspot/src/share/vm/shark/sharkInliner.hpp: New file. * ports/hotspot/src/share/vm/shark/sharkInliner.cpp: Likewise. * ports/hotspot/src/share/vm/shark/sharkBlock.hpp: Moved partly into... * ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp: New file. * ports/hotspot/src/share/vm/shark/sharkBlock.cpp: Likewise into... * ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp: New file. * ports/hotspot/src/share/vm/shark/sharkState.hpp: Merged SharkTrackingState into SharkState, and moved SharkEntryState into sharkFunction.cpp and SharkPHIState into sharkTopLevelBlock.cpp. * ports/hotspot/src/share/vm/shark/sharkState.inline.hpp: Likewise. * ports/hotspot/src/share/vm/shark/sharkState.cpp: Likewise. * ports/hotspot/src/share/vm/shark/sharkConstantPool.hpp: s/SharkBlock/SharkTopLevelBlock/g * ports/hotspot/src/share/vm/shark/sharkMonitor.hpp: Likewise. * ports/hotspot/src/share/vm/shark/sharkMonitor.cpp: Likewise. * ports/hotspot/src/share/vm/shark/sharkFunction.hpp: Likewise. * ports/hotspot/src/share/vm/shark/sharkFunction.cpp: Likewise. * ports/hotspot/src/share/vm/shark/shark_globals.hpp (SharkMaxInlineSize): New parameter. * ports/hotspot/src/share/vm/shark/sharkBuilder.hpp (SharkBuilder::GetBlockInsertionPoint): New method. (SharkBuilder::CreateBlock): Likewise. * ports/hotspot/src/share/vm/includeDB_shark: Updated.
author Gary Benson <gbenson@redhat.com>
date Wed, 04 Mar 2009 10:41:13 -0500
parents 22425c2ed9a9
children a737ec21e449
files ChangeLog ports/hotspot/src/share/vm/includeDB_shark ports/hotspot/src/share/vm/shark/sharkBlock.cpp ports/hotspot/src/share/vm/shark/sharkBlock.hpp ports/hotspot/src/share/vm/shark/sharkBuilder.hpp ports/hotspot/src/share/vm/shark/sharkConstantPool.hpp ports/hotspot/src/share/vm/shark/sharkFunction.cpp ports/hotspot/src/share/vm/shark/sharkFunction.hpp ports/hotspot/src/share/vm/shark/sharkInliner.cpp ports/hotspot/src/share/vm/shark/sharkInliner.hpp ports/hotspot/src/share/vm/shark/sharkMonitor.cpp ports/hotspot/src/share/vm/shark/sharkMonitor.hpp ports/hotspot/src/share/vm/shark/sharkState.cpp ports/hotspot/src/share/vm/shark/sharkState.hpp ports/hotspot/src/share/vm/shark/sharkState.inline.hpp ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp ports/hotspot/src/share/vm/shark/shark_globals.hpp
diffstat 18 files changed, 3598 insertions(+), 2557 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Mar 04 11:01:54 2009 +0100
+++ b/ChangeLog	Wed Mar 04 10:41:13 2009 -0500
@@ -1,3 +1,36 @@
+2009-03-04  Gary Benson  <gbenson@redhat.com>
+
+	* ports/hotspot/src/share/vm/shark/sharkInliner.hpp: New file.
+	* ports/hotspot/src/share/vm/shark/sharkInliner.cpp: Likewise.
+
+	* ports/hotspot/src/share/vm/shark/sharkBlock.hpp: Moved partly into...
+	* ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp: New file.
+	* ports/hotspot/src/share/vm/shark/sharkBlock.cpp: Likewise into...
+	* ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp: New file.
+
+	* ports/hotspot/src/share/vm/shark/sharkState.hpp:
+	Merged SharkTrackingState into SharkState, and moved
+	SharkEntryState into sharkFunction.cpp and SharkPHIState
+	into sharkTopLevelBlock.cpp.
+	* ports/hotspot/src/share/vm/shark/sharkState.inline.hpp: Likewise.
+	* ports/hotspot/src/share/vm/shark/sharkState.cpp: Likewise.
+	
+	* ports/hotspot/src/share/vm/shark/sharkConstantPool.hpp:
+	s/SharkBlock/SharkTopLevelBlock/g
+	* ports/hotspot/src/share/vm/shark/sharkMonitor.hpp: Likewise.
+	* ports/hotspot/src/share/vm/shark/sharkMonitor.cpp: Likewise.
+	* ports/hotspot/src/share/vm/shark/sharkFunction.hpp: Likewise.
+	* ports/hotspot/src/share/vm/shark/sharkFunction.cpp: Likewise.
+
+	* ports/hotspot/src/share/vm/shark/shark_globals.hpp
+	(SharkMaxInlineSize): New parameter.
+
+	* ports/hotspot/src/share/vm/shark/sharkBuilder.hpp
+	(SharkBuilder::GetBlockInsertionPoint): New method.
+	(SharkBuilder::CreateBlock): Likewise.
+
+	* ports/hotspot/src/share/vm/includeDB_shark: Updated.
+
 2009-03-04  Matthias Klose  <doko@ubuntu.com>
 
 	* configure.ac: Set version to 1.5pre.
--- a/ports/hotspot/src/share/vm/includeDB_shark	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/includeDB_shark	Wed Mar 04 10:41:13 2009 -0500
@@ -25,6 +25,25 @@
 
 // NOTE: DO NOT CHANGE THIS COPYRIGHT TO NEW STYLE - IT WILL BREAK makeDeps!
 
+sharkBlock.cpp                          debug.hpp
+sharkBlock.cpp                          bytecodes.hpp
+sharkBlock.cpp                          llvmHeaders.hpp
+sharkBlock.cpp                          shark_globals.hpp
+sharkBlock.cpp                          sharkBlock.hpp
+sharkBlock.cpp                          sharkBuilder.hpp
+sharkBlock.cpp                          sharkRuntime.hpp
+sharkBlock.cpp                          sharkState.inline.hpp
+sharkBlock.cpp                          sharkValue.inline.hpp
+
+sharkBlock.hpp                          allocation.hpp
+sharkBlock.hpp                          ciMethod.hpp
+sharkBlock.hpp                          ciStreams.hpp
+sharkBlock.hpp                          debug.hpp
+sharkBlock.hpp                          llvmHeaders.hpp
+sharkBlock.hpp                          sharkBuilder.hpp
+sharkBlock.hpp                          sharkState.hpp
+sharkBlock.hpp                          sharkValue.hpp
+
 ciMethod.cpp                            ciTypeFlow.hpp
 ciMethod.cpp                            methodOop.hpp
 
@@ -63,33 +82,35 @@
 shark_globals.hpp                       shark_globals_<arch>.hpp
 shark_globals.hpp                       globals.hpp
 
-sharkBlock.cpp                          allocation.hpp
-sharkBlock.cpp                          bytecodes.hpp
-sharkBlock.cpp                          ciField.hpp
-sharkBlock.cpp                          ciStreams.hpp
-sharkBlock.cpp                          ciType.hpp
-sharkBlock.cpp                          ciTypeFlow.hpp
-sharkBlock.cpp                          debug.hpp
-sharkBlock.cpp                          llvmHeaders.hpp
-sharkBlock.cpp                          shark_globals.hpp
-sharkBlock.cpp                          sharkBlock.hpp
-sharkBlock.cpp                          sharkBuilder.hpp
-sharkBlock.cpp                          sharkConstantPool.hpp
-sharkBlock.cpp                          sharkRuntime.hpp
-sharkBlock.cpp                          sharkState.inline.hpp
-sharkBlock.cpp                          sharkValue.inline.hpp
+sharkTopLevelBlock.cpp                  allocation.hpp
+sharkTopLevelBlock.cpp                  bytecodes.hpp
+sharkTopLevelBlock.cpp                  ciField.hpp
+sharkTopLevelBlock.cpp                  ciStreams.hpp
+sharkTopLevelBlock.cpp                  ciType.hpp
+sharkTopLevelBlock.cpp                  ciTypeFlow.hpp
+sharkTopLevelBlock.cpp                  debug.hpp
+sharkTopLevelBlock.cpp                  llvmHeaders.hpp
+sharkTopLevelBlock.cpp                  shark_globals.hpp
+sharkTopLevelBlock.cpp                  sharkTopLevelBlock.hpp
+sharkTopLevelBlock.cpp                  sharkBuilder.hpp
+sharkTopLevelBlock.cpp                  sharkConstantPool.hpp
+sharkTopLevelBlock.cpp                  sharkInliner.hpp
+sharkTopLevelBlock.cpp                  sharkRuntime.hpp
+sharkTopLevelBlock.cpp                  sharkState.inline.hpp
+sharkTopLevelBlock.cpp                  sharkValue.inline.hpp
 
-sharkBlock.hpp                          allocation.hpp
-sharkBlock.hpp                          bytecodes.hpp
-sharkBlock.hpp                          ciStreams.hpp
-sharkBlock.hpp                          ciType.hpp
-sharkBlock.hpp                          ciTypeFlow.hpp
-sharkBlock.hpp                          llvmHeaders.hpp
-sharkBlock.hpp                          sharkBuilder.hpp
-sharkBlock.hpp                          sharkFunction.hpp
-sharkBlock.hpp                          sharkMonitor.hpp
-sharkBlock.hpp                          sharkState.hpp
-sharkBlock.hpp                          sharkValue.inline.hpp
+sharkTopLevelBlock.hpp                  allocation.hpp
+sharkTopLevelBlock.hpp                  bytecodes.hpp
+sharkTopLevelBlock.hpp                  ciStreams.hpp
+sharkTopLevelBlock.hpp                  ciType.hpp
+sharkTopLevelBlock.hpp                  ciTypeFlow.hpp
+sharkTopLevelBlock.hpp                  llvmHeaders.hpp
+sharkTopLevelBlock.hpp                  sharkBlock.hpp
+sharkTopLevelBlock.hpp                  sharkBuilder.hpp
+sharkTopLevelBlock.hpp                  sharkFunction.hpp
+sharkTopLevelBlock.hpp                  sharkMonitor.hpp
+sharkTopLevelBlock.hpp                  sharkState.inline.hpp
+sharkTopLevelBlock.hpp                  sharkValue.inline.hpp
 
 sharkBuilder.cpp                        ciMethod.hpp
 sharkBuilder.cpp                        debug.hpp
@@ -163,8 +184,8 @@
 
 sharkConstantPool.hpp                   allocation.hpp
 sharkConstantPool.hpp                   llvmHeaders.hpp
-sharkConstantPool.hpp                   sharkBlock.hpp
 sharkConstantPool.hpp                   sharkBuilder.hpp
+sharkConstantPool.hpp                   sharkTopLevelBlock.hpp
 
 sharkEntry.cpp                          sharkEntry.hpp
 
@@ -175,12 +196,12 @@
 sharkFunction.cpp                       debug.hpp
 sharkFunction.cpp                       llvmHeaders.hpp
 sharkFunction.cpp                       shark_globals.hpp
-sharkFunction.cpp                       sharkBlock.hpp
 sharkFunction.cpp                       sharkBuilder.hpp
 sharkFunction.cpp                       sharkEntry.hpp
 sharkFunction.cpp                       sharkFunction.hpp
 sharkFunction.cpp                       sharkMonitor.hpp
 sharkFunction.cpp                       sharkState.inline.hpp
+sharkFunction.cpp                       sharkTopLevelBlock.hpp
 
 sharkFunction.hpp                       allocation.hpp
 sharkFunction.hpp                       ciEnv.hpp
@@ -189,11 +210,25 @@
 sharkFunction.hpp                       llvmHeaders.hpp
 sharkFunction.hpp                       sharkBuilder.hpp
 
+sharkInliner.cpp                        allocation.hpp
+sharkInliner.cpp                        bytecodes.hpp
+sharkInliner.cpp                        ciField.hpp
+sharkInliner.cpp                        ciMethod.hpp
+sharkInliner.cpp                        ciStreams.hpp
+sharkInliner.cpp                        shark_globals.hpp
+sharkInliner.cpp                        sharkInliner.hpp
+sharkInliner.cpp                        sharkState.inline.hpp
+sharkInliner.cpp                        sharkValue.inline.hpp
+
+sharkInliner.hpp                        allocation.hpp
+sharkInliner.hpp                        ciMethod.hpp
+sharkInliner.hpp                        sharkState.inline.hpp
+
 sharkMonitor.cpp                        llvmHeaders.hpp
-sharkMonitor.cpp                        sharkBlock.hpp
 sharkMonitor.cpp                        sharkMonitor.hpp
 sharkMonitor.cpp                        sharkRuntime.hpp
 sharkMonitor.cpp                        sharkState.inline.hpp
+sharkMonitor.cpp                        sharkTopLevelBlock.hpp
 
 sharkMonitor.hpp                        allocation.hpp
 sharkMonitor.hpp                        llvmHeaders.hpp
@@ -218,21 +253,22 @@
 sharkState.cpp                          allocation.hpp
 sharkState.cpp                          ciType.hpp
 sharkState.cpp                          ciTypeFlow.hpp
-sharkState.cpp                          sharkBlock.hpp
 sharkState.cpp                          sharkBuilder.hpp
+sharkState.cpp                          sharkCacheDecache.hpp
 sharkState.cpp                          sharkState.inline.hpp
+sharkState.cpp                          sharkTopLevelBlock.hpp
 sharkState.cpp                          sharkType.hpp
 sharkState.cpp                          sharkValue.inline.hpp
 
 sharkState.hpp                          allocation.hpp
+sharkState.hpp                          ciMethod.hpp
+sharkState.hpp                          llvmHeaders.hpp
 sharkState.hpp                          sharkBuilder.hpp
-sharkState.hpp                          sharkFunction.hpp
-sharkState.hpp                          sharkValue.inline.hpp
-sharkState.hpp                          vmreg.hpp
+sharkState.hpp                          sharkValue.hpp
 
 sharkState.inline.hpp                   sharkBlock.hpp
+sharkState.inline.hpp                   sharkBuilder.hpp
 sharkState.inline.hpp                   sharkState.hpp
-sharkState.inline.hpp                   sharkCacheDecache.hpp
 
 sharkStateScanner.cpp                   sharkState.inline.hpp
 sharkStateScanner.cpp                   sharkStateScanner.hpp
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.cpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkBlock.cpp	Wed Mar 04 10:41:13 2009 -0500
@@ -25,112 +25,26 @@
 
 #include "incls/_precompiled.incl"
 #include "incls/_sharkBlock.cpp.incl"
-#include "ciArrayKlass.hpp" // XXX fuck you makeDeps
-#include "ciObjArrayKlass.hpp" // XXX likewise
 
 using namespace llvm;
 
-void SharkBlock::enter(SharkBlock* predecessor, bool is_exception)
-{
-  // This block requires phis:
-  //  - if it is entered more than once
-  //  - if it is an exception handler, because in which
-  //    case we assume it's entered more than once.
-  //  - if the predecessor will be compiled after this
-  //    block, in which case we can't simple propagate
-  //    the state forward.
-  if (!needs_phis() &&
-      (entered() ||
-       is_exception ||
-       (predecessor && predecessor->index() >= index())))
-    _needs_phis = true;
-
-  // Recurse into the tree
-  if (!entered()) {
-    _entered = true;
-
-    if (!has_trap()) {
-      for (int i = 0; i < num_successors(); i++) {
-        successor(i)->enter(this, false);
-      }
-      for (int i = 0; i < num_exceptions(); i++) {
-        exception(i)->enter(this, true);
-      }
-    }
-  }
-}
-  
-void SharkBlock::initialize()
-{
-  char name[28];
-  snprintf(name, sizeof(name),
-           "bci_%d%s",
-           start(), is_private_copy() ? "_private_copy" : "");
-  _entry_block = function()->CreateBlock(name);
-}
-
-void SharkBlock::acquire_method_lock()
-{
-  Value *object;
-  if (target()->is_static()) {
-    SharkConstantPool constants(this);
-    object = constants.java_mirror();
-  }
-  else {
-    object = local(0)->jobject_value();
-  }
-  iter()->force_bci(start()); // for the decache
-  function()->monitor(0)->acquire(this, object);
-  check_pending_exception(false);
-}
-
-void SharkBlock::release_method_lock()
-{
-  function()->monitor(0)->release(this);
-
-  // We neither need nor want to check for pending exceptions here.
-  // This method is only called by handle_return, which copes with
-  // them implicitly:
-  //  - if a value is being returned then we just carry on as normal;
-  //    the caller will see the pending exception and handle it.
-  //  - if an exception is being thrown then that exception takes
-  //    priority and ours will be ignored.
-}
-
-void SharkBlock::parse()
+void SharkBlock::parse_bytecode(int start, int limit)
 {
   SharkValue *a, *b, *c, *d;
   int i;
 
-  builder()->SetInsertPoint(entry_block());
-
-  if (has_trap()) {
-    iter()->force_bci(start());
-
-    current_state()->decache_for_trap();
-    builder()->CreateCall2(
-      SharkRuntime::uncommon_trap(),
-      thread(),
-      LLVMValue::jint_constant(trap_index()));
-    builder()->CreateRetVoid();
-    return;
-  }
-
-  iter()->reset_to_bci(start());
-  bool successors_done = false;
-  while (iter()->next() != ciBytecodeStream::EOBC() && bci() < limit()) {
-    NOT_PRODUCT(a = b = c = d = NULL);    
+  iter()->reset_to_bci(start);
+  while (iter()->next_bci() < limit) {
+    NOT_PRODUCT(a = b = c = d = NULL);
+    iter()->next();
 
     if (SharkTraceBytecodes)
       tty->print_cr("%4d: %s", bci(), Bytecodes::name(bc()));
     
-    if(UseLoopSafepoints) {
-      int len;
-
+    if (UseLoopSafepoints) {
       // XXX if a lcmp is followed by an if_?? then C2 maybe-inserts
       // the safepoint before the lcmp rather than before the if.
       // Maybe we should do this too.  See parse2.cpp for details.
-
       switch (bc()) {
       case Bytecodes::_goto:
       case Bytecodes::_ifnull:
@@ -164,15 +78,15 @@
           add_safepoint();
           break;
         }
-        len = switch_table_length();
-        for (i = 0; i < len; i++) {
+        int len = switch_table_length();
+        for (int i = 0; i < len; i++) {
           if (switch_dest(i) <= bci()) {
             add_safepoint();
             break;
           }
         }
         break;
-      }
+      }  
     }
 
     switch (bc()) {
@@ -809,19 +723,16 @@
 
     case Bytecodes::_goto:
     case Bytecodes::_goto_w:
-      builder()->CreateBr(successor(ciTypeFlow::GOTO_TARGET)->entry_block());
+      do_goto();
       break;
 
     case Bytecodes::_jsr:
     case Bytecodes::_jsr_w:
-      push(SharkValue::create_returnAddress(iter()->next_bci()));
-      builder()->CreateBr(successor(ciTypeFlow::GOTO_TARGET)->entry_block());
+      do_jsr();
       break;
 
     case Bytecodes::_ret:
-      assert(local(iter()->get_index())->returnAddress_value() ==
-             successor(ciTypeFlow::GOTO_TARGET)->start(), "should be");
-      builder()->CreateBr(successor(ciTypeFlow::GOTO_TARGET)->entry_block());
+      do_ret();
       break;
 
     case Bytecodes::_ifnull:
@@ -831,11 +742,13 @@
       do_if(ICmpInst::ICMP_NE, SharkValue::null(), pop());
       break;
     case Bytecodes::_if_acmpeq:
-      b = pop(); a = pop();
+      b = pop();
+      a = pop();
       do_if(ICmpInst::ICMP_EQ, b, a);
       break;
     case Bytecodes::_if_acmpne:
-      b = pop(); a = pop();
+      b = pop();
+      a = pop();
       do_if(ICmpInst::ICMP_NE, b, a);
       break;
     case Bytecodes::_ifeq:
@@ -857,34 +770,39 @@
       do_if(ICmpInst::ICMP_SGE, SharkValue::jint_constant(0), pop());
       break;
     case Bytecodes::_if_icmpeq:
-      b = pop(); a = pop();
+      b = pop();
+      a = pop();
       do_if(ICmpInst::ICMP_EQ, b, a);
       break;
     case Bytecodes::_if_icmpne:
-      b = pop(); a = pop();
+      b = pop();
+      a = pop();
       do_if(ICmpInst::ICMP_NE, b, a);
       break;
     case Bytecodes::_if_icmplt:
-      b = pop(); a = pop();
+      b = pop();
+      a = pop();
       do_if(ICmpInst::ICMP_SLT, b, a);
       break;
     case Bytecodes::_if_icmple:
-      b = pop(); a = pop();
+      b = pop();
+      a = pop();
       do_if(ICmpInst::ICMP_SLE, b, a);
       break;
     case Bytecodes::_if_icmpgt:
-      b = pop(); a = pop();
+      b = pop();
+      a = pop();
       do_if(ICmpInst::ICMP_SGT, b, a);
       break;
     case Bytecodes::_if_icmpge:
-      b = pop(); a = pop();
+      b = pop();
+      a = pop();
       do_if(ICmpInst::ICMP_SGE, b, a);
       break;
 
     case Bytecodes::_tableswitch:
     case Bytecodes::_lookupswitch:
       do_switch();
-      successors_done = true;
       break;
 
     case Bytecodes::_invokestatic:
@@ -923,775 +841,11 @@
       ShouldNotReachHere();
     }
   }
-
-  if (falls_through()) {
-    builder()->CreateBr(successor(ciTypeFlow::FALL_THROUGH)->entry_block());
-  }
-
-  if (!successors_done) {
-    for (int i = 0; i < num_successors(); i++)
-      successor(i)->add_incoming(current_state());
-  }
-}
-
-SharkBlock* SharkBlock::bci_successor(int bci) const
-{
-  // XXX now with Linear Search Technology (tm)
-  for (int i = 0; i < num_successors(); i++) {
-    ciTypeFlow::Block *successor = ciblock()->successors()->at(i);
-    if (successor->start() == bci)
-      return function()->block(successor->pre_order());
-  }
-  ShouldNotReachHere();
-}
-
-void SharkBlock::check_zero(SharkValue *value)
-{
-  if (value->zero_checked())
-    return;
-
-  BasicBlock *zero     = function()->CreateBlock("zero");
-  BasicBlock *not_zero = function()->CreateBlock("not_zero");
-
-  Value *a, *b;
-  switch (value->basic_type()) {
-  case T_BYTE:
-  case T_CHAR:
-  case T_SHORT:
-  case T_INT:
-    a = value->jint_value();
-    b = LLVMValue::jint_constant(0);
-    break;
-  case T_LONG:
-    a = value->jlong_value();
-    b = LLVMValue::jlong_constant(0);
-    break;
-  case T_OBJECT:
-  case T_ARRAY:
-    a = value->jobject_value();
-    b = LLVMValue::LLVMValue::null();
-    break;
-  default:
-    tty->print_cr("Unhandled type %s", type2name(value->basic_type()));
-    ShouldNotReachHere();
-  }
-
-  builder()->CreateCondBr(builder()->CreateICmpNE(a, b), not_zero, zero);
-
-  builder()->SetInsertPoint(zero);
-  SharkTrackingState *saved_state = current_state()->copy();
-  if (value->is_jobject()) {
-    call_vm_nocheck(
-      SharkRuntime::throw_NullPointerException(),
-      builder()->pointer_constant(__FILE__),
-      LLVMValue::jint_constant(__LINE__));
-  }
-  else {
-    builder()->CreateUnimplemented(__FILE__, __LINE__);
-  } 
-  handle_exception(function()->CreateGetPendingException());
-  set_current_state(saved_state);  
-
-  builder()->SetInsertPoint(not_zero);
-
-  value->set_zero_checked(true);
-}
-
-void SharkBlock::check_bounds(SharkValue* array, SharkValue* index)
-{
-  BasicBlock *out_of_bounds = function()->CreateBlock("out_of_bounds");
-  BasicBlock *in_bounds     = function()->CreateBlock("in_bounds");
-
-  Value *length = builder()->CreateArrayLength(array->jarray_value());
-  // we use an unsigned comparison to catch negative values
-  builder()->CreateCondBr(
-    builder()->CreateICmpULT(index->jint_value(), length),
-    in_bounds, out_of_bounds);
-
-  builder()->SetInsertPoint(out_of_bounds);
-  SharkTrackingState *saved_state = current_state()->copy();
-  call_vm_nocheck(
-    SharkRuntime::throw_ArrayIndexOutOfBoundsException(),
-    builder()->pointer_constant(__FILE__),
-    LLVMValue::jint_constant(__LINE__),
-    index->jint_value());
-  handle_exception(function()->CreateGetPendingException());
-  set_current_state(saved_state);  
-
-  builder()->SetInsertPoint(in_bounds);
-}
-
-void SharkBlock::check_pending_exception(bool attempt_catch)
-{
-  BasicBlock *exception    = function()->CreateBlock("exception");
-  BasicBlock *no_exception = function()->CreateBlock("no_exception");
-
-  Value *pending_exception_addr = function()->pending_exception_address();
-  Value *pending_exception = builder()->CreateLoad(
-    pending_exception_addr, "pending_exception");
-
-  builder()->CreateCondBr(
-    builder()->CreateICmpEQ(pending_exception, LLVMValue::null()),
-    no_exception, exception);
-
-  builder()->SetInsertPoint(exception);
-  builder()->CreateStore(LLVMValue::null(), pending_exception_addr);
-  SharkTrackingState *saved_state = current_state()->copy();
-  handle_exception(pending_exception, attempt_catch);
-  set_current_state(saved_state);
-
-  builder()->SetInsertPoint(no_exception);
-}
-
-void SharkBlock::handle_exception(Value* exception, bool attempt_catch)
-{
-  if (attempt_catch && 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));
-
-    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();
-      }
-    }
-
-    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 *options = builder()->CreateAlloca(
-        ArrayType::get(SharkType::jint_type(), num_options),
-        LLVMValue::jint_constant(1));
-
-      for (int i = 0; i < num_options; i++)
-        builder()->CreateStore(
-          LLVMValue::jint_constant(indexes[i]),
-          builder()->CreateStructGEP(options, i));
-
-      Value *index = call_vm_nocheck(
-        SharkRuntime::find_exception_handler(),
-        builder()->CreateStructGEP(options, 0),
-        LLVMValue::jint_constant(num_options));
-      check_pending_exception(false);
-
-      // 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++) {
-        SharkBlock* handler = this->exception(i);
-
-        switchinst->addCase(
-          LLVMValue::jint_constant(i),
-          handler->entry_block());
-
-        handler->add_incoming(current_state());
-      }
-
-      builder()->SetInsertPoint(no_handler);
-    }
-
-    // No specific handler exists, but maybe there's a catch-all
-    if (has_catch_all) {
-      SharkBlock* handler = this->exception(num_options);
-
-      builder()->CreateBr(handler->entry_block());
-      handler->add_incoming(current_state());
-      return;
-    }
-  }
-
-  // No exception handler was found; unwind and return
-  handle_return(T_VOID, exception);
-}
-
-void SharkBlock::add_safepoint()
-{
-  BasicBlock *orig_block = builder()->GetInsertBlock();
-  SharkState *orig_state = current_state()->copy();
-
-  BasicBlock *do_safepoint = function()->CreateBlock("do_safepoint");
-  BasicBlock *safepointed  = function()->CreateBlock("safepointed");
-
-  Value *state = builder()->CreateLoad(
-    builder()->CreateIntToPtr(
-      builder()->pointer_constant(SafepointSynchronize::address_of_state()),
-      PointerType::getUnqual(SharkType::jint_type())),
-    "state");
-
-  builder()->CreateCondBr(
-    builder()->CreateICmpEQ(
-      state,
-      LLVMValue::jint_constant(SafepointSynchronize::_synchronizing)),
-    do_safepoint, safepointed);
-
-  builder()->SetInsertPoint(do_safepoint);
-  call_vm(SharkRuntime::safepoint());
-  BasicBlock *safepointed_block = builder()->GetInsertBlock();  
-  builder()->CreateBr(safepointed);
-
-  builder()->SetInsertPoint(safepointed);
-  current_state()->merge(orig_state, orig_block, safepointed_block);
-}
-
-void SharkBlock::call_register_finalizer(Value *receiver)
-{
-  BasicBlock *orig_block = builder()->GetInsertBlock();
-  SharkState *orig_state = current_state()->copy();
-
-  BasicBlock *do_call = function()->CreateBlock("has_finalizer");
-  BasicBlock *done    = function()->CreateBlock("done");
-
-  Value *klass = builder()->CreateValueOfStructEntry(
-    receiver,
-    in_ByteSize(oopDesc::klass_offset_in_bytes()),
-    SharkType::jobject_type(),
-    "klass");
-  
-  Value *klass_part = builder()->CreateAddressOfStructEntry(
-    klass,
-    in_ByteSize(klassOopDesc::klass_part_offset_in_bytes()),
-    SharkType::klass_type(),
-    "klass_part");
-
-  Value *access_flags = builder()->CreateValueOfStructEntry(
-    klass_part,
-    in_ByteSize(Klass::access_flags_offset_in_bytes()),
-    SharkType::jint_type(),
-    "access_flags");
-
-  builder()->CreateCondBr(
-    builder()->CreateICmpNE(
-      builder()->CreateAnd(
-        access_flags,
-        LLVMValue::jint_constant(JVM_ACC_HAS_FINALIZER)),
-      LLVMValue::jint_constant(0)),
-    do_call, done);
-
-  builder()->SetInsertPoint(do_call);
-  call_vm(SharkRuntime::register_finalizer(), receiver);
-  BasicBlock *branch_block = builder()->GetInsertBlock();  
-  builder()->CreateBr(done);
-
-  builder()->SetInsertPoint(done);
-  current_state()->merge(orig_state, orig_block, branch_block);
-}
-
-void SharkBlock::handle_return(BasicType type, Value* exception)
-{
-  assert (exception == NULL || type == T_VOID, "exception OR result, please");
-
-  if (exception)
-    builder()->CreateStore(exception, function()->exception_slot());
-
-  release_locked_monitors();
-  if (target()->is_synchronized())
-    release_method_lock();
-  
-  if (exception) {
-    exception = builder()->CreateLoad(function()->exception_slot());
-    builder()->CreateStore(exception, function()->pending_exception_address());
-  }
-
-  Value *result_addr = function()->CreatePopFrame(type2size[type]);
-  if (type != T_VOID) {
-    SharkValue *result = pop();
-
-#ifdef ASSERT
-    switch (result->basic_type()) {
-    case T_BOOLEAN:
-    case T_BYTE:
-    case T_CHAR:
-    case T_SHORT:
-      assert(type == T_INT, "type mismatch");
-      break;
-
-    case T_ARRAY:
-      assert(type == T_OBJECT, "type mismatch");
-      break;
-
-    default:
-      assert(result->basic_type() == type, "type mismatch");
-    }
-#endif // ASSERT
-
-    builder()->CreateStore(
-      result->generic_value(),
-      builder()->CreateIntToPtr(
-        result_addr,
-        PointerType::getUnqual(SharkType::to_stackType(type))));
-  }
-
-  builder()->CreateRetVoid();
-}
-
-void SharkBlock::release_locked_monitors()
-{
-  int base = target()->is_synchronized();
-  for (int i = function()->monitor_count() - 1; i >= base; i--) {
-    BasicBlock *locked   = function()->CreateBlock("locked");
-    BasicBlock *unlocked = function()->CreateBlock("unlocked");
-
-    Value *object = function()->monitor(i)->object();
-    builder()->CreateCondBr(
-      builder()->CreateICmpNE(object, LLVMValue::null()),
-      locked, unlocked);
-    
-    builder()->SetInsertPoint(locked);
-    builder()->CreateUnimplemented(__FILE__, __LINE__);
-    builder()->CreateUnreachable();
-
-    builder()->SetInsertPoint(unlocked);
-  }
 }
 
-void SharkBlock::do_ldc()
-{
-  SharkValue *value = SharkValue::from_ciConstant(iter()->get_constant());
-  if (value == NULL) {
-    SharkConstantPool constants(this);
-
-    BasicBlock *resolved   = function()->CreateBlock("resolved");
-    BasicBlock *resolved_class = function()->CreateBlock("resolved_class");
-    BasicBlock *unresolved = function()->CreateBlock("unresolved");
-    BasicBlock *unknown    = function()->CreateBlock("unknown");
-    BasicBlock *done       = function()->CreateBlock("done");
-
-    SwitchInst *switchinst = builder()->CreateSwitch(
-      constants.tag_at(iter()->get_constant_index()),
-      unknown, 5);
-
-    switchinst->addCase(
-      LLVMValue::jbyte_constant(JVM_CONSTANT_String), resolved);
-    switchinst->addCase(
-      LLVMValue::jbyte_constant(JVM_CONSTANT_Class), resolved_class);
-    switchinst->addCase(
-      LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedString), unresolved);
-    switchinst->addCase(
-      LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedClass), unresolved);
-    switchinst->addCase(
-      LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedClassInError),
-      unresolved);
-
-    builder()->SetInsertPoint(resolved);
-    Value *resolved_value = constants.object_at(iter()->get_constant_index());
-    builder()->CreateBr(done);
-
-    builder()->SetInsertPoint(resolved_class);
-    Value *resolved_class_value
-      = constants.object_at(iter()->get_constant_index());
-    resolved_class_value
-      = builder()->CreatePtrToInt(resolved_class_value,
-                                  SharkType::intptr_type());
-    resolved_class_value
-      = (builder()->CreateAdd
-         (resolved_class_value,
-          (LLVMValue::intptr_constant
-           (klassOopDesc::klass_part_offset_in_bytes()
-            + Klass::java_mirror_offset_in_bytes()))));
-    resolved_class_value
-      // FIXME: We need a memory barrier before this load.
-      = (builder()->CreateLoad
-         (builder()->CreateIntToPtr
-          (resolved_class_value,
-           PointerType::getUnqual(SharkType::jobject_type()))));
-    builder()->CreateBr(done);
-
-    builder()->SetInsertPoint(unresolved);
-    builder()->CreateUnimplemented(__FILE__, __LINE__);
-    Value *unresolved_value = LLVMValue::null();
-    builder()->CreateBr(done);
-
-    builder()->SetInsertPoint(unknown);
-    builder()->CreateShouldNotReachHere(__FILE__, __LINE__);
-    builder()->CreateUnreachable();
-
-    builder()->SetInsertPoint(done);
-    PHINode *phi = builder()->CreatePHI(SharkType::jobject_type(), "constant");
-    phi->addIncoming(resolved_value, resolved);
-    phi->addIncoming(resolved_class_value, resolved_class);
-    phi->addIncoming(unresolved_value, unresolved);
-    value = SharkValue::create_jobject(phi);
-  }
-  push(value);
-}
-
-void SharkBlock::do_arraylength()
-{
-  SharkValue *array = pop();
-  check_null(array);
-  Value *length = builder()->CreateArrayLength(array->jarray_value());
-  push(SharkValue::create_jint(length));
-}
-
-void SharkBlock::do_aload(BasicType basic_type)
-{
-  SharkValue *index = pop();
-  SharkValue *array = pop();
-
-  assert(array->type()->is_array_klass(), "should be");
-  ciType *element_type = ((ciArrayKlass *) array->type())->element_type();
-  assert((element_type->basic_type() == T_BOOLEAN && basic_type == T_BYTE) ||
-         (element_type->basic_type() == T_ARRAY && basic_type == T_OBJECT) ||
-         (element_type->basic_type() == basic_type), "type mismatch");
-
-  check_null(array);
-  check_bounds(array, index);
-
-  Value *value = builder()->CreateLoad(
-    builder()->CreateArrayAddress(
-      array->jarray_value(), basic_type, index->jint_value()));
-
-  const Type *stack_type = SharkType::to_stackType(basic_type);
-  if (value->getType() != stack_type)
-    value = builder()->CreateIntCast(value, stack_type, basic_type != T_CHAR);
-
-  switch (basic_type) {
-  case T_BYTE:
-  case T_CHAR:
-  case T_SHORT:
-  case T_INT:
-    push(SharkValue::create_jint(value));
-    break;
-
-  case T_LONG:
-    push(SharkValue::create_jlong(value));
-    break;
-
-  case T_FLOAT:
-    push(SharkValue::create_jfloat(value));
-    break;
-
-  case T_DOUBLE:
-    push(SharkValue::create_jdouble(value));
-    break;
-    
-  case T_OBJECT:
-    push(SharkValue::create_generic(element_type, value));
-    break;
-
-  default:
-    tty->print_cr("Unhandled type %s", type2name(basic_type));
-    ShouldNotReachHere();
-  }
-}
-
-void SharkBlock::do_astore(BasicType basic_type)
-{
-  SharkValue *svalue = pop();
-  SharkValue *index  = pop();
-  SharkValue *array  = pop();
-
-  assert(array->type()->is_array_klass(), "should be");
-  ciType *element_type = ((ciArrayKlass *) array->type())->element_type();
-  assert((element_type->basic_type() == T_BOOLEAN && basic_type == T_BYTE) ||
-         (element_type->basic_type() == T_ARRAY && basic_type == T_OBJECT) ||
-         (element_type->basic_type() == basic_type), "type mismatch");
-
-  check_null(array);
-  check_bounds(array, index);
-
-  Value *value;
-  switch (basic_type) {
-  case T_BYTE:
-  case T_CHAR:
-  case T_SHORT:
-  case T_INT:
-    value = svalue->jint_value();
-    break;
-
-  case T_LONG:
-    value = svalue->jlong_value();
-    break;
-
-  case T_FLOAT:
-    value = svalue->jfloat_value();
-    break;
-
-  case T_DOUBLE:
-    value = svalue->jdouble_value();
-    break;
-
-  case T_OBJECT:
-    value = svalue->jobject_value();
-    // XXX assignability check
-    break;
-
-  default:
-    tty->print_cr("Unhandled type %s", type2name(basic_type));
-    ShouldNotReachHere();
-  }
-
-  const Type *array_type = SharkType::to_arrayType(basic_type);
-  if (value->getType() != array_type)
-    value = builder()->CreateIntCast(value, array_type, basic_type != T_CHAR);
-
-  Value *addr = builder()->CreateArrayAddress(
-    array->jarray_value(), basic_type, index->jint_value(), "addr");
-
-  builder()->CreateStore(value, addr);
-
-  if (!element_type->is_primitive_type())
-    builder()->CreateUpdateBarrierSet(oopDesc::bs(), addr);
-}
-
-void SharkBlock::do_div_or_rem(bool is_long, bool is_rem)
+SharkState* SharkBlock::initial_current_state()
 {
-  SharkValue *sb = pop();
-  SharkValue *sa = pop();
-
-  check_divide_by_zero(sb);
-
-  Value *a, *b, *p, *q;
-  if (is_long) {
-    a = sa->jlong_value();
-    b = sb->jlong_value();
-    p = LLVMValue::jlong_constant(0x8000000000000000LL);
-    q = LLVMValue::jlong_constant(-1);
-  }
-  else {
-    a = sa->jint_value();
-    b = sb->jint_value();
-    p = LLVMValue::jint_constant(0x80000000);
-    q = LLVMValue::jint_constant(-1);
-  }
-
-  BasicBlock *special_case = function()->CreateBlock("special_case");
-  BasicBlock *general_case = function()->CreateBlock("general_case");
-  BasicBlock *done         = function()->CreateBlock("done");
-
-  builder()->CreateCondBr(
-    builder()->CreateAnd(
-      builder()->CreateICmpEQ(a, p),
-      builder()->CreateICmpEQ(b, q)),
-    special_case, general_case);
-  
-  builder()->SetInsertPoint(special_case);
-  Value *special_result;
-  if (is_rem) {
-    if (is_long)
-      special_result = LLVMValue::jlong_constant(0);
-    else
-      special_result = LLVMValue::jint_constant(0);
-  }
-  else {
-    special_result = a;
-  }
-  builder()->CreateBr(done);
-
-  builder()->SetInsertPoint(general_case);
-  Value *general_result;
-  if (is_rem)
-    general_result = builder()->CreateSRem(a, b);
-  else
-    general_result = builder()->CreateSDiv(a, b);
-  builder()->CreateBr(done);
-
-  builder()->SetInsertPoint(done);
-  PHINode *result;
-  if (is_long)
-    result = builder()->CreatePHI(SharkType::jlong_type(), "result");
-  else
-    result = builder()->CreatePHI(SharkType::jint_type(), "result");
-  result->addIncoming(special_result, special_case);
-  result->addIncoming(general_result, general_case);
-
-  if (is_long)
-    push(SharkValue::create_jlong(result));
-  else
-    push(SharkValue::create_jint(result));
-}
-
-void SharkBlock::do_field_access(bool is_get, bool is_field, ciField* field)
-{
-  if (field == NULL) {
-    bool will_link;
-    field = iter()->get_field(will_link);
-    assert(will_link, "typeflow responsibility");
-
-    // Check the bytecode matches the field
-    if (is_field == field->is_static())
-      Unimplemented();
-  }
-
-  // Pop the value off the stack where necessary
-  SharkValue *value = NULL;
-  if (!is_get)
-    value = pop();
-
-  // Find the object we're accessing, if necessary
-  Value *object = NULL;
-  if (is_field) {
-    SharkValue *value = pop();
-    check_null(value);
-    object = value->generic_value();
-  }
-  if (is_get && field->is_constant()) {
-    value = SharkValue::from_ciConstant(field->constant_value());
-  }
-  if (!is_get || value == NULL) {
-    if (!is_field) {
-      SharkConstantPool constants(this);
-      Value *cache = constants.cache_entry_at(iter()->get_field_index());
-  
-      object = builder()->CreateValueOfStructEntry(
-       cache, ConstantPoolCacheEntry::f1_offset(),
-       SharkType::jobject_type(),
-       "object");
-    }
-
-    BasicType   basic_type = field->type()->basic_type();
-    const Type *stack_type = SharkType::to_stackType(basic_type);
-    const Type *field_type = SharkType::to_arrayType(basic_type);
-    
-    Value *addr = builder()->CreateAddressOfStructEntry(
-      object, in_ByteSize(field->offset_in_bytes()),
-      PointerType::getUnqual(field_type),
-      "addr");
-  
-    // Do the access
-    if (is_get) {
-      Value *field_value = builder()->CreateLoad(addr);
-
-      if (field_type != stack_type)
-      field_value = builder()->CreateIntCast(
-        field_value, stack_type, basic_type != T_CHAR);
-
-      value = SharkValue::create_generic(field->type(), field_value);
-    }
-    else {
-      Value *field_value = value->generic_value();
-
-      if (field_type != stack_type)
-        field_value = builder()->CreateIntCast(
-          field_value, field_type, basic_type != T_CHAR);
-
-      builder()->CreateStore(field_value, addr);
-      
-      if (!field->type()->is_primitive_type())
-        builder()->CreateUpdateBarrierSet(oopDesc::bs(), addr);
-
-      if (field->is_volatile())
-        builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD);
-    }
-  }
-
-  // Push the value onto the stack where necessary
-  if (is_get)
-    push(value);
-}
-
-void SharkBlock::do_lcmp()
-{
-  Value *b = pop()->jlong_value();
-  Value *a = pop()->jlong_value();
-
-  BasicBlock *ne   = function()->CreateBlock("lcmp_ne");
-  BasicBlock *lt   = function()->CreateBlock("lcmp_lt");
-  BasicBlock *gt   = function()->CreateBlock("lcmp_gt");
-  BasicBlock *done = function()->CreateBlock("done");
-
-  BasicBlock *eq = builder()->GetInsertBlock();
-  builder()->CreateCondBr(builder()->CreateICmpEQ(a, b), done, ne);
-
-  builder()->SetInsertPoint(ne);
-  builder()->CreateCondBr(builder()->CreateICmpSLT(a, b), lt, gt);
-
-  builder()->SetInsertPoint(lt);
-  builder()->CreateBr(done);
-
-  builder()->SetInsertPoint(gt);
-  builder()->CreateBr(done);
-
-  builder()->SetInsertPoint(done);
-  PHINode *result = builder()->CreatePHI(SharkType::jint_type(), "result");
-  result->addIncoming(LLVMValue::jint_constant(-1), lt);
-  result->addIncoming(LLVMValue::jint_constant(0),  eq);
-  result->addIncoming(LLVMValue::jint_constant(1),  gt);
-
-  push(SharkValue::create_jint(result));
-}
-
-void SharkBlock::do_fcmp(bool is_double, bool unordered_is_greater)
-{
-  Value *a, *b;
-  if (is_double) {
-    b = pop()->jdouble_value();
-    a = pop()->jdouble_value();
-  }
-  else {
-    b = pop()->jfloat_value();
-    a = pop()->jfloat_value();
-  }
-
-  BasicBlock *ordered = function()->CreateBlock("ordered");
-  BasicBlock *ge      = function()->CreateBlock("fcmp_ge");
-  BasicBlock *lt      = function()->CreateBlock("fcmp_lt");
-  BasicBlock *eq      = function()->CreateBlock("fcmp_eq");
-  BasicBlock *gt      = function()->CreateBlock("fcmp_gt");
-  BasicBlock *done    = function()->CreateBlock("done");
-
-  builder()->CreateCondBr(
-    builder()->CreateFCmpUNO(a, b),
-    unordered_is_greater ? gt : lt, ordered);
-
-  builder()->SetInsertPoint(ordered);
-  builder()->CreateCondBr(builder()->CreateFCmpULT(a, b), lt, ge);
-
-  builder()->SetInsertPoint(ge);
-  builder()->CreateCondBr(builder()->CreateFCmpUGT(a, b), gt, eq);
-
-  builder()->SetInsertPoint(lt);
-  builder()->CreateBr(done);
-
-  builder()->SetInsertPoint(gt);
-  builder()->CreateBr(done);
-
-  builder()->SetInsertPoint(eq);
-  builder()->CreateBr(done);
-
-  builder()->SetInsertPoint(done);
-  PHINode *result = builder()->CreatePHI(SharkType::jint_type(), "result");
-  result->addIncoming(LLVMValue::jint_constant(-1), lt);
-  result->addIncoming(LLVMValue::jint_constant(0),  eq);
-  result->addIncoming(LLVMValue::jint_constant(1),  gt);
-
-  push(SharkValue::create_jint(result));
-}
-
-void SharkBlock::do_if(ICmpInst::Predicate p, SharkValue *b, SharkValue *a)
-{
-  Value *llvm_a, *llvm_b;
-  if (a->is_jobject()) {
-    llvm_a = a->intptr_value(builder());
-    llvm_b = b->intptr_value(builder());
-  }
-  else {
-    llvm_a = a->jint_value();
-    llvm_b = b->jint_value();
-  }
-                          
-  builder()->CreateCondBr(
-    builder()->CreateICmp(p, llvm_a, llvm_b),
-    successor(ciTypeFlow::IF_TAKEN)->entry_block(),
-    successor(ciTypeFlow::IF_NOT_TAKEN)->entry_block());
+  return new SharkState(entry_state());
 }
 
 int SharkBlock::switch_default_dest()
@@ -1741,1036 +895,340 @@
   } 
 }
 
-void SharkBlock::do_switch()
-{
-  int len = switch_table_length();
-
-  SharkBlock *dest_block = successor(ciTypeFlow::SWITCH_DEFAULT);
-  SwitchInst *switchinst = builder()->CreateSwitch(
-    pop()->jint_value(), dest_block->entry_block(), len);
-  dest_block->add_incoming(current_state());
-
-  for (int i = 0; i < len; i++) {
-    int dest_bci = switch_dest(i);
-    if (dest_bci != switch_default_dest()) {
-      dest_block = bci_successor(dest_bci);
-      switchinst->addCase(
-        LLVMValue::jint_constant(switch_key(i)),
-        dest_block->entry_block());
-      dest_block->add_incoming(current_state());      
-    }
-  }
-}
-
-// Figure out what type of call this is.
-//  - Direct calls are where the callee is fixed.
-//  - Interface and Virtual calls require lookup at runtime.
-// NB some invokevirtuals can be resolved to direct calls.
-SharkBlock::CallType SharkBlock::get_call_type(ciMethod* method)
-{
-  if (bc() == Bytecodes::_invokeinterface)
-    return CALL_INTERFACE;
-  else if (bc() == Bytecodes::_invokevirtual && !method->is_final_method())
-    return CALL_VIRTUAL;
-  else
-    return CALL_DIRECT;
-}
-
-Value *SharkBlock::get_callee(CallType    call_type,
-                              ciMethod*   method,
-                              SharkValue* receiver)
+void SharkBlock::do_div_or_rem(bool is_long, bool is_rem)
 {
-  switch (call_type) {
-  case CALL_DIRECT:
-    return get_direct_callee(method);
-  case CALL_VIRTUAL:
-    return get_virtual_callee(receiver, method);
-  case CALL_INTERFACE:
-    return get_interface_callee(receiver);
-  default:
-    ShouldNotReachHere();
-  } 
-}
+  SharkValue *sb = pop();
+  SharkValue *sa = pop();
+
+  check_divide_by_zero(sb);
 
-// Direct calls can be made when the callee is fixed.
-// invokestatic and invokespecial are always direct;
-// invokevirtual is direct in some circumstances.
-Value *SharkBlock::get_direct_callee(ciMethod* method)
-{
-  SharkConstantPool constants(this);
-  Value *cache = constants.cache_entry_at(iter()->get_method_index());
-  return builder()->CreateValueOfStructEntry(
-    cache,
-    bc() == Bytecodes::_invokevirtual ?
-      ConstantPoolCacheEntry::f2_offset() :
-      ConstantPoolCacheEntry::f1_offset(),
-    SharkType::methodOop_type(),
-    "callee");
-}
-
-// Non-direct virtual calls are handled here
-Value *SharkBlock::get_virtual_callee(SharkValue *receiver, ciMethod* method)
-{
-  Value *klass = builder()->CreateValueOfStructEntry(
-    receiver->jobject_value(),
-    in_ByteSize(oopDesc::klass_offset_in_bytes()),
-    SharkType::jobject_type(),
-    "klass");
-
-  Value *index;
-  if (!method->holder()->is_linked()) {
-    // Yuck, we have to do this one slow :(
-    // XXX should we trap on this?
-    NOT_PRODUCT(warning("unresolved invokevirtual in %s", function()->name()));
-    SharkConstantPool constants(this);
-    Value *cache = constants.cache_entry_at(iter()->get_method_index());
-    index = builder()->CreateValueOfStructEntry(
-      cache, ConstantPoolCacheEntry::f2_offset(),
-      SharkType::intptr_type(),
-      "index");
+  Value *a, *b, *p, *q;
+  if (is_long) {
+    a = sa->jlong_value();
+    b = sb->jlong_value();
+    p = LLVMValue::jlong_constant(0x8000000000000000LL);
+    q = LLVMValue::jlong_constant(-1);
   }
   else {
-    index = LLVMValue::intptr_constant(method->vtable_index());
+    a = sa->jint_value();
+    b = sb->jint_value();
+    p = LLVMValue::jint_constant(0x80000000);
+    q = LLVMValue::jint_constant(-1);
   }
 
-  return builder()->CreateLoad(
-    builder()->CreateArrayAddress(
-      klass,
-      SharkType::methodOop_type(),
-      vtableEntry::size() * wordSize,
-      in_ByteSize(instanceKlass::vtable_start_offset() * wordSize),
-      index),
-    "callee");
-}
-
-// Interpreter-style virtual call lookup
-Value* SharkBlock::get_virtual_callee(Value *cache, SharkValue *receiver)
-{
-  BasicBlock *final      = function()->CreateBlock("final");
-  BasicBlock *not_final  = function()->CreateBlock("not_final");
-  BasicBlock *got_callee = function()->CreateBlock("got_callee");
-
-  Value *flags = builder()->CreateValueOfStructEntry(
-    cache, ConstantPoolCacheEntry::flags_offset(),
-    SharkType::intptr_type(),
-    "flags");
-
-  const int mask = 1 << ConstantPoolCacheEntry::vfinalMethod;
-  builder()->CreateCondBr(
-    builder()->CreateICmpNE(
-      builder()->CreateAnd(flags, LLVMValue::intptr_constant(mask)),
-      LLVMValue::intptr_constant(0)),
-    final, not_final);
+  BasicBlock *ip           = builder()->GetBlockInsertionPoint();
+  BasicBlock *special_case = builder()->CreateBlock(ip, "special_case");
+  BasicBlock *general_case = builder()->CreateBlock(ip, "general_case");
+  BasicBlock *done         = builder()->CreateBlock(ip, "done");
 
-  // For final methods f2 is the actual address of the method
-  builder()->SetInsertPoint(final);
-  Value *final_callee = builder()->CreateValueOfStructEntry(
-    cache, ConstantPoolCacheEntry::f2_offset(),
-    SharkType::methodOop_type(),
-    "final_callee");
-  builder()->CreateBr(got_callee);
-
-  // For non-final methods f2 is the index into the vtable
-  builder()->SetInsertPoint(not_final);
-  Value *klass = builder()->CreateValueOfStructEntry(
-    receiver->jobject_value(),
-    in_ByteSize(oopDesc::klass_offset_in_bytes()),
-    SharkType::jobject_type(),
-    "klass");
+  builder()->CreateCondBr(
+    builder()->CreateAnd(
+      builder()->CreateICmpEQ(a, p),
+      builder()->CreateICmpEQ(b, q)),
+    special_case, general_case);
+  
+  builder()->SetInsertPoint(special_case);
+  Value *special_result;
+  if (is_rem) {
+    if (is_long)
+      special_result = LLVMValue::jlong_constant(0);
+    else
+      special_result = LLVMValue::jint_constant(0);
+  }
+  else {
+    special_result = a;
+  }
+  builder()->CreateBr(done);
 
-  Value *index = builder()->CreateValueOfStructEntry(
-    cache, ConstantPoolCacheEntry::f2_offset(),
-    SharkType::intptr_type(),
-    "index");
+  builder()->SetInsertPoint(general_case);
+  Value *general_result;
+  if (is_rem)
+    general_result = builder()->CreateSRem(a, b);
+  else
+    general_result = builder()->CreateSDiv(a, b);
+  builder()->CreateBr(done);
 
-  Value *nonfinal_callee = builder()->CreateLoad(
-    builder()->CreateArrayAddress(
-      klass,
-      SharkType::methodOop_type(),
-      vtableEntry::size() * wordSize,
-      in_ByteSize(instanceKlass::vtable_start_offset() * wordSize),
-      index),
-    "nonfinal_callee");
-  builder()->CreateBr(got_callee);
+  builder()->SetInsertPoint(done);
+  PHINode *result;
+  if (is_long)
+    result = builder()->CreatePHI(SharkType::jlong_type(), "result");
+  else
+    result = builder()->CreatePHI(SharkType::jint_type(), "result");
+  result->addIncoming(special_result, special_case);
+  result->addIncoming(general_result, general_case);
 
-  builder()->SetInsertPoint(got_callee);
-  PHINode *callee = builder()->CreatePHI(
-    SharkType::methodOop_type(), "callee");
-  callee->addIncoming(final_callee, final);
-  callee->addIncoming(nonfinal_callee, not_final);
-
-  return callee;
+  if (is_long)
+    push(SharkValue::create_jlong(result));
+  else
+    push(SharkValue::create_jint(result));
 }
 
-// Interpreter-style interface call lookup
-Value* SharkBlock::get_interface_callee(SharkValue *receiver)
+void SharkBlock::do_field_access(bool is_get, bool is_field)
 {
-  SharkConstantPool constants(this);
-  Value *cache = constants.cache_entry_at(iter()->get_method_index());
-
-  BasicBlock *hacky      = function()->CreateBlock("hacky");
-  BasicBlock *normal     = function()->CreateBlock("normal");
-  BasicBlock *loop       = function()->CreateBlock("loop");
-  BasicBlock *got_null   = function()->CreateBlock("got_null");
-  BasicBlock *not_null   = function()->CreateBlock("not_null");
-  BasicBlock *next       = function()->CreateBlock("next");
-  BasicBlock *got_entry  = function()->CreateBlock("got_entry");
-  BasicBlock *got_callee = function()->CreateBlock("got_callee");
-
-  Value *flags = builder()->CreateValueOfStructEntry(
-    cache, ConstantPoolCacheEntry::flags_offset(),
-    SharkType::intptr_type(),
-    "flags");
-
-  const int mask = 1 << ConstantPoolCacheEntry::methodInterface;
-  builder()->CreateCondBr(
-    builder()->CreateICmpNE(
-      builder()->CreateAnd(flags, LLVMValue::intptr_constant(mask)),
-      LLVMValue::intptr_constant(0)),
-    hacky, normal);
+  bool will_link;
+  ciField *field = iter()->get_field(will_link);
+  assert(will_link, "typeflow responsibility");
 
-  // Workaround for the case where we encounter an invokeinterface,
-  // but should really have an invokevirtual since the resolved
-  // method is a virtual method in java.lang.Object. This is a
-  // corner case in the spec but is presumably legal, and while
-  // javac does not generate this code there's no reason it could
-  // not be produced by a compliant java compiler.  See
-  // cpCacheOop.cpp for more details.
-  builder()->SetInsertPoint(hacky);
-  Value *hacky_callee = get_virtual_callee(cache, receiver);
-  BasicBlock *got_hacky = builder()->GetInsertBlock();
-  builder()->CreateBr(got_callee);
-
-  // Locate the receiver's itable
-  builder()->SetInsertPoint(normal);
-  Value *object_klass = builder()->CreateValueOfStructEntry(
-    receiver->jobject_value(), in_ByteSize(oopDesc::klass_offset_in_bytes()),
-    SharkType::jobject_type(),
-    "object_klass");
-
-  Value *vtable_start = builder()->CreateAdd(
-    builder()->CreatePtrToInt(object_klass, SharkType::intptr_type()),
-    LLVMValue::intptr_constant(
-      instanceKlass::vtable_start_offset() * HeapWordSize),
-    "vtable_start");
-
-  Value *vtable_length = builder()->CreateValueOfStructEntry(
-    object_klass,
-    in_ByteSize(instanceKlass::vtable_length_offset() * HeapWordSize),
-    SharkType::jint_type(),
-    "vtable_length");
-  vtable_length =
-    builder()->CreateIntCast(vtable_length, SharkType::intptr_type(), false);
+  // Check the bytecode matches the field
+  if (is_field == field->is_static())
+    Unimplemented();
 
-  bool needs_aligning = HeapWordsPerLong > 1;
-  const char *itable_start_name = "itable_start";
-  Value *itable_start = builder()->CreateAdd(
-    vtable_start,
-    builder()->CreateShl(
-      vtable_length,
-      LLVMValue::intptr_constant(exact_log2(vtableEntry::size() * wordSize))),
-    needs_aligning ? "" : itable_start_name);
-  if (needs_aligning)
-    itable_start = builder()->CreateAlign(
-      itable_start, BytesPerLong, itable_start_name);
-
-  // Locate this interface's entry in the table
-  Value *iklass = builder()->CreateValueOfStructEntry(
-    cache, ConstantPoolCacheEntry::f1_offset(),
-    SharkType::jobject_type(),
-    "iklass");
-
-  builder()->CreateBr(loop);
-  builder()->SetInsertPoint(loop);
-  PHINode *itable_entry_addr = builder()->CreatePHI(
-    SharkType::intptr_type(), "itable_entry_addr");
-  itable_entry_addr->addIncoming(itable_start, normal);
-
-  Value *itable_entry = builder()->CreateIntToPtr(
-    itable_entry_addr, SharkType::itableOffsetEntry_type(), "itable_entry");
-
-  Value *itable_iklass = builder()->CreateValueOfStructEntry(
-    itable_entry,
-    in_ByteSize(itableOffsetEntry::interface_offset_in_bytes()),
-    SharkType::jobject_type(),
-    "itable_iklass");
+  // Pop the value off the stack where necessary
+  SharkValue *value = NULL;
+  if (!is_get)
+    value = pop();
 
-  builder()->CreateCondBr(
-    builder()->CreateICmpEQ(itable_iklass, LLVMValue::null()),
-    got_null, not_null);
-
-  // A null entry means that the class doesn't implement the
-  // interface, and wasn't the same as the class checked when
-  // the interface was resolved.
-  builder()->SetInsertPoint(got_null);
-  builder()->CreateUnimplemented(__FILE__, __LINE__);
-  builder()->CreateUnreachable();
-                          
-  builder()->SetInsertPoint(not_null);
-  builder()->CreateCondBr(
-    builder()->CreateICmpEQ(itable_iklass, iklass),
-    got_entry, next);
-
-  builder()->SetInsertPoint(next);
-  Value *next_entry = builder()->CreateAdd(
-    itable_entry_addr,
-    LLVMValue::intptr_constant(itableOffsetEntry::size() * wordSize));
-  builder()->CreateBr(loop);
-  itable_entry_addr->addIncoming(next_entry, next);
-
-  // Locate the method pointer
-  builder()->SetInsertPoint(got_entry);
-  Value *offset = builder()->CreateValueOfStructEntry(
-    itable_entry,
-    in_ByteSize(itableOffsetEntry::offset_offset_in_bytes()),
-    SharkType::jint_type(),
-    "offset");
-  offset =
-    builder()->CreateIntCast(offset, SharkType::intptr_type(), false);
-
-  Value *index = builder()->CreateValueOfStructEntry(
-    cache, ConstantPoolCacheEntry::f2_offset(),
-    SharkType::intptr_type(),
-    "index");
+  // Find the object we're accessing, if necessary
+  Value *object = NULL;
+  if (is_field) {
+    SharkValue *value = pop();
+    check_null(value);
+    object = value->generic_value();
+  }
+  if (is_get && field->is_constant()) {
+    value = SharkValue::from_ciConstant(field->constant_value());
+  }
+  if (!is_get || value == NULL) {
+    if (!is_field)
+      object = lookup_for_field_access();
 
-  Value *normal_callee = builder()->CreateLoad(
-    builder()->CreateIntToPtr(
-      builder()->CreateAdd(
-        builder()->CreateAdd(
-          builder()->CreateAdd(
-            builder()->CreatePtrToInt(
-              object_klass, SharkType::intptr_type()),
-            offset),
-          builder()->CreateShl(
-            index,
-            LLVMValue::intptr_constant(
-              exact_log2(itableMethodEntry::size() * wordSize)))),
-        LLVMValue::intptr_constant(
-          itableMethodEntry::method_offset_in_bytes())),
-      PointerType::getUnqual(SharkType::methodOop_type())),
-    "normal_callee");
-  BasicBlock *got_normal = builder()->GetInsertBlock();
-  builder()->CreateBr(got_callee);
-
-  builder()->SetInsertPoint(got_callee);
-  PHINode *callee = builder()->CreatePHI(
-    SharkType::methodOop_type(), "callee");
-  callee->addIncoming(hacky_callee, got_hacky);
-  callee->addIncoming(normal_callee, got_normal);
-
-  return callee;
-} 
+    BasicType   basic_type = field->type()->basic_type();
+    const Type *stack_type = SharkType::to_stackType(basic_type);
+    const Type *field_type = SharkType::to_arrayType(basic_type);
+    
+    Value *addr = builder()->CreateAddressOfStructEntry(
+      object, in_ByteSize(field->offset_in_bytes()),
+      PointerType::getUnqual(field_type),
+      "addr");
+  
+    // Do the access
+    if (is_get) {
+      Value *field_value = builder()->CreateLoad(addr);
 
-bool SharkBlock::maybe_inline_call(ciMethod *method)
-{
-  // Quick checks to allow us to bail out fast.  We can't inline
-  // native methods, there's no point inlining abstract ones, and
-  // monitors aren't allowed because the inlined section has no
-  // frame to put them in.
-  if (method->is_native() ||
-      method->is_abstract() ||
-      method->is_synchronized() ||
-      method->has_monitor_bytecodes())
-    return false;
-
-  // Inlining empty methods is trivial
-  if (method->is_empty_method()) {
-    int desired_stack_depth = xstack_depth() - method->arg_size();
-    while (xstack_depth() > desired_stack_depth)
-      pop();
-
-    return true;
-  } 
-  
-  // We need to scan the bytecode to do any more, so we bail out
-  // now if the method is too big
-  if (method->code_size() > 5)
-    return false;
-
-  // If the holder isn't linked then there isn't a lot we can do
-  if (!method->holder()->is_linked())
-    return false;
-  
-  // Inspect the method's code to see if we can inline it.  We
-  // don't use method->is_accessor() because that only spots
-  // some getfields, whereas we can inline *all* getfields, all
-  // putfields, and some getstatics too.
-  address code = method->code();
-  switch (method->code_size()) {
-  case 4:
-    // getstatic and putstatic will try to look up the receiver
-    // from the holder's constant pool, which we can't do.  Some
-    // getstatics, however, resolve to constants, and those we
-    // can do.  So we try...
-    if (code[0] == Bytecodes::_getstatic)
-      return maybe_inline_accessor(method, false);
-    break;
+      if (field_type != stack_type)
+      field_value = builder()->CreateIntCast(
+        field_value, stack_type, basic_type != T_CHAR);
 
-  case 5:
-    if (code[0] == Bytecodes::_aload_0 &&
-        (code[1] == Bytecodes::_getfield ||
-         code[1] == Bytecodes::_putfield))
-      return maybe_inline_accessor(method, true);
-    break;
-  }
-  return false;
-}
-
-bool SharkBlock::maybe_inline_accessor(ciMethod *method, bool is_field)
-{
-  if (method->arg_size() != (is_field ? 1 : 0)) {
-    NOT_PRODUCT(warning("wacky accessor in %s", function()->name()));
-    return false;
-  }
-
-  ciBytecodeStream iter(method);
-  Bytecodes::Code bc;
-
-  if (is_field) {
-    bc = iter.next();
-    assert(bc == Bytecodes::_aload_0, "eh?");
-  }
-
-  bool is_get;
-  bc = iter.next();
-  if (is_field) {
-    assert(bc == Bytecodes::_getfield || bc == Bytecodes::_putfield, "eh?");
-    is_get = bc == Bytecodes::_getfield;
-  }
-  else {
-    assert(bc == Bytecodes::_getstatic, "eh?");
-    is_get = true;
-  }
+      value = SharkValue::create_generic(field->type(), field_value);
+    }
+    else {
+      Value *field_value = value->generic_value();
 
-  bool will_link;
-  ciField *field = iter.get_field(will_link);
-  if (!will_link)
-    return false;
-
-  // We can only inline getstatic if the field resolves to a
-  // non-oop constant.
-  if (!is_field) {
-    if (!field->is_constant())
-      return false;
-
-    if (SharkValue::from_ciConstant(field->constant_value()) == NULL)
-      return false;
-  }
+      if (field_type != stack_type)
+        field_value = builder()->CreateIntCast(
+          field_value, field_type, basic_type != T_CHAR);
 
-  // We mustn't inline if the resolved field is the wrong type,
-  // because the thrown exception would appear to come from the
-  // wrong method.
-  if (is_field == field->is_static())
-    return false;
-  
-  bc = iter.next();
-  if (is_get) {
-    switch (bc) {
-    case Bytecodes::_ireturn:
-    case Bytecodes::_lreturn:
-    case Bytecodes::_freturn:
-    case Bytecodes::_dreturn:
-    case Bytecodes::_areturn:
-      break;
+      builder()->CreateStore(field_value, addr);
+      
+      if (!field->type()->is_primitive_type())
+        builder()->CreateUpdateBarrierSet(oopDesc::bs(), addr);
 
-    default:
-      NOT_PRODUCT(warning("wacky accessor in %s", function()->name()));
-      return false;
-    }
-  }
-  else {
-    if (bc != Bytecodes::_return) {
-      NOT_PRODUCT(warning("wacky accessor in %s", function()->name()));
-      return false;
+      if (field->is_volatile())
+        builder()->CreateMemoryBarrier(SharkBuilder::BARRIER_STORELOAD);
     }
   }
 
-  bc = iter.next();
-  assert(bc == ciBytecodeStream::EOBC(), "eh?");
+  // Push the value onto the stack where necessary
+  if (is_get)
+    push(value);
+}
+
+void SharkBlock::do_lcmp()
+{
+  Value *b = pop()->jlong_value();
+  Value *a = pop()->jlong_value();
+
+  BasicBlock *ip   = builder()->GetBlockInsertionPoint();
+  BasicBlock *ne   = builder()->CreateBlock(ip, "lcmp_ne");
+  BasicBlock *lt   = builder()->CreateBlock(ip, "lcmp_lt");
+  BasicBlock *gt   = builder()->CreateBlock(ip, "lcmp_gt");
+  BasicBlock *done = builder()->CreateBlock(ip, "done");
+
+  BasicBlock *eq = builder()->GetInsertBlock();
+  builder()->CreateCondBr(builder()->CreateICmpEQ(a, b), done, ne);
+
+  builder()->SetInsertPoint(ne);
+  builder()->CreateCondBr(builder()->CreateICmpSLT(a, b), lt, gt);
+
+  builder()->SetInsertPoint(lt);
+  builder()->CreateBr(done);
+
+  builder()->SetInsertPoint(gt);
+  builder()->CreateBr(done);
+
+  builder()->SetInsertPoint(done);
+  PHINode *result = builder()->CreatePHI(SharkType::jint_type(), "result");
+  result->addIncoming(LLVMValue::jint_constant(-1), lt);
+  result->addIncoming(LLVMValue::jint_constant(0),  eq);
+  result->addIncoming(LLVMValue::jint_constant(1),  gt);
+
+  push(SharkValue::create_jint(result));
+}
+
+void SharkBlock::do_fcmp(bool is_double, bool unordered_is_greater)
+{
+  Value *a, *b;
+  if (is_double) {
+    b = pop()->jdouble_value();
+    a = pop()->jdouble_value();
+  }
+  else {
+    b = pop()->jfloat_value();
+    a = pop()->jfloat_value();
+  }
+
+  BasicBlock *ip      = builder()->GetBlockInsertionPoint();
+  BasicBlock *ordered = builder()->CreateBlock(ip, "ordered");
+  BasicBlock *ge      = builder()->CreateBlock(ip, "fcmp_ge");
+  BasicBlock *lt      = builder()->CreateBlock(ip, "fcmp_lt");
+  BasicBlock *eq      = builder()->CreateBlock(ip, "fcmp_eq");
+  BasicBlock *gt      = builder()->CreateBlock(ip, "fcmp_gt");
+  BasicBlock *done    = builder()->CreateBlock(ip, "done");
+
+  builder()->CreateCondBr(
+    builder()->CreateFCmpUNO(a, b),
+    unordered_is_greater ? gt : lt, ordered);
+
+  builder()->SetInsertPoint(ordered);
+  builder()->CreateCondBr(builder()->CreateFCmpULT(a, b), lt, ge);
+
+  builder()->SetInsertPoint(ge);
+  builder()->CreateCondBr(builder()->CreateFCmpUGT(a, b), gt, eq);
+
+  builder()->SetInsertPoint(lt);
+  builder()->CreateBr(done);
+
+  builder()->SetInsertPoint(gt);
+  builder()->CreateBr(done);
+
+  builder()->SetInsertPoint(eq);
+  builder()->CreateBr(done);
+
+  builder()->SetInsertPoint(done);
+  PHINode *result = builder()->CreatePHI(SharkType::jint_type(), "result");
+  result->addIncoming(LLVMValue::jint_constant(-1), lt);
+  result->addIncoming(LLVMValue::jint_constant(0),  eq);
+  result->addIncoming(LLVMValue::jint_constant(1),  gt);
 
-  // For field accesses we need to null check the receiver before
-  // entering the inlined section.  For the majority of accessors
-  // this has already been done (in do_call) but if the accessor
-  // was invoked by invokestatic (eg synthetic accessors) then it
-  // may not have been checked and do_field_access will try to do
-  // it and fail.
-  if (is_field) {
-    if (!xstack(0)->zero_checked())
-      return false;
-  }
-  
-  current_state()->enter_inlined_section();
-  do_field_access(is_get, is_field, field);
-  current_state()->leave_inlined_section();
-  return true;
+  push(SharkValue::create_jint(result));
+}
+
+void SharkBlock::emit_IR()
+{
+  ShouldNotCallThis();
+}
+
+SharkState* SharkBlock::entry_state()
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::do_zero_check(SharkValue* value)
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::add_safepoint()
+{
+  ShouldNotCallThis();
+}
+
+Value* SharkBlock::lookup_for_ldc()
+{
+  ShouldNotCallThis();
+}
+
+Value* SharkBlock::lookup_for_field_access()
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::do_arraylength()
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::do_aload(BasicType basic_type)
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::do_astore(BasicType basic_type)
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::do_return(BasicType type)
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::do_athrow()
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::do_goto()
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::do_jsr()
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::do_ret()
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::do_if(ICmpInst::Predicate p, SharkValue* b, SharkValue* a)
+{
+  ShouldNotCallThis();
+}
+
+void SharkBlock::do_switch()
+{
+  ShouldNotCallThis();
 }
 
 void SharkBlock::do_call()
 {
-  bool will_link;
-  ciMethod *method = iter()->get_method(will_link);
-  assert(will_link, "typeflow responsibility");
-
-  // Figure out what type of call this is
-  CallType call_type = get_call_type(method);
-
-  // Find the receiver in the stack.  This has to happen
-  // before we try to inline, because nothing in the inlined
-  // code can decache (which check_null needs to do for the
-  // VM call to throw the NullPointerException).  Once we've
-  // checked, the repeated null check elimination stuff does
-  // the work for us.
-  SharkValue *receiver = NULL;
-  if (bc() != Bytecodes::_invokestatic) {
-    receiver = xstack(method->arg_size() - 1);
-    check_null(receiver);
-  }
-
-  // Try to inline the call
-  if (call_type == CALL_DIRECT) {
-    if (maybe_inline_call(method))
-      return;
-  }
-
-  // Find the method we are calling
-  Value *callee = get_callee(call_type, method, receiver);
-
-  // Load the SharkEntry from the callee
-  Value *base_pc = builder()->CreateValueOfStructEntry(
-    callee, methodOopDesc::from_interpreted_offset(),
-    SharkType::intptr_type(),
-    "base_pc");
-
-  // Load the entry point from the SharkEntry
-  Value *entry_point = builder()->CreateLoad(
-    builder()->CreateIntToPtr(
-      builder()->CreateAdd(
-        base_pc,
-        LLVMValue::intptr_constant(in_bytes(ZeroEntry::entry_point_offset()))),
-      PointerType::getUnqual(
-        PointerType::getUnqual(SharkType::entry_point_type()))),
-    "entry_point");
-
-  // Make the call
-  current_state()->decache_for_Java_call(method);
-  builder()->CreateCall3(entry_point, callee, base_pc, thread());
-  current_state()->cache_after_Java_call(method);
-
-  // Check for pending exceptions
-  check_pending_exception();
+  ShouldNotCallThis();
 }
 
 void SharkBlock::do_instance_check()
 {
-  // Leave the object on the stack until after all the VM calls
-  assert(xstack(0)->is_jobject(), "should be");
-  
-  ciKlass *klass = NULL;
-  if (bc() == Bytecodes::_checkcast) {
-    bool will_link;
-    klass = iter()->get_klass(will_link);
-    if (!will_link) {
-      // XXX why is this not typeflow's responsibility?
-      NOT_PRODUCT(warning("unresolved checkcast in %s", function()->name()));
-      klass = (ciKlass *) xstack(0)->type();
-    }
-  }
-
-  BasicBlock *not_null      = function()->CreateBlock("not_null");
-  BasicBlock *fast_path     = function()->CreateBlock("fast_path");
-  BasicBlock *slow_path     = function()->CreateBlock("slow_path");
-  BasicBlock *got_klass     = function()->CreateBlock("got_klass");
-  BasicBlock *subtype_check = function()->CreateBlock("subtype_check");
-  BasicBlock *is_instance   = function()->CreateBlock("is_instance");
-  BasicBlock *not_instance  = function()->CreateBlock("not_instance");
-  BasicBlock *merge1        = function()->CreateBlock("merge1");
-  BasicBlock *merge2        = function()->CreateBlock("merge2");
-
-  enum InstanceCheckStates {
-    IC_IS_NULL,
-    IC_IS_INSTANCE,
-    IC_NOT_INSTANCE,
-  };
-
-  // Null objects aren't instances of anything
-  builder()->CreateCondBr(
-    builder()->CreateICmpEQ(xstack(0)->jobject_value(), LLVMValue::null()),
-    merge2, not_null);
-  BasicBlock *null_block = builder()->GetInsertBlock();
-  SharkState *null_state = current_state()->copy();
-
-  // Get the class we're checking against
-  builder()->SetInsertPoint(not_null);
-  SharkConstantPool constants(this);
-  Value *tag = constants.tag_at(iter()->get_klass_index());
-  builder()->CreateCondBr(
-    builder()->CreateOr(
-      builder()->CreateICmpEQ(
-        tag, LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedClass)),
-      builder()->CreateICmpEQ(
-        tag, LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedClassInError))),
-    slow_path, fast_path);
-
-  // The fast path
-  builder()->SetInsertPoint(fast_path);
-  BasicBlock *fast_block = builder()->GetInsertBlock();
-  SharkState *fast_state = current_state()->copy();
-  Value *fast_klass = constants.object_at(iter()->get_klass_index());
-  builder()->CreateBr(got_klass);
-
-  // The slow path
-  builder()->SetInsertPoint(slow_path);
-  call_vm(
-    SharkRuntime::resolve_klass(),
-    LLVMValue::jint_constant(iter()->get_klass_index()));
-  Value *slow_klass = function()->CreateGetVMResult();
-  BasicBlock *slow_block = builder()->GetInsertBlock();  
-  builder()->CreateBr(got_klass);
-
-  // We have the class to test against
-  builder()->SetInsertPoint(got_klass);
-  current_state()->merge(fast_state, fast_block, slow_block);
-  PHINode *check_klass = builder()->CreatePHI(
-    SharkType::jobject_type(), "check_klass");
-  check_klass->addIncoming(fast_klass, fast_block);
-  check_klass->addIncoming(slow_klass, slow_block);
-
-  // Get the class of the object being tested
-  Value *object_klass = builder()->CreateValueOfStructEntry(
-    xstack(0)->jobject_value(), in_ByteSize(oopDesc::klass_offset_in_bytes()),
-    SharkType::jobject_type(),
-    "object_klass");
-
-  // Perform the check
-  builder()->CreateCondBr(
-    builder()->CreateICmpEQ(check_klass, object_klass),
-    is_instance, subtype_check);
-
-  builder()->SetInsertPoint(subtype_check);
-  builder()->CreateCondBr(
-    builder()->CreateICmpNE(
-      builder()->CreateCall2(
-        SharkRuntime::is_subtype_of(), check_klass, object_klass),
-      LLVMValue::jbyte_constant(0)),
-    is_instance, not_instance);
-
-  builder()->SetInsertPoint(is_instance);
-  builder()->CreateBr(merge1);
-
-  builder()->SetInsertPoint(not_instance);
-  builder()->CreateBr(merge1);
-
-  // First merge
-  builder()->SetInsertPoint(merge1);
-  PHINode *nonnull_result = builder()->CreatePHI(
-    SharkType::jint_type(), "nonnull_result");
-  nonnull_result->addIncoming(
-    LLVMValue::jint_constant(IC_IS_INSTANCE), is_instance);
-  nonnull_result->addIncoming(
-    LLVMValue::jint_constant(IC_NOT_INSTANCE), not_instance);
-  BasicBlock *nonnull_block = builder()->GetInsertBlock();
-  builder()->CreateBr(merge2);
-  
-  // Second merge
-  builder()->SetInsertPoint(merge2);
-  current_state()->merge(null_state, null_block, nonnull_block);
-  PHINode *result = builder()->CreatePHI(
-    SharkType::jint_type(), "result");
-  result->addIncoming(LLVMValue::jint_constant(IC_IS_NULL), null_block);
-  result->addIncoming(nonnull_result, nonnull_block);
-
-  // We can finally pop the object!
-  Value *object = pop()->jobject_value();
-
-  // Handle the result
-  if (bc() == Bytecodes::_checkcast) {
-    BasicBlock *failure = function()->CreateBlock("failure");
-    BasicBlock *success = function()->CreateBlock("success");
-
-    builder()->CreateCondBr(
-      builder()->CreateICmpNE(
-        result, LLVMValue::jint_constant(IC_NOT_INSTANCE)),
-      success, failure);
-
-    builder()->SetInsertPoint(failure);
-    builder()->CreateUnimplemented(__FILE__, __LINE__);
-    builder()->CreateUnreachable();
-
-    builder()->SetInsertPoint(success);
-    push(SharkValue::create_generic(klass, object));
-  }
-  else {
-    push(
-      SharkValue::create_jint(
-        builder()->CreateIntCast(
-          builder()->CreateICmpEQ(
-            result, LLVMValue::jint_constant(IC_IS_INSTANCE)),
-          SharkType::jint_type(), false)));
-  }
+  ShouldNotCallThis();
 }
 
 void SharkBlock::do_new()
 {
-  bool will_link;
-  ciInstanceKlass* klass = iter()->get_klass(will_link)->as_instance_klass();
-  assert(will_link, "typeflow responsibility");
-
-  BasicBlock *tlab_alloc          = NULL;
-  BasicBlock *got_tlab            = NULL;
-  BasicBlock *heap_alloc          = NULL;
-  BasicBlock *retry               = NULL;
-  BasicBlock *got_heap            = NULL;
-  BasicBlock *initialize          = NULL;
-  BasicBlock *got_fast            = NULL;
-  BasicBlock *slow_alloc_and_init = NULL;
-  BasicBlock *got_slow            = NULL;
-  BasicBlock *push_object         = NULL;
-
-  SharkState *fast_state = NULL;
-  
-  Value *tlab_object = NULL;
-  Value *heap_object = NULL;
-  Value *fast_object = NULL;
-  Value *slow_object = NULL;
-  Value *object      = NULL;
-
-  SharkConstantPool constants(this);
-
-  // The fast path
-  if (!Klass::layout_helper_needs_slow_path(klass->layout_helper())) {
-    if (UseTLAB) {
-      tlab_alloc        = function()->CreateBlock("tlab_alloc");
-      got_tlab          = function()->CreateBlock("got_tlab");
-    }
-    heap_alloc          = function()->CreateBlock("heap_alloc");
-    retry               = function()->CreateBlock("retry");
-    got_heap            = function()->CreateBlock("got_heap");
-    initialize          = function()->CreateBlock("initialize");
-    slow_alloc_and_init = function()->CreateBlock("slow_alloc_and_init");
-    push_object         = function()->CreateBlock("push_object");
-
-    builder()->CreateCondBr(
-      builder()->CreateICmpEQ(
-        constants.tag_at(iter()->get_klass_index()),
-        LLVMValue::jbyte_constant(JVM_CONSTANT_Class)),
-      UseTLAB ? tlab_alloc : heap_alloc, slow_alloc_and_init);
-    
-    size_t size_in_bytes = klass->size_helper() << LogHeapWordSize;
-
-    // Thread local allocation
-    if (UseTLAB) {
-      builder()->SetInsertPoint(tlab_alloc);
-
-      Value *top_addr = builder()->CreateAddressOfStructEntry(
-        thread(), Thread::tlab_top_offset(),
-        PointerType::getUnqual(SharkType::intptr_type()),
-        "top_addr");
-
-      Value *end = builder()->CreateValueOfStructEntry(
-        thread(), Thread::tlab_end_offset(),
-        SharkType::intptr_type(),
-        "end");
-
-      Value *old_top = builder()->CreateLoad(top_addr, "old_top");
-      Value *new_top = builder()->CreateAdd(
-        old_top, LLVMValue::intptr_constant(size_in_bytes));
-
-      builder()->CreateCondBr(
-        builder()->CreateICmpULE(new_top, end),
-        got_tlab, heap_alloc);
-
-      builder()->SetInsertPoint(got_tlab);
-      tlab_object = builder()->CreateIntToPtr(
-        old_top, SharkType::jobject_type(), "tlab_object");
-
-      builder()->CreateStore(new_top, top_addr);
-      builder()->CreateBr(initialize);
-    }
-
-    // Heap allocation
-    builder()->SetInsertPoint(heap_alloc);
-
-    Value *top_addr = builder()->CreateIntToPtr(
-	builder()->pointer_constant(Universe::heap()->top_addr()),
-      PointerType::getUnqual(SharkType::intptr_type()),
-      "top_addr");
-
-    Value *end = builder()->CreateLoad(
-      builder()->CreateIntToPtr(
-        builder()->pointer_constant(Universe::heap()->end_addr()),
-        PointerType::getUnqual(SharkType::intptr_type())),
-      "end");
-
-    builder()->CreateBr(retry);
-    builder()->SetInsertPoint(retry);
-
-    Value *old_top = builder()->CreateLoad(top_addr, "top");
-    Value *new_top = builder()->CreateAdd(
-      old_top, LLVMValue::intptr_constant(size_in_bytes));
-
-    builder()->CreateCondBr(
-      builder()->CreateICmpULE(new_top, end),
-      got_heap, slow_alloc_and_init);
-
-    builder()->SetInsertPoint(got_heap);
-    heap_object = builder()->CreateIntToPtr(
-      old_top, SharkType::jobject_type(), "heap_object");
-
-    Value *check = builder()->CreateCmpxchgPtr(new_top, top_addr, old_top);
-    builder()->CreateCondBr(
-      builder()->CreateICmpEQ(old_top, check),
-      initialize, retry);
-
-    // Initialize the object
-    builder()->SetInsertPoint(initialize);
-    if (tlab_object) {
-      PHINode *phi = builder()->CreatePHI(
-        SharkType::jobject_type(), "fast_object");
-      phi->addIncoming(tlab_object, got_tlab);
-      phi->addIncoming(heap_object, got_heap);
-      fast_object = phi;
-    }
-    else {
-      fast_object = heap_object;
-    }
-
-    builder()->CreateMemset(
-      builder()->CreateBitCast(
-        fast_object, PointerType::getUnqual(SharkType::jbyte_type())),
-      LLVMValue::jbyte_constant(0),
-      LLVMValue::jint_constant(size_in_bytes),
-      LLVMValue::jint_constant(HeapWordSize));
-
-    Value *mark_addr = builder()->CreateAddressOfStructEntry(
-      fast_object, in_ByteSize(oopDesc::mark_offset_in_bytes()),
-      PointerType::getUnqual(SharkType::intptr_type()),
-      "mark_addr");
-
-    Value *klass_addr = builder()->CreateAddressOfStructEntry(
-      fast_object, in_ByteSize(oopDesc::klass_offset_in_bytes()),
-      PointerType::getUnqual(SharkType::jobject_type()),
-      "klass_addr");
-
-    // Set the mark
-    intptr_t mark;
-    if (UseBiasedLocking) {
-      Unimplemented();
-    }
-    else {
-      mark = (intptr_t) markOopDesc::prototype();
-    }
-    builder()->CreateStore(LLVMValue::intptr_constant(mark), mark_addr);
-
-    // Set the class
-    Value *rtklass = constants.object_at(iter()->get_klass_index());
-    builder()->CreateStore(rtklass, klass_addr);
-    got_fast = builder()->GetInsertBlock();
-
-    builder()->CreateBr(push_object);
-    builder()->SetInsertPoint(slow_alloc_and_init);
-    fast_state = current_state()->copy();
-  }
-
-  // The slow path
-  call_vm(
-    SharkRuntime::new_instance(),
-    LLVMValue::jint_constant(iter()->get_klass_index()));
-  slow_object = function()->CreateGetVMResult();
-  got_slow = builder()->GetInsertBlock();
-
-  // Push the object
-  if (push_object) {
-    builder()->CreateBr(push_object);
-    builder()->SetInsertPoint(push_object);
-  }
-  if (fast_object) {
-    PHINode *phi = builder()->CreatePHI(SharkType::jobject_type(), "object");
-    phi->addIncoming(fast_object, got_fast);
-    phi->addIncoming(slow_object, got_slow);
-    object = phi;
-    current_state()->merge(fast_state, got_fast, got_slow);
-  }
-  else {
-    object = slow_object;
-  }
-
-  SharkValue *result = SharkValue::create_jobject(object);
-  result->set_zero_checked(true);
-  push(result);
+  ShouldNotCallThis();
 }
 
 void SharkBlock::do_newarray()
 {
-  BasicType type = (BasicType) iter()->get_index();
-
-  call_vm(
-    SharkRuntime::newarray(),
-    LLVMValue::jint_constant(type),
-    pop()->jint_value());
-
-  SharkValue *result = SharkValue::create_generic(
-    ciArrayKlass::make(ciType::make(type)),
-    function()->CreateGetVMResult());
-  result->set_zero_checked(true);
-  push(result);
+  ShouldNotCallThis();
 }
 
 void SharkBlock::do_anewarray()
 {
-  bool will_link;
-  ciKlass *klass = iter()->get_klass(will_link);
-  assert(will_link, "typeflow responsibility");
-
-  ciObjArrayKlass *array_klass = ciObjArrayKlass::make(klass);
-  if (!array_klass->is_loaded()) {
-    Unimplemented();
-  }
-
-  call_vm(
-    SharkRuntime::anewarray(),
-    LLVMValue::jint_constant(iter()->get_klass_index()),
-    pop()->jint_value());
-
-  SharkValue *result = SharkValue::create_generic(
-    array_klass, function()->CreateGetVMResult());
-  result->set_zero_checked(true);
-  push(result);
+  ShouldNotCallThis();
 }
 
 void SharkBlock::do_multianewarray()
 {
-  bool will_link;
-  ciArrayKlass *array_klass = iter()->get_klass(will_link)->as_array_klass();
-  assert(will_link, "typeflow responsibility");
-
-  // The dimensions are stack values, so we use their slots for the
-  // dimensions array.  Note that we are storing them in the reverse
-  // of normal stack order.
-  int ndims = iter()->get_dimensions();
-
-  Value *dimensions = function()->CreateAddressOfFrameEntry(
-    function()->stack_slots_offset() + max_stack() - xstack_depth(),
-    ArrayType::get(SharkType::jint_type(), ndims),
-    "dimensions");
-
-  for (int i = 0; i < ndims; i++) {
-    builder()->CreateStore(
-      xstack(ndims - 1 - i)->jint_value(),
-      builder()->CreateStructGEP(dimensions, i));
-  }
-
-  call_vm(
-    SharkRuntime::multianewarray(),
-    LLVMValue::jint_constant(iter()->get_klass_index()),
-    LLVMValue::jint_constant(ndims),
-    builder()->CreateStructGEP(dimensions, 0));
-
-  // Now we can pop the dimensions off the stack
-  for (int i = 0; i < ndims; i++)
-    pop();
-
-  SharkValue *result = SharkValue::create_generic(
-    array_klass, function()->CreateGetVMResult());
-  result->set_zero_checked(true);
-  push(result);
+  ShouldNotCallThis();
 }
 
 void SharkBlock::do_monitorenter()
 {
-  SharkValue *lockee = pop();
-  check_null(lockee);
-  Value *object = lockee->jobject_value();
-
-  // Find a free monitor, or one already allocated for this object
-  BasicBlock *loop_top    = function()->CreateBlock("loop_top");
-  BasicBlock *loop_iter   = function()->CreateBlock("loop_iter");
-  BasicBlock *loop_check  = function()->CreateBlock("loop_check");
-  BasicBlock *no_monitor  = function()->CreateBlock("no_monitor");
-  BasicBlock *got_monitor = function()->CreateBlock("got_monitor");
-
-  BasicBlock *entry_block = builder()->GetInsertBlock();
-  builder()->CreateBr(loop_check);
-
-  builder()->SetInsertPoint(loop_check);
-  PHINode *index = builder()->CreatePHI(SharkType::jint_type(), "index");
-  index->addIncoming(
-    LLVMValue::jint_constant(function()->monitor_count() - 1), entry_block);
-  builder()->CreateCondBr(
-    builder()->CreateICmpUGE(index, LLVMValue::jint_constant(0)),
-    loop_top, no_monitor);
-
-  builder()->SetInsertPoint(loop_top);
-  SharkMonitor* monitor = function()->monitor(index);
-  Value *smo = monitor->object();
-  builder()->CreateCondBr(
-    builder()->CreateOr(
-      builder()->CreateICmpEQ(smo, LLVMValue::null()),
-      builder()->CreateICmpEQ(smo, object)),
-    got_monitor, loop_iter);
-
-  builder()->SetInsertPoint(loop_iter);
-  index->addIncoming(
-    builder()->CreateSub(index, LLVMValue::jint_constant(1)), loop_iter);
-  builder()->CreateBr(loop_check);
-
-  builder()->SetInsertPoint(no_monitor);
-  builder()->CreateShouldNotReachHere(__FILE__, __LINE__);
-  builder()->CreateUnreachable();
-
-  // Acquire the lock
-  builder()->SetInsertPoint(got_monitor);
-  monitor->acquire(this, object);
-  check_pending_exception();
+  ShouldNotCallThis();
 }
 
 void SharkBlock::do_monitorexit()
 {
-  SharkValue *lockee = pop();
-  // The monitorexit can't throw an NPE because the verifier checks
-  // that the monitor operations are block structured before we
-  // compile.
-  // check_null(lockee);
-  Value *object = lockee->jobject_value();
-
-  // Find the monitor associated with this object
-  BasicBlock *loop_top    = function()->CreateBlock("loop_top");
-  BasicBlock *loop_iter   = function()->CreateBlock("loop_iter");
-  BasicBlock *loop_check  = function()->CreateBlock("loop_check");
-  BasicBlock *no_monitor  = function()->CreateBlock("no_monitor");
-  BasicBlock *got_monitor = function()->CreateBlock("got_monitor");
-
-  BasicBlock *entry_block = builder()->GetInsertBlock();
-  builder()->CreateBr(loop_check);
-
-  builder()->SetInsertPoint(loop_check);
-  PHINode *index = builder()->CreatePHI(SharkType::jint_type(), "index");
-  index->addIncoming(
-    LLVMValue::jint_constant(function()->monitor_count() - 1), entry_block);
-  builder()->CreateCondBr(
-    builder()->CreateICmpUGE(index, LLVMValue::jint_constant(0)),
-    loop_top, no_monitor);
-
-  builder()->SetInsertPoint(loop_top);
-  SharkMonitor* monitor = function()->monitor(index);
-  Value *smo = monitor->object();
-  builder()->CreateCondBr(
-    builder()->CreateICmpEQ(smo, object),
-    got_monitor, loop_iter);
-
-  builder()->SetInsertPoint(loop_iter);
-  index->addIncoming(
-    builder()->CreateSub(index, LLVMValue::jint_constant(1)), loop_iter);
-  builder()->CreateBr(loop_check);
-
-  builder()->SetInsertPoint(no_monitor);
-  builder()->CreateShouldNotReachHere(__FILE__, __LINE__);
-  builder()->CreateUnreachable();
-
-  // Release the lock
-  builder()->SetInsertPoint(got_monitor);
-  monitor->release(this);
-  // The monitorexit can't throw an NPE because the verifier checks
-  // that the monitor operations are block structured before we
-  // compile.
-  // check_pending_exception();
+  ShouldNotCallThis();
 }
--- a/ports/hotspot/src/share/vm/shark/sharkBlock.hpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkBlock.hpp	Wed Mar 04 10:41:13 2009 -0500
@@ -23,119 +23,46 @@
  *
  */
 
+class SharkState;
+
 class SharkBlock : public ResourceObj {
  public:
-  SharkBlock(SharkFunction* function, ciTypeFlow::Block* ciblock)
-    : _function(function),
-      _ciblock(ciblock),
-      _entered(false),
-      _needs_phis(false),
-      _entry_state(NULL),
-      _entry_block(NULL),
-      _current_state(NULL) {}
+  SharkBlock(SharkBuilder* builder, ciMethod* target, ciBytecodeStream* iter)
+    : _builder(builder),_target(target),_iter(iter),_current_state(NULL) {}
 
  private:
-  SharkFunction*     _function;
-  ciTypeFlow::Block* _ciblock;
-
- public:
-  SharkFunction* function() const
-  {
-    return _function;
-  }
-  ciTypeFlow::Block* ciblock() const
-  {
-    return _ciblock;
-  }
+  SharkBuilder*     _builder;
+  ciMethod*         _target;
+  ciBytecodeStream* _iter;
+  SharkState*       _current_state;
 
  public:
   SharkBuilder* builder() const
   {
-    return function()->builder();
+    return _builder;
   }
   ciMethod* target() const
   {
-    return function()->target();
+    return _target;
   }
-  llvm::Value* thread() const
+  ciBytecodeStream* iter() const
   {
-    return function()->thread();
+    return _iter;
   }
 
-  // Typeflow properties
+  // Target properties
  public:
-  int index() const
-  {
-    return ciblock()->pre_order();
-  }
-  bool has_trap() const
-  {
-    return ciblock()->has_trap();
-  }
-  int trap_index() const
-  {
-    return ciblock()->trap_index();
-  }
-  bool is_private_copy() const
-  {
-    return ciblock()->is_backedge_copy();
-  }
   int max_locals() const
   {
-    return ciblock()->outer()->max_locals();
+    return target()->max_locals();
   }
   int max_stack() const
   {
-    return ciblock()->outer()->max_stack();
-  }
-  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);
+    return target()->max_stack();
   }  
-  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_exceptions() const
-  {
-    return ciblock()->exceptions()->length();
-  }
-  SharkBlock* exception(int index) const
-  {
-    return function()->block(ciblock()->exceptions()->at(index)->pre_order());
-  }
-  int num_successors() const
-  {
-    return ciblock()->successors()->length();
-  }
-  SharkBlock* successor(int index) const
-  {
-    return function()->block(ciblock()->successors()->at(index)->pre_order());
-  }
-  SharkBlock* bci_successor(int bci) const;
-
+  
   // Bytecode stream
  public:
-  ciBytecodeStream* iter() const
-  {
-    return function()->iter();
-  }  
   Bytecodes::Code bc() const
   {
     return iter()->cur_bc();
@@ -146,93 +73,29 @@
   }
 
   // Entry state
+ protected:
+  virtual SharkState* entry_state();
+  
+  // Current state
  private:
-  bool _entered;
-  bool _needs_phis;
-
+  SharkState* initial_current_state();
+  
  public:
-  bool entered() const
-  {
-    return _entered;
-  }
-  bool needs_phis() const
+  SharkState* current_state()
   {
-    return _needs_phis;
-  }
-
- private:
-  void enter(SharkBlock* predecessor, bool is_exception);
-
- public:
-  void enter()
-  {
-    enter(NULL, false);
+    if (_current_state == NULL)
+      set_current_state(initial_current_state());
+    return _current_state;
   }
 
- private:
-  SharkState* _entry_state;
-
- private:
-  SharkState* entry_state()
-  {
-    if (_entry_state == NULL) {
-      assert(needs_phis(), "should do");
-      _entry_state = new SharkPHIState(this);
-    }
-    return _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)
-  {
-    if (needs_phis()) {
-      ((SharkPHIState *) entry_state())->add_incoming(incoming_state);
-    }
-    else if (_entry_state != incoming_state) {
-      assert(_entry_state == NULL, "should be");
-      _entry_state = incoming_state;
-    }
-  }
-
-  // Current state
- private:
-  SharkTrackingState* _current_state;
-
- private:
-  void set_current_state(SharkTrackingState* current_state)
+ protected:
+  void set_current_state(SharkState* current_state)
   {
     _current_state = current_state;
   }
 
- public:
-  SharkTrackingState* current_state()
-  {
-    if (_current_state == NULL)
-      set_current_state(new SharkTrackingState(entry_state()));
-    return _current_state;
-  }
-
-  // Method
- public:
-  llvm::Value* method()
-  {
-    return current_state()->method();
-  }
-
   // Local variables  
- private:
+ protected:
   SharkValue* local(int index)
   {
     SharkValue *value = current_state()->local(index);
@@ -251,7 +114,7 @@
   }
 
   // Expression stack (raw)
- private:
+ protected:
   void xpush(SharkValue* value)
   {
     current_state()->push(value);
@@ -275,7 +138,7 @@
   }
 
   // Expression stack (cooked)
- private:
+ protected:
   void push(SharkValue* value)
   {
     assert(value != NULL, "shouldn't be");
@@ -292,133 +155,90 @@
     assert(value && value->size() == size, "should be");
     return value;
   }
-
-  // VM calls
- private:
-  llvm::CallInst* call_vm_nocheck(llvm::Constant* callee,
-                                  llvm::Value**   args_start,
-                                  llvm::Value**   args_end)
+  SharkValue* pop_result(BasicType type)
   {
-    current_state()->decache_for_VM_call();
-    function()->set_last_Java_frame();
-    llvm::CallInst *res = builder()->CreateCall(callee, args_start, args_end);
-    function()->reset_last_Java_frame();
-    current_state()->cache_after_VM_call();
-    return res;
-  }
+    SharkValue *result = pop();
+
+#ifdef ASSERT
+    switch (result->basic_type()) {
+    case T_BOOLEAN:
+    case T_BYTE:
+    case T_CHAR:
+    case T_SHORT:
+      assert(type == T_INT, "type mismatch");
+      break;
 
-  llvm::CallInst* call_vm(llvm::Constant* callee,
-                          llvm::Value**   args_start,
-                          llvm::Value**   args_end)
-  {
-    llvm::CallInst* res = call_vm_nocheck(callee, args_start, args_end);
-    check_pending_exception();
-    return res;
+    case T_ARRAY:
+      assert(type == T_OBJECT, "type mismatch");
+      break;
+
+    default:
+      assert(result->basic_type() == type, "type mismatch");
+    }
+#endif // ASSERT
+
+    return result;
   }
 
+  // Code generation
  public:
-  llvm::CallInst* call_vm(llvm::Constant* callee)
-  {
-    llvm::Value *args[] = {thread()};
-    return call_vm(callee, args, args + 1);
-  }
-  llvm::CallInst* call_vm(llvm::Constant* callee,
-                          llvm::Value*    arg1)
-  {
-    llvm::Value *args[] = {thread(), arg1};
-    return call_vm(callee, args, args + 2);
-  }
-  llvm::CallInst* call_vm(llvm::Constant* callee,
-                          llvm::Value*    arg1,
-                          llvm::Value*    arg2)
-  {
-    llvm::Value *args[] = {thread(), arg1, arg2};
-    return call_vm(callee, args, args + 3);
-  }
-  llvm::CallInst* call_vm(llvm::Constant* callee,
-                          llvm::Value*    arg1,
-                          llvm::Value*    arg2,
-                          llvm::Value*    arg3)
-  {
-    llvm::Value *args[] = {thread(), arg1, arg2, arg3};
-    return call_vm(callee, args, args + 4);
-  }
+  virtual void emit_IR();
+
+ protected:
+  void parse_bytecode(int start, int limit);
 
-  llvm::CallInst* call_vm_nocheck(llvm::Constant* callee)
-  {
-    llvm::Value *args[] = {thread()};
-    return call_vm_nocheck(callee, args, args + 1);
-  }
-  llvm::CallInst* call_vm_nocheck(llvm::Constant* callee,
-                                  llvm::Value*    arg1)
-  {
-    llvm::Value *args[] = {thread(), arg1};
-    return call_vm_nocheck(callee, args, args + 2);
-  }
-  llvm::CallInst* call_vm_nocheck(llvm::Constant* callee,
-                                  llvm::Value*    arg1,
-                                  llvm::Value*    arg2)
-  {
-    llvm::Value *args[] = {thread(), arg1, arg2};
-    return call_vm_nocheck(callee, args, args + 3);
-  }
-  llvm::CallInst* call_vm_nocheck(llvm::Constant* callee,
-                                  llvm::Value*    arg1,
-                                  llvm::Value*    arg2,
-                                  llvm::Value*    arg3)
-  {
-    llvm::Value *args[] = {thread(), arg1, arg2, arg3};
-    return call_vm_nocheck(callee, args, args + 4);
-  }
+  // Helpers
+ protected:
+  virtual void do_zero_check(SharkValue* value);
+  virtual llvm::Value* lookup_for_ldc();
+  virtual llvm::Value* lookup_for_field_access();
 
-  llvm::CallInst* call_vm_leaf(llvm::Constant* callee,
-                               llvm::Value*    arg1)
+  // Leaf calls
+ protected:
+  llvm::CallInst* call_vm_leaf(llvm::Constant* callee, llvm::Value* arg1)
   {
     return builder()->CreateCall(callee, arg1);
   }
 
-  // Whole-method synchronization
- public:
-  void acquire_method_lock();  
-  void release_method_lock();  
-
-  // Error checking
- private:
+  // Zero checking
+ protected:
   void check_null(SharkValue* object)
   {
-    check_zero(object);
+    zero_check(object);
   }
   void check_divide_by_zero(SharkValue* value)
   {
-    check_zero(value);
+    zero_check(value);
   }
-  void check_zero(SharkValue* value);
-  void check_bounds(SharkValue* array, SharkValue* index);
-  void check_pending_exception(bool attempt_catch = true);
-  void handle_exception(llvm::Value* exception, bool attempt_catch = true);
+ private:
+  void zero_check(SharkValue* value)
+  {
+    if (!value->zero_checked())
+      do_zero_check(value);
+  }
 
   // Safepoints
- private:
-  void add_safepoint();
-
-  // Returns
- private:
-  void call_register_finalizer(llvm::Value* receiver);
-  void handle_return(BasicType type, llvm::Value* exception);
-  void release_locked_monitors();
+ protected:
+  virtual void add_safepoint();
 
   // ldc*
  private:
-  void do_ldc();
+  void do_ldc()
+  {
+    SharkValue *value = SharkValue::from_ciConstant(iter()->get_constant());
+    if (value == NULL)
+      value = SharkValue::create_jobject(lookup_for_ldc());
+    push(value);
+  }
 
   // arraylength
- private:
-  void do_arraylength();
+ protected:
+  virtual void do_arraylength();
 
   // *aload and *astore
- private:
-  void do_aload(BasicType basic_type);
-  void do_astore(BasicType basic_type);
+ protected:
+  virtual void do_aload(BasicType basic_type);
+  virtual void do_astore(BasicType basic_type);
 
   // *div and *rem
  private:
@@ -438,8 +258,8 @@
   {
     do_div_or_rem(true, true);
   }
-  void do_div_or_rem(bool is_long, bool is_rem);
-  
+  void do_div_or_rem(bool is_long, bool is_rem);  
+
   // get* and put*
  private:
   void do_getstatic()
@@ -458,7 +278,7 @@
   {
     do_field_access(false, true);
   }
-  void do_field_access(bool is_get, bool is_field, ciField* field = NULL);
+  void do_field_access(bool is_get, bool is_field);
 
   // lcmp and [fd]cmp[lg]
  private:
@@ -466,75 +286,49 @@
   void do_fcmp(bool is_double, bool unordered_is_greater);
 
   // *return and athrow
- private:
-  void do_return(BasicType type)
-  {
-    if (target()->intrinsic_id() == vmIntrinsics::_Object_init)
-      call_register_finalizer(local(0)->jobject_value());
-    else
-      add_safepoint();
-    handle_return(type, NULL);
-  }
-  void do_athrow()
-  {
-    SharkValue *exception = pop();
-    check_null(exception);
-    handle_exception(exception->jobject_value());
-  }
+ protected:
+  virtual void do_return(BasicType type);
+  virtual void do_athrow();
+
+  // goto*
+ protected:
+  virtual void do_goto();
+
+  // jsr* and ret
+ protected:
+  virtual void do_jsr();
+  virtual void do_ret();
 
   // if*
- private:
-  void do_if(llvm::ICmpInst::Predicate p, SharkValue* b, SharkValue* a);
+ protected:
+  virtual void do_if(llvm::ICmpInst::Predicate p, SharkValue* b, SharkValue* a);
 
-  // tableswitch and lookupswitch
- private:
+  // *switch
+ protected:
   int switch_default_dest();
   int switch_table_length();
   int switch_key(int i);
   int switch_dest(int i);
 
-  void do_switch();
-
+  virtual void do_switch();
+  
   // invoke*
- private:
-  enum CallType {
-    CALL_DIRECT,
-    CALL_VIRTUAL,
-    CALL_INTERFACE
-  };
-  CallType get_call_type(ciMethod* method);
-  llvm::Value* get_callee(CallType    call_type,
-                          ciMethod*   method,
-                          SharkValue* receiver);
-
-  llvm::Value* get_direct_callee(ciMethod* method);
-  llvm::Value* get_virtual_callee(SharkValue* receiver, ciMethod* method);
-
-  llvm::Value* get_virtual_callee(llvm::Value* cache, SharkValue* receiver);
-  llvm::Value* get_interface_callee(SharkValue* receiver);
-
-  bool maybe_inline_call(ciMethod* method);
-  bool maybe_inline_accessor(ciMethod* method, bool is_field);
-
-  void do_call();
+ protected:
+  virtual void do_call();
 
   // checkcast and instanceof
- private:
-  void do_instance_check();
+ protected:
+  virtual void do_instance_check();
 
   // new and *newarray
- private:
-  void do_new();
-  void do_newarray();
-  void do_anewarray();
-  void do_multianewarray();
+ protected:
+  virtual void do_new();
+  virtual void do_newarray();
+  virtual void do_anewarray();
+  virtual void do_multianewarray();
 
   // monitorenter and monitorexit
- private:
-  void do_monitorenter();
-  void do_monitorexit();
-
-  // The big one
- public:
-  void parse();
+ protected:
+  virtual void do_monitorenter();
+  virtual void do_monitorexit();
 };
--- a/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp	Wed Mar 04 10:41:13 2009 -0500
@@ -111,6 +111,35 @@
  public:
   llvm::Function *CreateFunction(const char *name = "func");
 
+  // Helpers for creating basic blocks
+  // NB don't use unless SharkFunction::CreateBlock is unavailable
+ public:
+  llvm::BasicBlock* GetBlockInsertionPoint() const
+  {
+    llvm::BasicBlock *cur = GetInsertBlock();
+
+    // BasicBlock::Create takes an insertBefore argument, so
+    // we need to find the block _after_ the current block
+    llvm::Function::iterator iter = cur->getParent()->begin();
+    llvm::Function::iterator end  = cur->getParent()->end();
+    while (iter != end) {
+      iter++;
+      if (&*iter == cur) {
+        iter++;
+        break;
+      }
+    }
+
+    if (iter == end)
+      return NULL;
+    else
+      return iter;
+  }
+  llvm::BasicBlock* CreateBlock(llvm::BasicBlock* ip, const char* name="") const
+  {
+    return llvm::BasicBlock::Create(name, GetInsertBlock()->getParent(), ip);
+  }
+  
   // Helpers for accessing structures and arrays
  public:
   llvm::Value* CreateAddressOfStructEntry(llvm::Value* base,
--- a/ports/hotspot/src/share/vm/shark/sharkConstantPool.hpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkConstantPool.hpp	Wed Mar 04 10:41:13 2009 -0500
@@ -25,17 +25,17 @@
 
 class SharkConstantPool : public StackObj {
  public:
-  SharkConstantPool(SharkBlock* block)
+  SharkConstantPool(SharkTopLevelBlock* block)
     : _block(block),
       _constants_method(NULL),
       _tags_constants(NULL),
       _cache_constants(NULL) {}
 
  private:
-  SharkBlock* _block;
+  SharkTopLevelBlock* _block;
 
  private:
-  SharkBlock* block() const
+  SharkTopLevelBlock* block() const
   {
     return _block;
   }
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.cpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkFunction.cpp	Wed Mar 04 10:41:13 2009 -0500
@@ -30,6 +30,65 @@
 
 using namespace llvm;
 
+class SharkEntryState : public SharkState {
+ public:
+  SharkEntryState(SharkTopLevelBlock* block, llvm::Value* method)
+    : SharkState(block, block->function(), method)
+  {
+    char name[18];
+
+    // Local variables
+    for (int i = 0; i < max_locals(); i++) {
+      ciType *type = block->local_type_at_entry(i);
+
+      SharkValue *value = NULL;
+      switch (type->basic_type()) {
+      case T_INT:
+      case T_LONG:
+      case T_FLOAT:
+      case T_DOUBLE:
+      case T_OBJECT:
+      case T_ARRAY:
+        if (i < function()->arg_size()) {
+          snprintf(name, sizeof(name), "local_%d_", i);
+          value = SharkValue::create_generic(
+            type,
+            builder()->CreateLoad(
+              function()->CreateAddressOfFrameEntry(
+                function()->locals_slots_offset()
+                + max_locals() - type->size() - i,
+                SharkType::to_stackType(type)),
+              name));
+        }
+        else {
+          Unimplemented();
+        }
+        break;
+      
+      case ciTypeFlow::StateVector::T_BOTTOM:
+        break;
+
+      case ciTypeFlow::StateVector::T_LONG2:
+      case ciTypeFlow::StateVector::T_DOUBLE2:
+        break;
+
+      default:
+        ShouldNotReachHere();
+      }
+      set_local(i, value);
+    }
+
+    // Non-static methods have a guaranteed non-null receiver
+    if (!function()->target()->is_static()) {
+      assert(local(0)->is_jobject(), "should be");
+      local(0)->set_zero_checked(true);
+    }
+
+    // Expression stack
+    assert(!block->stack_depth_at_entry(), "entry block shouldn't have stack");
+  }
+};
+
 void SharkFunction::initialize()
 {
   // Emit the entry point
@@ -47,19 +106,19 @@
 
   // Create the list of blocks
   set_block_insertion_point(NULL);
-  _blocks = NEW_RESOURCE_ARRAY(SharkBlock*, flow()->block_count());
+  _blocks = NEW_RESOURCE_ARRAY(SharkTopLevelBlock*, flow()->block_count());
   for (int i = 0; i < block_count(); i++)
     {
       ciTypeFlow::Block *b = flow()->pre_order_at(i);
       // Work around a bug in pre_order_at() that does not return the
       // correct pre-ordering.  If pre_order_at() were correct this
       // line could simply be:
-      // _blocks[i] = new SharkBlock(this, b);
-      _blocks[b->pre_order()] = new SharkBlock(this, b);
+      // _blocks[i] = new SharkTopLevelBlock(this, b);
+      _blocks[b->pre_order()] = new SharkTopLevelBlock(this, b);
     }
   // Walk the tree from the start block to determine which
   // blocks are entered and which blocks require phis
-  SharkBlock *start_block = block(0);
+  SharkTopLevelBlock *start_block = block(0);
   assert(start_block->start() == 0, "blocks out of order");
   start_block->enter();
 
@@ -99,9 +158,10 @@
       "method_slot")));
 
   // Lock if necessary
-  SharkState *entry_state = new SharkEntryState(method, start_block);
+  SharkState *entry_state = new SharkEntryState(start_block, method);
   if (target()->is_synchronized()) {
-    SharkBlock *locker = new SharkBlock(this, start_block->ciblock());
+    SharkTopLevelBlock *locker =
+      new SharkTopLevelBlock(this, start_block->ciblock());
     locker->add_incoming(entry_state);
 
     set_block_insertion_point(start_block->entry_block());
@@ -124,7 +184,7 @@
     else
       set_block_insertion_point(NULL);
 
-    block(i)->parse();
+    block(i)->emit_IR();
   }
 
   // Dump the bitcode, if requested
--- a/ports/hotspot/src/share/vm/shark/sharkFunction.hpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkFunction.hpp	Wed Mar 04 10:41:13 2009 -0500
@@ -23,7 +23,7 @@
  *
  */
 
-class SharkBlock;
+class SharkTopLevelBlock;
 class SharkMonitor;
 
 class SharkFunction : public StackObj {
@@ -44,16 +44,16 @@
   void initialize();
 
  private:
-  SharkBuilder*     _builder;
-  const char*       _name;
-  ciTypeFlow*       _flow;
-  ciBytecodeStream* _iter;
-  MacroAssembler*   _masm;
-  llvm::Function*   _function;
-  SharkBlock**      _blocks;
-  llvm::Value*      _base_pc;
-  llvm::Value*      _thread;
-  int               _monitor_count;
+  SharkBuilder*        _builder;
+  const char*          _name;
+  ciTypeFlow*          _flow;
+  ciBytecodeStream*    _iter;
+  MacroAssembler*      _masm;
+  llvm::Function*      _function;
+  SharkTopLevelBlock** _blocks;
+  llvm::Value*         _base_pc;
+  llvm::Value*         _thread;
+  int                  _monitor_count;
 
  public:  
   SharkBuilder* builder() const
@@ -80,7 +80,7 @@
   {
     return _function;
   }
-  SharkBlock* block(int i) const
+  SharkTopLevelBlock* block(int i) const
   {
     return _blocks[i];
   }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkInliner.cpp	Wed Mar 04 10:41:13 2009 -0500
@@ -0,0 +1,761 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+#include "incls/_precompiled.incl"
+#include "incls/_sharkInliner.cpp.incl"
+
+using namespace llvm;
+
+class SharkInlineBlock : public SharkBlock {
+ public:
+  SharkInlineBlock(ciMethod*         target,
+                   SharkState*       state,
+                   ciBytecodeStream* iter)
+    : SharkBlock(state->builder(), target, iter),
+      _outer_state(state),
+      _entry_state(new SharkState(this))
+  {
+    for (int i = target->max_locals() - 1; i >= 0; i--) {
+      SharkValue *value = NULL;
+      if (i < target->arg_size())
+        value = outer_state()->pop();
+      entry_state()->set_local(i, value);
+    }
+  }
+
+ private:
+  SharkState* _outer_state;
+  SharkState* _entry_state;
+
+ private:
+  SharkState* outer_state()
+  {
+    return _outer_state;
+  }
+  SharkState* entry_state()
+  {
+    return _entry_state;
+  }
+
+ public:
+  void emit_IR()
+  {
+    parse_bytecode(0, target()->code_size());
+  }
+
+ private:
+  void do_return(BasicType type)
+  {
+    if (type != T_VOID) {
+      SharkValue *result = pop_result(type);
+      outer_state()->push(result);
+      if (result->is_two_word())
+        outer_state()->push(NULL);
+    }
+  }
+};
+
+class SharkInlinerHelper : public StackObj {
+ public:
+  SharkInlinerHelper(ciMethod* target, SharkState* entry_state)
+    : _target(target), _entry_state(entry_state), _iter(target) {}
+
+ private:
+  ciBytecodeStream _iter;
+  SharkState*      _entry_state;
+  ciMethod*        _target;
+  
+ public:
+  ciBytecodeStream* iter()
+  {
+    return &_iter;
+  }
+  SharkState* entry_state() const
+  {
+    return _entry_state;
+  }
+  ciMethod* target() const
+  {
+    return _target;
+  }
+
+ public:
+  Bytecodes::Code bc()
+  {
+    return iter()->cur_bc();
+  }
+  int max_locals() const
+  {
+    return target()->max_locals();
+  }
+  int max_stack() const
+  {
+    return target()->max_stack();
+  }
+  
+  // Inlinability check
+ public:
+  bool is_inlinable();
+
+ private:
+  void initialize_for_check();
+
+  bool do_getstatic()
+  {
+    return do_field_access(true, false);
+  }
+  bool do_getfield()
+  {
+    return do_field_access(true, true);
+  }
+  bool do_putfield()
+  {
+    return do_field_access(false, true);
+  }
+  bool do_field_access(bool is_get, bool is_field);
+
+  // Local variables for inlinability check
+ private:
+  bool* _locals;
+
+ public:
+  bool* local_addr(int index) const
+  {
+    assert(index >= 0 && index < max_locals(), "bad local variable index");
+    return &_locals[index];
+  }
+  bool local(int index) const
+  {
+    return *local_addr(index);
+  }
+  void set_local(int index, bool value)
+  {
+    *local_addr(index) = value;
+  }
+
+  // Expression stack for inlinability check
+ private:
+  bool* _stack;
+  bool* _sp;
+
+ public:
+  int stack_depth() const
+  {
+    return _sp - _stack;
+  }
+  bool* stack_addr(int slot) const
+  {
+    assert(slot >= 0 && slot < stack_depth(), "bad stack slot");
+    return &_sp[-(slot + 1)];
+  }
+  void push(bool value)
+  {
+    assert(stack_depth() < max_stack(), "stack overrun");
+    *(_sp++) = value;
+  }
+  bool pop()
+  {
+    assert(stack_depth() > 0, "stack underrun");
+    return *(--_sp);
+  }
+
+  // Methods for two-word locals
+ public:
+  void push_pair_local(int index)
+  {
+    push(local(index));
+    push(local(index + 1));
+  }
+  void pop_pair_local(int index)
+  {
+    set_local(index + 1, pop());
+    set_local(index, pop());
+  }
+
+  // Code generation
+ public:
+  void do_inline()
+  {
+    (new SharkInlineBlock(target(), entry_state(), iter()))->emit_IR();
+  }
+};
+
+// Quick checks so we can bail out before doing too much
+bool SharkInliner::may_be_inlinable(ciMethod *target)
+{
+  // We can't inline native methods
+  if (target->is_native())
+    return false;
+
+  // Not much point inlining abstract ones, and in any
+  // case we'd need a stack frame to throw the exception
+  if (target->is_abstract())
+    return false;
+
+  // Don't inline anything huge
+  if (target->code_size() > SharkMaxInlineSize)
+    return false;
+
+  // Monitors aren't allowed without a frame to put them in
+  if (target->is_synchronized() || target->has_monitor_bytecodes())
+    return false;
+
+  // We don't do control flow
+  if (target->has_exception_handlers() || target->has_jsrs())
+    return false;
+
+  // Mustn't inline Object.<init>
+  if (target->intrinsic_id() == vmIntrinsics::_Object_init)
+    return false;
+
+  return true;
+}
+
+// Full-on detailed check, for methods that pass the quick checks
+// Inlined methods have no stack frame, so we can't do anything
+// that would require one.  This means no safepoints (and hence
+// no loops) and no VM calls.  No VM calls means, amongst other
+// things, that no exceptions can be created, which means no null
+// checks or divide-by-zero checks are allowed.  The lack of null
+// checks in particular would eliminate practically everything,
+// but we can get around that restriction by relying on the zero-
+// check eliminator to strip the checks.  To do that, we need to
+// walk through the method, tracking which values are and are not
+// zero-checked.
+bool SharkInlinerHelper::is_inlinable()
+{
+  ResourceMark rm;
+  initialize_for_check();
+
+  SharkValue *sv;
+  bool a, b, c, d;
+
+  iter()->reset_to_bci(0);
+  while (iter()->next() != ciBytecodeStream::EOBC()) {
+    switch (bc()) {
+    case Bytecodes::_nop:
+      break;
+
+    case Bytecodes::_aconst_null:
+      push(false);
+      break;
+
+    case Bytecodes::_iconst_0:
+      push(false);
+      break;
+    case Bytecodes::_iconst_m1:
+    case Bytecodes::_iconst_1:
+    case Bytecodes::_iconst_2:
+    case Bytecodes::_iconst_3:
+    case Bytecodes::_iconst_4:
+    case Bytecodes::_iconst_5:
+      push(true);
+      break;
+
+    case Bytecodes::_lconst_0:
+      push(false);
+      push(false);
+      break;      
+    case Bytecodes::_lconst_1:
+      push(true);
+      push(false);
+      break;
+
+    case Bytecodes::_fconst_0:
+    case Bytecodes::_fconst_1:
+    case Bytecodes::_fconst_2:
+      push(false);
+      break;
+
+    case Bytecodes::_dconst_0:
+    case Bytecodes::_dconst_1:
+      push(false);
+      push(false);
+      break;
+
+    case Bytecodes::_bipush:
+      push(iter()->get_byte() != 0);
+      break;
+    case Bytecodes::_sipush:
+      push(iter()->get_short() != 0);
+      break;
+
+    case Bytecodes::_ldc:
+    case Bytecodes::_ldc_w:
+    case Bytecodes::_ldc2_w:
+      sv = SharkValue::from_ciConstant(iter()->get_constant());
+      if (sv == NULL)
+        return false;
+      push(sv->zero_checked());
+      if (sv->is_two_word())
+        push(false);
+      break;
+
+    case Bytecodes::_iload_0:
+    case Bytecodes::_fload_0:
+    case Bytecodes::_aload_0:
+      push(local(0));
+      break;
+    case Bytecodes::_lload_0:
+    case Bytecodes::_dload_0:
+      push_pair_local(0);
+      break;
+
+    case Bytecodes::_iload_1:
+    case Bytecodes::_fload_1:
+    case Bytecodes::_aload_1:
+      push(local(1));
+      break;
+    case Bytecodes::_lload_1:
+    case Bytecodes::_dload_1:
+      push_pair_local(1);
+      break;
+
+    case Bytecodes::_iload_2:
+    case Bytecodes::_fload_2:
+    case Bytecodes::_aload_2:
+      push(local(2));
+      break;
+    case Bytecodes::_lload_2:
+    case Bytecodes::_dload_2:
+      push_pair_local(2);
+      break;
+
+    case Bytecodes::_iload_3:
+    case Bytecodes::_fload_3:
+    case Bytecodes::_aload_3:
+      push(local(3));
+      break;
+    case Bytecodes::_lload_3:
+    case Bytecodes::_dload_3:
+      push_pair_local(3);
+      break;
+
+    case Bytecodes::_iload:
+    case Bytecodes::_fload:
+    case Bytecodes::_aload:
+      push(local(iter()->get_index()));
+      break;
+    case Bytecodes::_lload:
+    case Bytecodes::_dload:
+      push_pair_local(iter()->get_index());
+      break;
+
+    case Bytecodes::_istore_0:
+    case Bytecodes::_fstore_0:
+    case Bytecodes::_astore_0:
+      set_local(0, pop());
+      break;
+    case Bytecodes::_lstore_0:
+    case Bytecodes::_dstore_0:
+      pop_pair_local(0);
+      break;
+
+    case Bytecodes::_istore_1:
+    case Bytecodes::_fstore_1:
+    case Bytecodes::_astore_1:
+      set_local(1, pop());
+      break;
+    case Bytecodes::_lstore_1:
+    case Bytecodes::_dstore_1:
+      pop_pair_local(1);
+      break;
+
+    case Bytecodes::_istore_2:
+    case Bytecodes::_fstore_2:
+    case Bytecodes::_astore_2:
+      set_local(2, pop());
+      break;
+    case Bytecodes::_lstore_2:
+    case Bytecodes::_dstore_2:
+      pop_pair_local(2);
+      break;
+
+    case Bytecodes::_istore_3:
+    case Bytecodes::_fstore_3:
+    case Bytecodes::_astore_3:
+      set_local(3, pop());
+      break;
+    case Bytecodes::_lstore_3:
+    case Bytecodes::_dstore_3:
+      pop_pair_local(3);
+      break;
+
+    case Bytecodes::_istore:
+    case Bytecodes::_fstore:
+    case Bytecodes::_astore:
+      set_local(iter()->get_index(), pop());
+      break;
+    case Bytecodes::_lstore:
+    case Bytecodes::_dstore:
+      pop_pair_local(iter()->get_index());
+      break;
+
+    case Bytecodes::_pop:
+      pop();
+      break;
+    case Bytecodes::_pop2:
+      pop();
+      pop();
+      break;
+    case Bytecodes::_swap: 
+      a = pop();
+      b = pop();
+      push(a);
+      push(b);
+      break;  
+    case Bytecodes::_dup:
+      a = pop();
+      push(a);
+      push(a);
+      break;
+    case Bytecodes::_dup_x1: 
+      a = pop();
+      b = pop();
+      push(a);
+      push(b);
+      push(a);
+      break;
+    case Bytecodes::_dup_x2: 
+      a = pop();
+      b = pop();
+      c = pop();
+      push(a);
+      push(c);
+      push(b);
+      push(a);
+      break;
+    case Bytecodes::_dup2: 
+      a = pop();
+      b = pop();
+      push(b);
+      push(a);
+      push(b);
+      push(a);
+      break;
+    case Bytecodes::_dup2_x1:
+      a = pop();
+      b = pop();
+      c = pop();
+      push(b);
+      push(a);
+      push(c);
+      push(b);
+      push(a);
+      break;
+    case Bytecodes::_dup2_x2:
+      a = pop();
+      b = pop();
+      c = pop();
+      d = pop();
+      push(b);
+      push(a);
+      push(d);
+      push(c);
+      push(b);
+      push(a);
+      break;
+
+    case Bytecodes::_getfield:
+      if (!do_getfield())
+        return false;
+      break;
+    case Bytecodes::_getstatic:
+      if (!do_getstatic())
+        return false;
+      break;
+    case Bytecodes::_putfield:
+      if (!do_putfield())
+        return false;
+      break;
+
+    case Bytecodes::_iadd:
+    case Bytecodes::_isub:
+    case Bytecodes::_imul:
+    case Bytecodes::_iand:
+    case Bytecodes::_ior:
+    case Bytecodes::_ixor:
+    case Bytecodes::_ishl:
+    case Bytecodes::_ishr:
+    case Bytecodes::_iushr:
+      pop();
+      pop();
+      push(false);
+      break;
+    case Bytecodes::_idiv:
+    case Bytecodes::_irem:
+      if (!pop())
+        return false;
+      pop();
+      push(false);
+      break;
+    case Bytecodes::_ineg:
+      break;
+      
+    case Bytecodes::_ladd:
+    case Bytecodes::_lsub:
+    case Bytecodes::_lmul:
+    case Bytecodes::_land:
+    case Bytecodes::_lor:
+    case Bytecodes::_lxor:
+      pop();
+      pop();
+      pop();
+      pop();
+      push(false);
+      push(false);
+      break;
+    case Bytecodes::_ldiv:
+    case Bytecodes::_lrem:
+      pop();
+      if (!pop())
+        return false;
+      pop();
+      pop();
+      push(false);
+      push(false);
+      break;
+    case Bytecodes::_lneg:
+      break;
+    case Bytecodes::_lshl:
+    case Bytecodes::_lshr:
+    case Bytecodes::_lushr:
+      pop();
+      pop();
+      pop();
+      push(false);
+      push(false);
+      break;
+
+    case Bytecodes::_fadd:
+    case Bytecodes::_fsub:
+    case Bytecodes::_fmul:
+    case Bytecodes::_fdiv:
+    case Bytecodes::_frem:
+      pop();
+      pop();
+      push(false);
+      break;
+    case Bytecodes::_fneg:
+      break;
+
+    case Bytecodes::_dadd:
+    case Bytecodes::_dsub:
+    case Bytecodes::_dmul:
+    case Bytecodes::_ddiv:
+    case Bytecodes::_drem:
+      pop();
+      pop();
+      pop();
+      pop();
+      push(false);
+      push(false);
+      break;
+    case Bytecodes::_dneg:
+      break;
+
+    case Bytecodes::_iinc:
+      set_local(iter()->get_index(), false);
+      break;
+
+    case Bytecodes::_lcmp:
+      pop();
+      pop();
+      pop();
+      pop();
+      push(false);
+      break;
+
+    case Bytecodes::_fcmpl:
+    case Bytecodes::_fcmpg:
+      pop();
+      pop();
+      push(false);
+      break;
+      
+    case Bytecodes::_dcmpl:
+    case Bytecodes::_dcmpg:
+      pop();
+      pop();
+      pop();
+      pop();
+      push(false);
+      break;
+
+    case Bytecodes::_i2l:
+      push(false);
+      break;
+    case Bytecodes::_i2f:
+      pop();
+      push(false);
+      break;
+    case Bytecodes::_i2d:
+      pop();
+      push(false);
+      push(false);
+      break;
+
+    case Bytecodes::_l2i:
+    case Bytecodes::_l2f:
+      pop();
+      pop();
+      push(false);
+      break;
+    case Bytecodes::_l2d:
+      pop();
+      pop();
+      push(false);
+      push(false);
+      break;
+
+    case Bytecodes::_f2i:
+      pop();
+      push(false);
+      break;
+    case Bytecodes::_f2l:
+    case Bytecodes::_f2d:
+      pop();
+      push(false);
+      push(false);
+      break;
+
+    case Bytecodes::_d2i:
+    case Bytecodes::_d2f:
+      pop();
+      pop();
+      push(false);
+      break;
+    case Bytecodes::_d2l:
+      pop();
+      pop();
+      push(false);
+      push(false);
+      break;
+
+    case Bytecodes::_i2b:
+    case Bytecodes::_i2c:
+    case Bytecodes::_i2s:
+      pop();
+      push(false);
+      break;
+
+    case Bytecodes::_return:
+    case Bytecodes::_ireturn:
+    case Bytecodes::_lreturn:
+    case Bytecodes::_freturn:
+    case Bytecodes::_dreturn:
+    case Bytecodes::_areturn:
+      break;
+
+    default:
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void SharkInlinerHelper::initialize_for_check()
+{
+  _locals = NEW_RESOURCE_ARRAY(bool, max_locals());
+  _stack = NEW_RESOURCE_ARRAY(bool, max_stack());
+
+  memset(_locals, 0, max_locals() * sizeof(bool));
+  for (int i = 0; i < target()->arg_size(); i++) {
+    SharkValue *arg = entry_state()->stack(target()->arg_size() - 1 - i);
+    if (arg && arg->zero_checked())
+      set_local(i, true);
+  }
+
+  _sp = _stack;
+}
+
+bool SharkInlinerHelper::do_field_access(bool is_get, bool is_field)
+{
+  assert(is_get || is_field, "can't inline putstatic");
+
+  // If the holder isn't linked then there isn't a lot we can do
+  if (!target()->holder()->is_linked())
+    return false;
+
+  // Get the field
+  bool will_link;
+  ciField *field = iter()->get_field(will_link);
+  if (!will_link)
+    return false;
+
+  // If the field is mismatched then an exception needs throwing
+  if (is_field == field->is_static())
+    return false;
+
+  // Pop the value off the stack if necessary
+  if (!is_get) {
+    pop();
+    if (field->type()->is_two_word())
+      pop();
+  }
+
+  // Pop and null-check the receiver if necessary
+  if (is_field) {
+    if (!pop())
+      return false;
+  }
+
+  // Push the result if necessary
+  if (is_get) {
+    bool result_pushed = false;
+    if (field->is_constant()) {
+      SharkValue *value = SharkValue::from_ciConstant(field->constant_value());
+      if (value != NULL) {
+        push(value->zero_checked());
+        result_pushed = true;
+      }
+    }
+
+    if (!result_pushed) {
+      if (!is_field)
+        return false;
+
+      push(false);
+    }
+
+    if (field->type()->is_two_word())
+      push(false);
+  }
+
+  return true;
+}
+
+bool SharkInliner::attempt_inline(ciMethod *target, SharkState *state)
+{
+  if (may_be_inlinable(target)) {
+    SharkInlinerHelper inliner(target, state);
+    if (inliner.is_inlinable()) {
+      inliner.do_inline();
+      return true;
+    }
+  }
+  return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkInliner.hpp	Wed Mar 04 10:41:13 2009 -0500
@@ -0,0 +1,32 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2009 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+class SharkInliner : public AllStatic {
+ public:
+  static bool attempt_inline(ciMethod* target, SharkState* state);
+                      
+ private:
+  static bool may_be_inlinable(ciMethod* target);
+};
--- a/ports/hotspot/src/share/vm/shark/sharkMonitor.cpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkMonitor.cpp	Wed Mar 04 10:41:13 2009 -0500
@@ -43,7 +43,7 @@
     "displaced_header_addr");
 }
 
-void SharkMonitor::acquire(SharkBlock* block, Value *lockee) const
+void SharkMonitor::acquire(SharkTopLevelBlock* block, Value *lockee) const
 {
   BasicBlock *try_recursive = function()->CreateBlock("try_recursive");
   BasicBlock *got_recursive = function()->CreateBlock("got_recursive");
@@ -120,7 +120,7 @@
   block->current_state()->merge(fast_state, acquired_fast, acquired_slow);
 }
 
-void SharkMonitor::release(SharkBlock* block) const
+void SharkMonitor::release(SharkTopLevelBlock* block) const
 {
   BasicBlock *not_recursive = function()->CreateBlock("not_recursive");
   BasicBlock *released_fast = function()->CreateBlock("released_fast");
--- a/ports/hotspot/src/share/vm/shark/sharkMonitor.hpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkMonitor.hpp	Wed Mar 04 10:41:13 2009 -0500
@@ -23,7 +23,7 @@
  *
  */
 
-class SharkBlock;
+class SharkTopLevelBlock;
 
 class SharkMonitor : public ResourceObj {
  public:
@@ -89,6 +89,6 @@
   }
 
  public:
-  void acquire(SharkBlock* block, llvm::Value* lockee) const;
-  void release(SharkBlock* block) const;
+  void acquire(SharkTopLevelBlock* block, llvm::Value* lockee) const;
+  void release(SharkTopLevelBlock* block) const;
 };
--- a/ports/hotspot/src/share/vm/shark/sharkState.cpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkState.cpp	Wed Mar 04 10:41:13 2009 -0500
@@ -28,6 +28,24 @@
 
 using namespace llvm;
 
+SharkState::SharkState(SharkBlock*    block,
+                       SharkFunction* function,
+                       llvm::Value*   method)
+  : _block(block),
+    _function(function),
+    _method(method)
+{
+  initialize(NULL);
+}
+
+SharkState::SharkState(const SharkState* state)
+  : _block(state->block()),
+    _function(state->function()),
+    _method(state->method())
+{
+  initialize(state);
+}
+
 void SharkState::initialize(const SharkState *state)
 {
   _locals = NEW_RESOURCE_ARRAY(SharkValue*, max_locals());
@@ -45,177 +63,9 @@
     NOT_PRODUCT(memset(_stack,  23, max_stack()  * sizeof(SharkValue *)));
   }
 }
-
-void SharkEntryState::initialize(Value* method)
-{
-  char name[18];
-
-  // Method
-  set_method(method);
-
-  // Local variables
-  for (int i = 0; i < max_locals(); i++) {
-    ciType *type = block()->local_type_at_entry(i);
-
-    SharkValue *value = NULL;
-    switch (type->basic_type()) {
-    case T_INT:
-    case T_LONG:
-    case T_FLOAT:
-    case T_DOUBLE:
-    case T_OBJECT:
-    case T_ARRAY:
-      if (i < function()->arg_size()) {
-        snprintf(name, sizeof(name), "local_%d_", i);
-        value = SharkValue::create_generic(
-          type,
-          builder()->CreateLoad(
-            function()->CreateAddressOfFrameEntry(
-              function()->locals_slots_offset()
-                + max_locals() - type->size() - i,
-              SharkType::to_stackType(type)),
-            name));
-      }
-      else {
-        Unimplemented();
-      }
-      break;
-      
-    case ciTypeFlow::StateVector::T_BOTTOM:
-      break;
-
-    case ciTypeFlow::StateVector::T_LONG2:
-    case ciTypeFlow::StateVector::T_DOUBLE2:
-      break;
-
-    default:
-      ShouldNotReachHere();
-    }
-    set_local(i, value);
-  }
-
-  // Non-static methods have a guaranteed non-null receiver
-  if (!function()->target()->is_static()) {
-    assert(local(0)->is_jobject(), "should be");
-    local(0)->set_zero_checked(true);
-  }
-
-  // Expression stack
-  assert(!stack_depth_at_entry(), "entry block shouldn't have stack");
-}
-
-void SharkPHIState::initialize()
-{
-  BasicBlock *saved_insert_point = builder()->GetInsertBlock();
-  builder()->SetInsertPoint(block()->entry_block());
-  char name[18];
-
-  // Method
-  set_method(builder()->CreatePHI(SharkType::methodOop_type(), "method"));
-
-  // Local variables
-  for (int i = 0; i < max_locals(); i++) {
-    ciType *type = block()->local_type_at_entry(i);
-    if (type->basic_type() == (BasicType) ciTypeFlow::StateVector::T_NULL) {
-      // XXX we could do all kinds of clever stuff here
-      type = ciType::make(T_OBJECT); // XXX what about T_ARRAY?
-    }
-
-    SharkValue *value = NULL;
-    switch (type->basic_type()) {
-    case T_INT:
-    case T_LONG:
-    case T_FLOAT:
-    case T_DOUBLE:
-    case T_OBJECT:
-    case T_ARRAY:
-      snprintf(name, sizeof(name), "local_%d_", i);
-      value = SharkValue::create_generic(
-        type, builder()->CreatePHI(SharkType::to_stackType(type), name));
-      break;
-
-    case T_ADDRESS:
-      value = SharkValue::create_returnAddress(
-        type->as_return_address()->bci());
-      break;
-
-    case ciTypeFlow::StateVector::T_BOTTOM:
-      break;
-
-    case ciTypeFlow::StateVector::T_LONG2:
-    case ciTypeFlow::StateVector::T_DOUBLE2:
-      break;
-
-    default:
-      ShouldNotReachHere();
-    }
-    set_local(i, value);
-  }
-
-  // Expression stack
-  for (int i = 0; i < stack_depth_at_entry(); i++) {
-    ciType *type = block()->stack_type_at_entry(i);
-    if (type->basic_type() == (BasicType) ciTypeFlow::StateVector::T_NULL) {
-      // XXX we could do all kinds of clever stuff here
-      type = ciType::make(T_OBJECT); // XXX what about T_ARRAY?
-    }
-
-    SharkValue *value = NULL;
-    switch (type->basic_type()) {
-    case T_INT:
-    case T_LONG:
-    case T_FLOAT:
-    case T_DOUBLE:
-    case T_OBJECT:
-    case T_ARRAY:
-      snprintf(name, sizeof(name), "stack_%d_", i);
-      value = SharkValue::create_generic(
-        type, builder()->CreatePHI(SharkType::to_stackType(type), name));
-      break;
-
-    case T_ADDRESS:
-      value = SharkValue::create_returnAddress(
-        type->as_return_address()->bci());
-      break;
-
-    case ciTypeFlow::StateVector::T_LONG2:
-    case ciTypeFlow::StateVector::T_DOUBLE2:
-      break;
-
-    default:
-      ShouldNotReachHere();
-    }
-    push(value);
-  }
-
-  builder()->SetInsertPoint(saved_insert_point);
-}
-
-void SharkPHIState::add_incoming(SharkState* incoming_state)
-{
-  BasicBlock *predecessor = builder()->GetInsertBlock();
-    
-  // Method
-  ((PHINode *) method())->addIncoming(incoming_state->method(), predecessor);
-
-  // Local variables
-  for (int i = 0; i < max_locals(); i++) {
-    if (local(i) != NULL)
-      local(i)->addIncoming(incoming_state->local(i), predecessor);
-  }
-
-  // Expression stack
-  assert(stack_depth_at_entry() == incoming_state->stack_depth(), "should be");
-  for (int i = 0; i < stack_depth_at_entry(); i++) {
-    assert((stack(i) == NULL) == (incoming_state->stack(i) == NULL), "oops");
-    if (stack(i))
-      stack(i)->addIncoming(incoming_state->stack(i), predecessor);
-  }
-}
-
-void SharkTrackingState::merge(SharkState* other,
-                               BasicBlock* other_block,
-                               BasicBlock* this_block)
+void SharkState::merge(SharkState* other,
+                       BasicBlock* other_block,
+                       BasicBlock* this_block)
 {
   PHINode *phi;
   char name[18];
@@ -269,16 +119,51 @@
   }
 }
 
-#ifndef PRODUCT
-void SharkTrackingState::enter_inlined_section()
+void SharkState::decache_for_Java_call(ciMethod* callee)
 {
-  assert(has_stack_frame(), "should do");
-  set_has_stack_frame(false);
+  assert(function() && method(), "you cannot decache here");
+  SharkJavaCallDecacher(function(), block()->bci(), callee).scan(this);
+  pop(callee->arg_size());
 }
 
-void SharkTrackingState::leave_inlined_section()
+void SharkState::cache_after_Java_call(ciMethod* callee)
 {
-  assert(!has_stack_frame(), "shouldn't do");
-  set_has_stack_frame(true);
+  assert(function() && method(), "you cannot cache here");
+  if (callee->return_type()->size()) {
+    ciType *type;
+    switch (callee->return_type()->basic_type()) {
+    case T_BOOLEAN:
+    case T_BYTE:
+    case T_CHAR:
+    case T_SHORT:
+      type = ciType::make(T_INT);
+      break;
+
+    default:
+      type = callee->return_type();
+    }
+
+    push(SharkValue::create_generic(type, NULL));
+    if (type->is_two_word())
+      push(NULL);
+  }
+  SharkJavaCallCacher(function(), block()->bci(), callee).scan(this);
 }
-#endif // PRODUCT
+
+void SharkState::decache_for_VM_call()
+{
+  assert(function() && method(), "you cannot decache here");
+  SharkVMCallDecacher(function(), block()->bci()).scan(this);
+}
+
+void SharkState::cache_after_VM_call()
+{
+  assert(function() && method(), "you cannot cache here");
+  SharkVMCallCacher(function(), block()->bci()).scan(this);
+}
+
+void SharkState::decache_for_trap()
+{
+  assert(function() && method(), "you cannot decache here");
+  SharkTrapDecacher(function(), block()->bci()).scan(this);
+}
--- a/ports/hotspot/src/share/vm/shark/sharkState.hpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkState.hpp	Wed Mar 04 10:41:13 2009 -0500
@@ -24,41 +24,41 @@
  */
 
 class SharkBlock;
+class SharkFunction;
 
 class SharkState : public ResourceObj {
- protected:
-  SharkState(SharkBlock* block)
-    : _block(block)          { initialize(NULL); }
-  SharkState(const SharkState* state)
-    : _block(state->block()) { initialize(state); }
+ public:
+  SharkState(SharkBlock*    block,
+             SharkFunction* function = NULL,
+             llvm::Value*   method = NULL);
+  SharkState(const SharkState* state);
 
  private:
   void initialize(const SharkState* state);
 
  private:
-  SharkBlock* _block;
+  SharkBlock*    _block;
+  SharkFunction* _function;
+  llvm::Value*   _method;
+  SharkValue**   _locals;
+  SharkValue**   _stack;
+  SharkValue**   _sp;
 
  public:
   SharkBlock *block() const
   {
     return _block;
   }
-
- protected:
+  SharkFunction *function() const
+  {
+    return _function;
+  }
+  
+ public:
   inline SharkBuilder* builder() const;
-  inline SharkFunction* function() const;
-
- public:
   inline int max_locals() const;
   inline int max_stack() const;
 
-  // The values we are tracking
- private:
-  llvm::Value* _method;
-  SharkValue** _locals;
-  SharkValue** _stack;
-  SharkValue** _sp;
-
   // Method
  public:
   llvm::Value** method_addr()
@@ -125,75 +125,23 @@
   {
     assert(stack_depth() >= slots, "stack underrun");
     _sp -= slots;
-  }  
-  inline int stack_depth_at_entry() const;
-};
-
-class SharkEntryState : public SharkState {
- public:
-  SharkEntryState(llvm::Value* method, SharkBlock* start_block)
-    : SharkState(start_block) { initialize(method); }
-
- private:
-  void initialize(llvm::Value* method);
-};
-
-class SharkPHIState : public SharkState {
- public:
-  SharkPHIState(SharkBlock* block)
-    : SharkState(block) { initialize(); }
-
- private:
-  void initialize();
-
- public:
-  void add_incoming(SharkState* incoming_state);
-};
-
-class SharkTrackingState : public SharkState {
- public:
-  SharkTrackingState(const SharkState* state)
-    : SharkState(state)
-  {
-    set_method(state->method());
-    NOT_PRODUCT(set_has_stack_frame(true));
   }
 
-  // Cache and decache
- public:
-  inline void decache_for_Java_call(ciMethod* callee);
-  inline void cache_after_Java_call(ciMethod* callee);
-  inline void decache_for_VM_call();
-  inline void cache_after_VM_call();
-  inline void decache_for_trap();
-
   // Copy and merge
  public:
-  SharkTrackingState* copy() const
+  SharkState* copy() const
   {
-    return new SharkTrackingState(this);
+    return new SharkState(this);
   }
   void merge(SharkState*       other,
              llvm::BasicBlock* other_block,
              llvm::BasicBlock* this_block);
 
-  // Inlining
-#ifndef PRODUCT
- private:
-  bool _has_stack_frame;
-
- protected:
-  bool has_stack_frame() const
-  {
-    return _has_stack_frame;
-  }
-  void set_has_stack_frame(bool has_stack_frame)
-  {
-    _has_stack_frame = has_stack_frame;
-  }
-#endif // PRODUCT
-
+  // Cache and decache
  public:
-  void enter_inlined_section() PRODUCT_RETURN;
-  void leave_inlined_section() PRODUCT_RETURN;
+  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();
 };
--- a/ports/hotspot/src/share/vm/shark/sharkState.inline.hpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/sharkState.inline.hpp	Wed Mar 04 10:41:13 2009 -0500
@@ -28,11 +28,6 @@
   return block()->builder();
 }  
   
-inline SharkFunction* SharkState::function() const
-{
-  return block()->function();
-}  
-  
 inline int SharkState::max_locals() const
 {
   return block()->max_locals();
@@ -42,57 +37,3 @@
 {
   return block()->max_stack();
 }
-
-inline int SharkState::stack_depth_at_entry() const
-{
-  return block()->stack_depth_at_entry();
-}
-
-inline void SharkTrackingState::decache_for_Java_call(ciMethod* callee)
-{
-  assert(has_stack_frame(), "should do");
-  SharkJavaCallDecacher(function(), block()->bci(), callee).scan(this);
-  pop(callee->arg_size());
-}
-
-inline void SharkTrackingState::cache_after_Java_call(ciMethod* callee)
-{
-  assert(has_stack_frame(), "should do");
-  if (callee->return_type()->size()) {
-    ciType *type;
-    switch (callee->return_type()->basic_type()) {
-    case T_BOOLEAN:
-    case T_BYTE:
-    case T_CHAR:
-    case T_SHORT:
-      type = ciType::make(T_INT);
-      break;
-
-    default:
-      type = callee->return_type();
-    }
-
-    push(SharkValue::create_generic(type, NULL));
-    if (type->is_two_word())
-      push(NULL);
-  }
-  SharkJavaCallCacher(function(), block()->bci(), callee).scan(this);
-}
-
-inline void SharkTrackingState::decache_for_VM_call()
-{
-  assert(has_stack_frame(), "should do");
-  SharkVMCallDecacher(function(), block()->bci()).scan(this);
-}
-
-inline void SharkTrackingState::cache_after_VM_call()
-{
-  assert(has_stack_frame(), "should do");
-  SharkVMCallCacher(function(), block()->bci()).scan(this);
-}
-
-inline void SharkTrackingState::decache_for_trap()
-{
-  assert(has_stack_frame(), "should do");
-  SharkTrapDecacher(function(), block()->bci()).scan(this);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp	Wed Mar 04 10:41:13 2009 -0500
@@ -0,0 +1,1716 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2008, 2009 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+#include "incls/_precompiled.incl"
+#include "incls/_sharkTopLevelBlock.cpp.incl"
+#include "ciArrayKlass.hpp" // XXX fuck you makeDeps
+#include "ciObjArrayKlass.hpp" // XXX likewise
+
+using namespace llvm;
+
+class SharkPHIState : public SharkState {
+ public:
+  SharkPHIState(SharkTopLevelBlock* block)
+    : SharkState(block, block->function())
+  {
+    BasicBlock *saved_insert_point = builder()->GetInsertBlock();
+    builder()->SetInsertPoint(block->entry_block());
+    char name[18];
+  
+    // Method
+    set_method(builder()->CreatePHI(SharkType::methodOop_type(), "method"));
+  
+    // Local variables
+    for (int i = 0; i < max_locals(); i++) {
+      ciType *type = block->local_type_at_entry(i);
+      if (type->basic_type() == (BasicType) ciTypeFlow::StateVector::T_NULL) {
+        // XXX we could do all kinds of clever stuff here
+        type = ciType::make(T_OBJECT); // XXX what about T_ARRAY?
+      }
+  
+      SharkValue *value = NULL;
+      switch (type->basic_type()) {
+      case T_INT:
+      case T_LONG:
+      case T_FLOAT:
+      case T_DOUBLE:
+      case T_OBJECT:
+      case T_ARRAY:
+        snprintf(name, sizeof(name), "local_%d_", i);
+        value = SharkValue::create_generic(
+          type, builder()->CreatePHI(SharkType::to_stackType(type), name));
+        break;
+  
+      case T_ADDRESS:
+        value = SharkValue::create_returnAddress(
+          type->as_return_address()->bci());
+        break;
+  
+      case ciTypeFlow::StateVector::T_BOTTOM:
+        break;
+  
+      case ciTypeFlow::StateVector::T_LONG2:
+      case ciTypeFlow::StateVector::T_DOUBLE2:
+        break;
+  
+      default:
+        ShouldNotReachHere();
+      }
+      set_local(i, value);
+    }
+  
+    // Expression stack
+    for (int i = 0; i < block->stack_depth_at_entry(); i++) {
+      ciType *type = block->stack_type_at_entry(i);
+      if (type->basic_type() == (BasicType) ciTypeFlow::StateVector::T_NULL) {
+        // XXX we could do all kinds of clever stuff here
+        type = ciType::make(T_OBJECT); // XXX what about T_ARRAY?
+      }
+  
+      SharkValue *value = NULL;
+      switch (type->basic_type()) {
+      case T_INT:
+      case T_LONG:
+      case T_FLOAT:
+      case T_DOUBLE:
+      case T_OBJECT:
+      case T_ARRAY:
+        snprintf(name, sizeof(name), "stack_%d_", i);
+        value = SharkValue::create_generic(
+          type, builder()->CreatePHI(SharkType::to_stackType(type), name));
+        break;
+  
+      case T_ADDRESS:
+        value = SharkValue::create_returnAddress(
+          type->as_return_address()->bci());
+        break;
+  
+      case ciTypeFlow::StateVector::T_LONG2:
+      case ciTypeFlow::StateVector::T_DOUBLE2:
+        break;
+  
+      default:
+        ShouldNotReachHere();
+      }
+      push(value);
+    }
+  
+    builder()->SetInsertPoint(saved_insert_point);    
+  }
+
+ public:
+  void add_incoming(SharkState* incoming_state)
+  {
+    BasicBlock *predecessor = builder()->GetInsertBlock();
+      
+    // Method
+    ((PHINode *) method())->addIncoming(incoming_state->method(), predecessor);
+  
+    // Local variables
+    for (int i = 0; i < max_locals(); i++) {
+      if (local(i) != NULL)
+        local(i)->addIncoming(incoming_state->local(i), predecessor);
+    }
+  
+    // Expression stack
+    int stack_depth = ((SharkTopLevelBlock *) block())->stack_depth_at_entry();
+    assert(stack_depth == incoming_state->stack_depth(), "should be");
+    for (int i = 0; i < stack_depth; i++) {
+      assert((stack(i) == NULL) == (incoming_state->stack(i) == NULL), "oops");
+      if (stack(i))
+        stack(i)->addIncoming(incoming_state->stack(i), predecessor);
+    }    
+  }
+};
+
+SharkState* SharkTopLevelBlock::entry_state()
+{
+  if (_entry_state == NULL) {
+    assert(needs_phis(), "should do");
+    _entry_state = new SharkPHIState(this);
+  }
+  return _entry_state;
+}
+
+void SharkTopLevelBlock::add_incoming(SharkState* incoming_state)
+{
+  if (needs_phis()) {
+    ((SharkPHIState *) entry_state())->add_incoming(incoming_state);
+  }
+  else if (_entry_state != incoming_state) {
+    assert(_entry_state == NULL, "should be");
+    _entry_state = incoming_state;
+  }
+}
+
+void SharkTopLevelBlock::enter(SharkTopLevelBlock* predecessor,
+                               bool is_exception)
+{
+  // This block requires phis:
+  //  - if it is entered more than once
+  //  - if it is an exception handler, because in which
+  //    case we assume it's entered more than once.
+  //  - if the predecessor will be compiled after this
+  //    block, in which case we can't simple propagate
+  //    the state forward.
+  if (!needs_phis() &&
+      (entered() ||
+       is_exception ||
+       (predecessor && predecessor->index() >= index())))
+    _needs_phis = true;
+
+  // Recurse into the tree
+  if (!entered()) {
+    _entered = true;
+
+    if (!has_trap()) {
+      for (int i = 0; i < num_successors(); i++) {
+        successor(i)->enter(this, false);
+      }
+      for (int i = 0; i < num_exceptions(); i++) {
+        exception(i)->enter(this, true);
+      }
+    }
+  }
+}
+  
+void SharkTopLevelBlock::initialize()
+{
+  char name[28];
+  snprintf(name, sizeof(name),
+           "bci_%d%s",
+           start(), is_private_copy() ? "_private_copy" : "");
+  _entry_block = function()->CreateBlock(name);
+}
+
+void SharkTopLevelBlock::acquire_method_lock()
+{
+  Value *object;
+  if (target()->is_static()) {
+    SharkConstantPool constants(this);
+    object = constants.java_mirror();
+  }
+  else {
+    object = local(0)->jobject_value();
+  }
+  iter()->force_bci(start()); // for the decache
+  function()->monitor(0)->acquire(this, object);
+  check_pending_exception(false);
+}
+
+void SharkTopLevelBlock::release_method_lock()
+{
+  function()->monitor(0)->release(this);
+
+  // We neither need nor want to check for pending exceptions here.
+  // This method is only called by handle_return, which copes with
+  // them implicitly:
+  //  - if a value is being returned then we just carry on as normal;
+  //    the caller will see the pending exception and handle it.
+  //  - if an exception is being thrown then that exception takes
+  //    priority and ours will be ignored.
+}
+
+void SharkTopLevelBlock::emit_IR()
+{
+  builder()->SetInsertPoint(entry_block());
+
+  // Handle traps
+  if (has_trap()) {
+    iter()->force_bci(start());
+
+    current_state()->decache_for_trap();
+    builder()->CreateCall2(
+      SharkRuntime::uncommon_trap(),
+      thread(),
+      LLVMValue::jint_constant(trap_index()));
+    builder()->CreateRetVoid();
+    return;
+  }
+
+  // Parse the bytecode
+  parse_bytecode(start(), limit());
+
+  // If this block falls through to the next then it won't have been
+  // terminated by a bytecode and we have to add the branch ourselves
+  if (falls_through()) {
+    builder()->CreateBr(successor(ciTypeFlow::FALL_THROUGH)->entry_block());
+  }
+
+  // Process the successor states if not already done
+  switch (bc()) {
+  case Bytecodes::_tableswitch:
+  case Bytecodes::_lookupswitch:
+    // done by do_switch()
+    break;
+
+  default:
+    for (int i = 0; i < num_successors(); i++)
+      successor(i)->add_incoming(current_state());
+  }
+}
+
+SharkTopLevelBlock* SharkTopLevelBlock::bci_successor(int bci) const
+{
+  // XXX now with Linear Search Technology (tm)
+  for (int i = 0; i < num_successors(); i++) {
+    ciTypeFlow::Block *successor = ciblock()->successors()->at(i);
+    if (successor->start() == bci)
+      return function()->block(successor->pre_order());
+  }
+  ShouldNotReachHere();
+}
+
+void SharkTopLevelBlock::do_zero_check(SharkValue *value)
+{
+  BasicBlock *zero     = function()->CreateBlock("zero");
+  BasicBlock *not_zero = function()->CreateBlock("not_zero");
+
+  Value *a, *b;
+  switch (value->basic_type()) {
+  case T_BYTE:
+  case T_CHAR:
+  case T_SHORT:
+  case T_INT:
+    a = value->jint_value();
+    b = LLVMValue::jint_constant(0);
+    break;
+  case T_LONG:
+    a = value->jlong_value();
+    b = LLVMValue::jlong_constant(0);
+    break;
+  case T_OBJECT:
+  case T_ARRAY:
+    a = value->jobject_value();
+    b = LLVMValue::LLVMValue::null();
+    break;
+  default:
+    tty->print_cr("Unhandled type %s", type2name(value->basic_type()));
+    ShouldNotReachHere();
+  }
+
+  builder()->CreateCondBr(builder()->CreateICmpNE(a, b), not_zero, zero);
+
+  builder()->SetInsertPoint(zero);
+  SharkState *saved_state = current_state()->copy();
+  if (value->is_jobject()) {
+    call_vm_nocheck(
+      SharkRuntime::throw_NullPointerException(),
+      builder()->pointer_constant(__FILE__),
+      LLVMValue::jint_constant(__LINE__));
+  }
+  else {
+    builder()->CreateUnimplemented(__FILE__, __LINE__);
+  } 
+  handle_exception(function()->CreateGetPendingException());
+  set_current_state(saved_state);  
+
+  builder()->SetInsertPoint(not_zero);
+
+  value->set_zero_checked(true);
+}
+
+void SharkTopLevelBlock::check_bounds(SharkValue* array, SharkValue* index)
+{
+  BasicBlock *out_of_bounds = function()->CreateBlock("out_of_bounds");
+  BasicBlock *in_bounds     = function()->CreateBlock("in_bounds");
+
+  Value *length = builder()->CreateArrayLength(array->jarray_value());
+  // we use an unsigned comparison to catch negative values
+  builder()->CreateCondBr(
+    builder()->CreateICmpULT(index->jint_value(), length),
+    in_bounds, out_of_bounds);
+
+  builder()->SetInsertPoint(out_of_bounds);
+  SharkState *saved_state = current_state()->copy();
+  call_vm_nocheck(
+    SharkRuntime::throw_ArrayIndexOutOfBoundsException(),
+    builder()->pointer_constant(__FILE__),
+    LLVMValue::jint_constant(__LINE__),
+    index->jint_value());
+  handle_exception(function()->CreateGetPendingException());
+  set_current_state(saved_state);  
+
+  builder()->SetInsertPoint(in_bounds);
+}
+
+void SharkTopLevelBlock::check_pending_exception(bool attempt_catch)
+{
+  BasicBlock *exception    = function()->CreateBlock("exception");
+  BasicBlock *no_exception = function()->CreateBlock("no_exception");
+
+  Value *pending_exception_addr = function()->pending_exception_address();
+  Value *pending_exception = builder()->CreateLoad(
+    pending_exception_addr, "pending_exception");
+
+  builder()->CreateCondBr(
+    builder()->CreateICmpEQ(pending_exception, LLVMValue::null()),
+    no_exception, exception);
+
+  builder()->SetInsertPoint(exception);
+  builder()->CreateStore(LLVMValue::null(), pending_exception_addr);
+  SharkState *saved_state = current_state()->copy();
+  handle_exception(pending_exception, attempt_catch);
+  set_current_state(saved_state);
+
+  builder()->SetInsertPoint(no_exception);
+}
+
+void SharkTopLevelBlock::handle_exception(Value* exception, bool attempt_catch)
+{
+  if (attempt_catch && 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));
+
+    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();
+      }
+    }
+
+    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 *options = builder()->CreateAlloca(
+        ArrayType::get(SharkType::jint_type(), num_options),
+        LLVMValue::jint_constant(1));
+
+      for (int i = 0; i < num_options; i++)
+        builder()->CreateStore(
+          LLVMValue::jint_constant(indexes[i]),
+          builder()->CreateStructGEP(options, i));
+
+      Value *index = call_vm_nocheck(
+        SharkRuntime::find_exception_handler(),
+        builder()->CreateStructGEP(options, 0),
+        LLVMValue::jint_constant(num_options));
+      check_pending_exception(false);
+
+      // 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);
+    }
+
+    // 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());
+      handler->add_incoming(current_state());
+      return;
+    }
+  }
+
+  // No exception handler was found; unwind and return
+  handle_return(T_VOID, exception);
+}
+
+void SharkTopLevelBlock::add_safepoint()
+{
+  BasicBlock *orig_block = builder()->GetInsertBlock();
+  SharkState *orig_state = current_state()->copy();
+
+  BasicBlock *do_safepoint = function()->CreateBlock("do_safepoint");
+  BasicBlock *safepointed  = function()->CreateBlock("safepointed");
+
+  Value *state = builder()->CreateLoad(
+    builder()->CreateIntToPtr(
+      builder()->pointer_constant(SafepointSynchronize::address_of_state()),
+      PointerType::getUnqual(SharkType::jint_type())),
+    "state");
+
+  builder()->CreateCondBr(
+    builder()->CreateICmpEQ(
+      state,
+      LLVMValue::jint_constant(SafepointSynchronize::_synchronizing)),
+    do_safepoint, safepointed);
+
+  builder()->SetInsertPoint(do_safepoint);
+  call_vm(SharkRuntime::safepoint());
+  BasicBlock *safepointed_block = builder()->GetInsertBlock();  
+  builder()->CreateBr(safepointed);
+
+  builder()->SetInsertPoint(safepointed);
+  current_state()->merge(orig_state, orig_block, safepointed_block);
+}
+
+void SharkTopLevelBlock::call_register_finalizer(Value *receiver)
+{
+  BasicBlock *orig_block = builder()->GetInsertBlock();
+  SharkState *orig_state = current_state()->copy();
+
+  BasicBlock *do_call = function()->CreateBlock("has_finalizer");
+  BasicBlock *done    = function()->CreateBlock("done");
+
+  Value *klass = builder()->CreateValueOfStructEntry(
+    receiver,
+    in_ByteSize(oopDesc::klass_offset_in_bytes()),
+    SharkType::jobject_type(),
+    "klass");
+  
+  Value *klass_part = builder()->CreateAddressOfStructEntry(
+    klass,
+    in_ByteSize(klassOopDesc::klass_part_offset_in_bytes()),
+    SharkType::klass_type(),
+    "klass_part");
+
+  Value *access_flags = builder()->CreateValueOfStructEntry(
+    klass_part,
+    in_ByteSize(Klass::access_flags_offset_in_bytes()),
+    SharkType::jint_type(),
+    "access_flags");
+
+  builder()->CreateCondBr(
+    builder()->CreateICmpNE(
+      builder()->CreateAnd(
+        access_flags,
+        LLVMValue::jint_constant(JVM_ACC_HAS_FINALIZER)),
+      LLVMValue::jint_constant(0)),
+    do_call, done);
+
+  builder()->SetInsertPoint(do_call);
+  call_vm(SharkRuntime::register_finalizer(), receiver);
+  BasicBlock *branch_block = builder()->GetInsertBlock();  
+  builder()->CreateBr(done);
+
+  builder()->SetInsertPoint(done);
+  current_state()->merge(orig_state, orig_block, branch_block);
+}
+
+void SharkTopLevelBlock::handle_return(BasicType type, Value* exception)
+{
+  assert (exception == NULL || type == T_VOID, "exception OR result, please");
+
+  if (exception)
+    builder()->CreateStore(exception, function()->exception_slot());
+
+  release_locked_monitors();
+  if (target()->is_synchronized())
+    release_method_lock();
+  
+  if (exception) {
+    exception = builder()->CreateLoad(function()->exception_slot());
+    builder()->CreateStore(exception, function()->pending_exception_address());
+  }
+
+  Value *result_addr = function()->CreatePopFrame(type2size[type]);
+  if (type != T_VOID) {
+    builder()->CreateStore(
+      pop_result(type)->generic_value(),
+      builder()->CreateIntToPtr(
+        result_addr,
+        PointerType::getUnqual(SharkType::to_stackType(type))));
+  }
+
+  builder()->CreateRetVoid();
+}
+
+void SharkTopLevelBlock::release_locked_monitors()
+{
+  int base = target()->is_synchronized();
+  for (int i = function()->monitor_count() - 1; i >= base; i--) {
+    BasicBlock *locked   = function()->CreateBlock("locked");
+    BasicBlock *unlocked = function()->CreateBlock("unlocked");
+
+    Value *object = function()->monitor(i)->object();
+    builder()->CreateCondBr(
+      builder()->CreateICmpNE(object, LLVMValue::null()),
+      locked, unlocked);
+    
+    builder()->SetInsertPoint(locked);
+    builder()->CreateUnimplemented(__FILE__, __LINE__);
+    builder()->CreateUnreachable();
+
+    builder()->SetInsertPoint(unlocked);
+  }
+}
+
+Value *SharkTopLevelBlock::lookup_for_ldc()
+{
+  SharkConstantPool constants(this);
+
+  BasicBlock *resolved       = function()->CreateBlock("resolved");
+  BasicBlock *resolved_class = function()->CreateBlock("resolved_class");
+  BasicBlock *unresolved     = function()->CreateBlock("unresolved");
+  BasicBlock *unknown        = function()->CreateBlock("unknown");
+  BasicBlock *done           = function()->CreateBlock("done");
+
+  SwitchInst *switchinst = builder()->CreateSwitch(
+    constants.tag_at(iter()->get_constant_index()),
+    unknown, 5);
+
+  switchinst->addCase(
+    LLVMValue::jbyte_constant(JVM_CONSTANT_String), resolved);
+  switchinst->addCase(
+    LLVMValue::jbyte_constant(JVM_CONSTANT_Class), resolved_class);
+  switchinst->addCase(
+    LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedString), unresolved);
+  switchinst->addCase(
+    LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedClass), unresolved);
+  switchinst->addCase(
+    LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedClassInError),
+    unresolved);
+
+  builder()->SetInsertPoint(resolved);
+  Value *resolved_value = constants.object_at(iter()->get_constant_index());
+  builder()->CreateBr(done);
+
+  builder()->SetInsertPoint(resolved_class);
+  Value *resolved_class_value
+    = constants.object_at(iter()->get_constant_index());
+  resolved_class_value
+    = builder()->CreatePtrToInt(resolved_class_value,
+                                SharkType::intptr_type());
+  resolved_class_value
+    = (builder()->CreateAdd
+       (resolved_class_value,
+        (LLVMValue::intptr_constant
+         (klassOopDesc::klass_part_offset_in_bytes()
+          + Klass::java_mirror_offset_in_bytes()))));
+  // XXX FIXME: We need a memory barrier before this load.
+  resolved_class_value
+    = (builder()->CreateLoad
+       (builder()->CreateIntToPtr
+        (resolved_class_value,
+         PointerType::getUnqual(SharkType::jobject_type()))));
+  builder()->CreateBr(done);
+
+  builder()->SetInsertPoint(unresolved);
+  builder()->CreateUnimplemented(__FILE__, __LINE__);
+  Value *unresolved_value = LLVMValue::null();
+  builder()->CreateBr(done);
+
+  builder()->SetInsertPoint(unknown);
+  builder()->CreateShouldNotReachHere(__FILE__, __LINE__);
+  builder()->CreateUnreachable();
+
+  builder()->SetInsertPoint(done);
+  PHINode *phi = builder()->CreatePHI(SharkType::jobject_type(), "constant");
+  phi->addIncoming(resolved_value, resolved);
+  phi->addIncoming(resolved_class_value, resolved_class);
+  phi->addIncoming(unresolved_value, unresolved);
+  return phi;
+}
+
+Value* SharkTopLevelBlock::lookup_for_field_access()
+{
+  SharkConstantPool constants(this);
+  Value *cache = constants.cache_entry_at(iter()->get_field_index());
+
+  return builder()->CreateValueOfStructEntry(
+   cache, ConstantPoolCacheEntry::f1_offset(),
+   SharkType::jobject_type(),
+   "object");
+}
+
+void SharkTopLevelBlock::do_arraylength()
+{
+  SharkValue *array = pop();
+  check_null(array);
+  Value *length = builder()->CreateArrayLength(array->jarray_value());
+  push(SharkValue::create_jint(length));
+}
+
+void SharkTopLevelBlock::do_aload(BasicType basic_type)
+{
+  SharkValue *index = pop();
+  SharkValue *array = pop();
+
+  assert(array->type()->is_array_klass(), "should be");
+  ciType *element_type = ((ciArrayKlass *) array->type())->element_type();
+  assert((element_type->basic_type() == T_BOOLEAN && basic_type == T_BYTE) ||
+         (element_type->basic_type() == T_ARRAY && basic_type == T_OBJECT) ||
+         (element_type->basic_type() == basic_type), "type mismatch");
+
+  check_null(array);
+  check_bounds(array, index);
+
+  Value *value = builder()->CreateLoad(
+    builder()->CreateArrayAddress(
+      array->jarray_value(), basic_type, index->jint_value()));
+
+  const Type *stack_type = SharkType::to_stackType(basic_type);
+  if (value->getType() != stack_type)
+    value = builder()->CreateIntCast(value, stack_type, basic_type != T_CHAR);
+
+  switch (basic_type) {
+  case T_BYTE:
+  case T_CHAR:
+  case T_SHORT:
+  case T_INT:
+    push(SharkValue::create_jint(value));
+    break;
+
+  case T_LONG:
+    push(SharkValue::create_jlong(value));
+    break;
+
+  case T_FLOAT:
+    push(SharkValue::create_jfloat(value));
+    break;
+
+  case T_DOUBLE:
+    push(SharkValue::create_jdouble(value));
+    break;
+    
+  case T_OBJECT:
+    push(SharkValue::create_generic(element_type, value));
+    break;
+
+  default:
+    tty->print_cr("Unhandled type %s", type2name(basic_type));
+    ShouldNotReachHere();
+  }
+}
+
+void SharkTopLevelBlock::do_astore(BasicType basic_type)
+{
+  SharkValue *svalue = pop();
+  SharkValue *index  = pop();
+  SharkValue *array  = pop();
+
+  assert(array->type()->is_array_klass(), "should be");
+  ciType *element_type = ((ciArrayKlass *) array->type())->element_type();
+  assert((element_type->basic_type() == T_BOOLEAN && basic_type == T_BYTE) ||
+         (element_type->basic_type() == T_ARRAY && basic_type == T_OBJECT) ||
+         (element_type->basic_type() == basic_type), "type mismatch");
+
+  check_null(array);
+  check_bounds(array, index);
+
+  Value *value;
+  switch (basic_type) {
+  case T_BYTE:
+  case T_CHAR:
+  case T_SHORT:
+  case T_INT:
+    value = svalue->jint_value();
+    break;
+
+  case T_LONG:
+    value = svalue->jlong_value();
+    break;
+
+  case T_FLOAT:
+    value = svalue->jfloat_value();
+    break;
+
+  case T_DOUBLE:
+    value = svalue->jdouble_value();
+    break;
+
+  case T_OBJECT:
+    value = svalue->jobject_value();
+    // XXX assignability check
+    break;
+
+  default:
+    tty->print_cr("Unhandled type %s", type2name(basic_type));
+    ShouldNotReachHere();
+  }
+
+  const Type *array_type = SharkType::to_arrayType(basic_type);
+  if (value->getType() != array_type)
+    value = builder()->CreateIntCast(value, array_type, basic_type != T_CHAR);
+
+  Value *addr = builder()->CreateArrayAddress(
+    array->jarray_value(), basic_type, index->jint_value(), "addr");
+
+  builder()->CreateStore(value, addr);
+
+  if (!element_type->is_primitive_type())
+    builder()->CreateUpdateBarrierSet(oopDesc::bs(), addr);
+}
+
+void SharkTopLevelBlock::do_return(BasicType type)
+{
+  if (target()->intrinsic_id() == vmIntrinsics::_Object_init)
+    call_register_finalizer(local(0)->jobject_value());
+  else
+    add_safepoint();
+  handle_return(type, NULL);
+}
+
+void SharkTopLevelBlock::do_athrow()
+{
+  SharkValue *exception = pop();
+  check_null(exception);
+  handle_exception(exception->jobject_value());
+}
+
+void SharkTopLevelBlock::do_goto()
+{
+  builder()->CreateBr(successor(ciTypeFlow::GOTO_TARGET)->entry_block());
+}
+
+void SharkTopLevelBlock::do_jsr()
+{
+  push(SharkValue::create_returnAddress(iter()->next_bci()));
+  builder()->CreateBr(successor(ciTypeFlow::GOTO_TARGET)->entry_block());
+}
+
+void SharkTopLevelBlock::do_ret()
+{
+  assert(local(iter()->get_index())->returnAddress_value() ==
+         successor(ciTypeFlow::GOTO_TARGET)->start(), "should be");
+  builder()->CreateBr(successor(ciTypeFlow::GOTO_TARGET)->entry_block());
+}
+ 
+void SharkTopLevelBlock::do_if(ICmpInst::Predicate p, SharkValue *b, SharkValue *a)
+{
+  Value *llvm_a, *llvm_b;
+  if (a->is_jobject()) {
+    llvm_a = a->intptr_value(builder());
+    llvm_b = b->intptr_value(builder());
+  }
+  else {
+    llvm_a = a->jint_value();
+    llvm_b = b->jint_value();
+  }
+                          
+  builder()->CreateCondBr(
+    builder()->CreateICmp(p, llvm_a, llvm_b),
+    successor(ciTypeFlow::IF_TAKEN)->entry_block(),
+    successor(ciTypeFlow::IF_NOT_TAKEN)->entry_block());
+}
+
+void SharkTopLevelBlock::do_switch()
+{
+  int len = switch_table_length();
+
+  SharkTopLevelBlock *dest_block = successor(ciTypeFlow::SWITCH_DEFAULT);
+  SwitchInst *switchinst = builder()->CreateSwitch(
+    pop()->jint_value(), dest_block->entry_block(), len);
+  dest_block->add_incoming(current_state());
+
+  for (int i = 0; i < len; i++) {
+    int dest_bci = switch_dest(i);
+    if (dest_bci != switch_default_dest()) {
+      dest_block = bci_successor(dest_bci);
+      switchinst->addCase(
+        LLVMValue::jint_constant(switch_key(i)),
+        dest_block->entry_block());
+      dest_block->add_incoming(current_state());      
+    }
+  }
+}
+
+// Figure out what type of call this is.
+//  - Direct calls are where the callee is fixed.
+//  - Interface and Virtual calls require lookup at runtime.
+// NB some invokevirtuals can be resolved to direct calls.
+SharkTopLevelBlock::CallType SharkTopLevelBlock::get_call_type(ciMethod* method)
+{
+  if (bc() == Bytecodes::_invokeinterface)
+    return CALL_INTERFACE;
+  else if (bc() == Bytecodes::_invokevirtual && !method->is_final_method())
+    return CALL_VIRTUAL;
+  else
+    return CALL_DIRECT;
+}
+
+Value *SharkTopLevelBlock::get_callee(CallType    call_type,
+                              ciMethod*   method,
+                              SharkValue* receiver)
+{
+  switch (call_type) {
+  case CALL_DIRECT:
+    return get_direct_callee(method);
+  case CALL_VIRTUAL:
+    return get_virtual_callee(receiver, method);
+  case CALL_INTERFACE:
+    return get_interface_callee(receiver);
+  default:
+    ShouldNotReachHere();
+  } 
+}
+
+// Direct calls can be made when the callee is fixed.
+// invokestatic and invokespecial are always direct;
+// invokevirtual is direct in some circumstances.
+Value *SharkTopLevelBlock::get_direct_callee(ciMethod* method)
+{
+  SharkConstantPool constants(this);
+  Value *cache = constants.cache_entry_at(iter()->get_method_index());
+  return builder()->CreateValueOfStructEntry(
+    cache,
+    bc() == Bytecodes::_invokevirtual ?
+      ConstantPoolCacheEntry::f2_offset() :
+      ConstantPoolCacheEntry::f1_offset(),
+    SharkType::methodOop_type(),
+    "callee");
+}
+
+// Non-direct virtual calls are handled here
+Value *SharkTopLevelBlock::get_virtual_callee(SharkValue* receiver,
+                                              ciMethod*   method)
+{
+  Value *klass = builder()->CreateValueOfStructEntry(
+    receiver->jobject_value(),
+    in_ByteSize(oopDesc::klass_offset_in_bytes()),
+    SharkType::jobject_type(),
+    "klass");
+
+  Value *index;
+  if (!method->holder()->is_linked()) {
+    // Yuck, we have to do this one slow :(
+    // XXX should we trap on this?
+    NOT_PRODUCT(warning("unresolved invokevirtual in %s", function()->name()));
+    SharkConstantPool constants(this);
+    Value *cache = constants.cache_entry_at(iter()->get_method_index());
+    index = builder()->CreateValueOfStructEntry(
+      cache, ConstantPoolCacheEntry::f2_offset(),
+      SharkType::intptr_type(),
+      "index");
+  }
+  else {
+    index = LLVMValue::intptr_constant(method->vtable_index());
+  }
+
+  return builder()->CreateLoad(
+    builder()->CreateArrayAddress(
+      klass,
+      SharkType::methodOop_type(),
+      vtableEntry::size() * wordSize,
+      in_ByteSize(instanceKlass::vtable_start_offset() * wordSize),
+      index),
+    "callee");
+}
+
+// Interpreter-style virtual call lookup
+Value* SharkTopLevelBlock::get_virtual_callee(Value *cache, SharkValue *receiver)
+{
+  BasicBlock *final      = function()->CreateBlock("final");
+  BasicBlock *not_final  = function()->CreateBlock("not_final");
+  BasicBlock *got_callee = function()->CreateBlock("got_callee");
+
+  Value *flags = builder()->CreateValueOfStructEntry(
+    cache, ConstantPoolCacheEntry::flags_offset(),
+    SharkType::intptr_type(),
+    "flags");
+
+  const int mask = 1 << ConstantPoolCacheEntry::vfinalMethod;
+  builder()->CreateCondBr(
+    builder()->CreateICmpNE(
+      builder()->CreateAnd(flags, LLVMValue::intptr_constant(mask)),
+      LLVMValue::intptr_constant(0)),
+    final, not_final);
+
+  // For final methods f2 is the actual address of the method
+  builder()->SetInsertPoint(final);
+  Value *final_callee = builder()->CreateValueOfStructEntry(
+    cache, ConstantPoolCacheEntry::f2_offset(),
+    SharkType::methodOop_type(),
+    "final_callee");
+  builder()->CreateBr(got_callee);
+
+  // For non-final methods f2 is the index into the vtable
+  builder()->SetInsertPoint(not_final);
+  Value *klass = builder()->CreateValueOfStructEntry(
+    receiver->jobject_value(),
+    in_ByteSize(oopDesc::klass_offset_in_bytes()),
+    SharkType::jobject_type(),
+    "klass");
+
+  Value *index = builder()->CreateValueOfStructEntry(
+    cache, ConstantPoolCacheEntry::f2_offset(),
+    SharkType::intptr_type(),
+    "index");
+
+  Value *nonfinal_callee = builder()->CreateLoad(
+    builder()->CreateArrayAddress(
+      klass,
+      SharkType::methodOop_type(),
+      vtableEntry::size() * wordSize,
+      in_ByteSize(instanceKlass::vtable_start_offset() * wordSize),
+      index),
+    "nonfinal_callee");
+  builder()->CreateBr(got_callee);
+
+  builder()->SetInsertPoint(got_callee);
+  PHINode *callee = builder()->CreatePHI(
+    SharkType::methodOop_type(), "callee");
+  callee->addIncoming(final_callee, final);
+  callee->addIncoming(nonfinal_callee, not_final);
+
+  return callee;
+}
+
+// Interpreter-style interface call lookup
+Value* SharkTopLevelBlock::get_interface_callee(SharkValue *receiver)
+{
+  SharkConstantPool constants(this);
+  Value *cache = constants.cache_entry_at(iter()->get_method_index());
+
+  BasicBlock *hacky      = function()->CreateBlock("hacky");
+  BasicBlock *normal     = function()->CreateBlock("normal");
+  BasicBlock *loop       = function()->CreateBlock("loop");
+  BasicBlock *got_null   = function()->CreateBlock("got_null");
+  BasicBlock *not_null   = function()->CreateBlock("not_null");
+  BasicBlock *next       = function()->CreateBlock("next");
+  BasicBlock *got_entry  = function()->CreateBlock("got_entry");
+  BasicBlock *got_callee = function()->CreateBlock("got_callee");
+
+  Value *flags = builder()->CreateValueOfStructEntry(
+    cache, ConstantPoolCacheEntry::flags_offset(),
+    SharkType::intptr_type(),
+    "flags");
+
+  const int mask = 1 << ConstantPoolCacheEntry::methodInterface;
+  builder()->CreateCondBr(
+    builder()->CreateICmpNE(
+      builder()->CreateAnd(flags, LLVMValue::intptr_constant(mask)),
+      LLVMValue::intptr_constant(0)),
+    hacky, normal);
+
+  // Workaround for the case where we encounter an invokeinterface,
+  // but should really have an invokevirtual since the resolved
+  // method is a virtual method in java.lang.Object. This is a
+  // corner case in the spec but is presumably legal, and while
+  // javac does not generate this code there's no reason it could
+  // not be produced by a compliant java compiler.  See
+  // cpCacheOop.cpp for more details.
+  builder()->SetInsertPoint(hacky);
+  Value *hacky_callee = get_virtual_callee(cache, receiver);
+  BasicBlock *got_hacky = builder()->GetInsertBlock();
+  builder()->CreateBr(got_callee);
+
+  // Locate the receiver's itable
+  builder()->SetInsertPoint(normal);
+  Value *object_klass = builder()->CreateValueOfStructEntry(
+    receiver->jobject_value(), in_ByteSize(oopDesc::klass_offset_in_bytes()),
+    SharkType::jobject_type(),
+    "object_klass");
+
+  Value *vtable_start = builder()->CreateAdd(
+    builder()->CreatePtrToInt(object_klass, SharkType::intptr_type()),
+    LLVMValue::intptr_constant(
+      instanceKlass::vtable_start_offset() * HeapWordSize),
+    "vtable_start");
+
+  Value *vtable_length = builder()->CreateValueOfStructEntry(
+    object_klass,
+    in_ByteSize(instanceKlass::vtable_length_offset() * HeapWordSize),
+    SharkType::jint_type(),
+    "vtable_length");
+  vtable_length =
+    builder()->CreateIntCast(vtable_length, SharkType::intptr_type(), false);
+
+  bool needs_aligning = HeapWordsPerLong > 1;
+  const char *itable_start_name = "itable_start";
+  Value *itable_start = builder()->CreateAdd(
+    vtable_start,
+    builder()->CreateShl(
+      vtable_length,
+      LLVMValue::intptr_constant(exact_log2(vtableEntry::size() * wordSize))),
+    needs_aligning ? "" : itable_start_name);
+  if (needs_aligning)
+    itable_start = builder()->CreateAlign(
+      itable_start, BytesPerLong, itable_start_name);
+
+  // Locate this interface's entry in the table
+  Value *iklass = builder()->CreateValueOfStructEntry(
+    cache, ConstantPoolCacheEntry::f1_offset(),
+    SharkType::jobject_type(),
+    "iklass");
+
+  builder()->CreateBr(loop);
+  builder()->SetInsertPoint(loop);
+  PHINode *itable_entry_addr = builder()->CreatePHI(
+    SharkType::intptr_type(), "itable_entry_addr");
+  itable_entry_addr->addIncoming(itable_start, normal);
+
+  Value *itable_entry = builder()->CreateIntToPtr(
+    itable_entry_addr, SharkType::itableOffsetEntry_type(), "itable_entry");
+
+  Value *itable_iklass = builder()->CreateValueOfStructEntry(
+    itable_entry,
+    in_ByteSize(itableOffsetEntry::interface_offset_in_bytes()),
+    SharkType::jobject_type(),
+    "itable_iklass");
+
+  builder()->CreateCondBr(
+    builder()->CreateICmpEQ(itable_iklass, LLVMValue::null()),
+    got_null, not_null);
+
+  // A null entry means that the class doesn't implement the
+  // interface, and wasn't the same as the class checked when
+  // the interface was resolved.
+  builder()->SetInsertPoint(got_null);
+  builder()->CreateUnimplemented(__FILE__, __LINE__);
+  builder()->CreateUnreachable();
+                          
+  builder()->SetInsertPoint(not_null);
+  builder()->CreateCondBr(
+    builder()->CreateICmpEQ(itable_iklass, iklass),
+    got_entry, next);
+
+  builder()->SetInsertPoint(next);
+  Value *next_entry = builder()->CreateAdd(
+    itable_entry_addr,
+    LLVMValue::intptr_constant(itableOffsetEntry::size() * wordSize));
+  builder()->CreateBr(loop);
+  itable_entry_addr->addIncoming(next_entry, next);
+
+  // Locate the method pointer
+  builder()->SetInsertPoint(got_entry);
+  Value *offset = builder()->CreateValueOfStructEntry(
+    itable_entry,
+    in_ByteSize(itableOffsetEntry::offset_offset_in_bytes()),
+    SharkType::jint_type(),
+    "offset");
+  offset =
+    builder()->CreateIntCast(offset, SharkType::intptr_type(), false);
+
+  Value *index = builder()->CreateValueOfStructEntry(
+    cache, ConstantPoolCacheEntry::f2_offset(),
+    SharkType::intptr_type(),
+    "index");
+
+  Value *normal_callee = builder()->CreateLoad(
+    builder()->CreateIntToPtr(
+      builder()->CreateAdd(
+        builder()->CreateAdd(
+          builder()->CreateAdd(
+            builder()->CreatePtrToInt(
+              object_klass, SharkType::intptr_type()),
+            offset),
+          builder()->CreateShl(
+            index,
+            LLVMValue::intptr_constant(
+              exact_log2(itableMethodEntry::size() * wordSize)))),
+        LLVMValue::intptr_constant(
+          itableMethodEntry::method_offset_in_bytes())),
+      PointerType::getUnqual(SharkType::methodOop_type())),
+    "normal_callee");
+  BasicBlock *got_normal = builder()->GetInsertBlock();
+  builder()->CreateBr(got_callee);
+
+  builder()->SetInsertPoint(got_callee);
+  PHINode *callee = builder()->CreatePHI(
+    SharkType::methodOop_type(), "callee");
+  callee->addIncoming(hacky_callee, got_hacky);
+  callee->addIncoming(normal_callee, got_normal);
+
+  return callee;
+} 
+
+void SharkTopLevelBlock::do_call()
+{
+  bool will_link;
+  ciMethod *method = iter()->get_method(will_link);
+  assert(will_link, "typeflow responsibility");
+
+  // Figure out what type of call this is
+  CallType call_type = get_call_type(method);
+
+  // Find the receiver in the stack.  We do this before
+  // trying to inline because the inliner can only use
+  // zero-checked values, not being able to perform the
+  // check itself.
+  SharkValue *receiver = NULL;
+  if (bc() != Bytecodes::_invokestatic) {
+    receiver = xstack(method->arg_size() - 1);
+    check_null(receiver);
+  }
+
+  // Try to inline the call
+  if (call_type == CALL_DIRECT) {
+    if (SharkInliner::attempt_inline(method, current_state()))
+      return;
+  }
+
+  // Find the method we are calling
+  Value *callee = get_callee(call_type, method, receiver);
+
+  // Load the SharkEntry from the callee
+  Value *base_pc = builder()->CreateValueOfStructEntry(
+    callee, methodOopDesc::from_interpreted_offset(),
+    SharkType::intptr_type(),
+    "base_pc");
+
+  // Load the entry point from the SharkEntry
+  Value *entry_point = builder()->CreateLoad(
+    builder()->CreateIntToPtr(
+      builder()->CreateAdd(
+        base_pc,
+        LLVMValue::intptr_constant(in_bytes(ZeroEntry::entry_point_offset()))),
+      PointerType::getUnqual(
+        PointerType::getUnqual(SharkType::entry_point_type()))),
+    "entry_point");
+
+  // Make the call
+  current_state()->decache_for_Java_call(method);
+  builder()->CreateCall3(entry_point, callee, base_pc, thread());
+  current_state()->cache_after_Java_call(method);
+
+  // Check for pending exceptions
+  check_pending_exception();
+}
+
+void SharkTopLevelBlock::do_instance_check()
+{
+  // Leave the object on the stack until after all the VM calls
+  assert(xstack(0)->is_jobject(), "should be");
+  
+  ciKlass *klass = NULL;
+  if (bc() == Bytecodes::_checkcast) {
+    bool will_link;
+    klass = iter()->get_klass(will_link);
+    if (!will_link) {
+      // XXX why is this not typeflow's responsibility?
+      NOT_PRODUCT(warning("unresolved checkcast in %s", function()->name()));
+      klass = (ciKlass *) xstack(0)->type();
+    }
+  }
+
+  BasicBlock *not_null      = function()->CreateBlock("not_null");
+  BasicBlock *fast_path     = function()->CreateBlock("fast_path");
+  BasicBlock *slow_path     = function()->CreateBlock("slow_path");
+  BasicBlock *got_klass     = function()->CreateBlock("got_klass");
+  BasicBlock *subtype_check = function()->CreateBlock("subtype_check");
+  BasicBlock *is_instance   = function()->CreateBlock("is_instance");
+  BasicBlock *not_instance  = function()->CreateBlock("not_instance");
+  BasicBlock *merge1        = function()->CreateBlock("merge1");
+  BasicBlock *merge2        = function()->CreateBlock("merge2");
+
+  enum InstanceCheckStates {
+    IC_IS_NULL,
+    IC_IS_INSTANCE,
+    IC_NOT_INSTANCE,
+  };
+
+  // Null objects aren't instances of anything
+  builder()->CreateCondBr(
+    builder()->CreateICmpEQ(xstack(0)->jobject_value(), LLVMValue::null()),
+    merge2, not_null);
+  BasicBlock *null_block = builder()->GetInsertBlock();
+  SharkState *null_state = current_state()->copy();
+
+  // Get the class we're checking against
+  builder()->SetInsertPoint(not_null);
+  SharkConstantPool constants(this);
+  Value *tag = constants.tag_at(iter()->get_klass_index());
+  builder()->CreateCondBr(
+    builder()->CreateOr(
+      builder()->CreateICmpEQ(
+        tag, LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedClass)),
+      builder()->CreateICmpEQ(
+        tag, LLVMValue::jbyte_constant(JVM_CONSTANT_UnresolvedClassInError))),
+    slow_path, fast_path);
+
+  // The fast path
+  builder()->SetInsertPoint(fast_path);
+  BasicBlock *fast_block = builder()->GetInsertBlock();
+  SharkState *fast_state = current_state()->copy();
+  Value *fast_klass = constants.object_at(iter()->get_klass_index());
+  builder()->CreateBr(got_klass);
+
+  // The slow path
+  builder()->SetInsertPoint(slow_path);
+  call_vm(
+    SharkRuntime::resolve_klass(),
+    LLVMValue::jint_constant(iter()->get_klass_index()));
+  Value *slow_klass = function()->CreateGetVMResult();
+  BasicBlock *slow_block = builder()->GetInsertBlock();  
+  builder()->CreateBr(got_klass);
+
+  // We have the class to test against
+  builder()->SetInsertPoint(got_klass);
+  current_state()->merge(fast_state, fast_block, slow_block);
+  PHINode *check_klass = builder()->CreatePHI(
+    SharkType::jobject_type(), "check_klass");
+  check_klass->addIncoming(fast_klass, fast_block);
+  check_klass->addIncoming(slow_klass, slow_block);
+
+  // Get the class of the object being tested
+  Value *object_klass = builder()->CreateValueOfStructEntry(
+    xstack(0)->jobject_value(), in_ByteSize(oopDesc::klass_offset_in_bytes()),
+    SharkType::jobject_type(),
+    "object_klass");
+
+  // Perform the check
+  builder()->CreateCondBr(
+    builder()->CreateICmpEQ(check_klass, object_klass),
+    is_instance, subtype_check);
+
+  builder()->SetInsertPoint(subtype_check);
+  builder()->CreateCondBr(
+    builder()->CreateICmpNE(
+      builder()->CreateCall2(
+        SharkRuntime::is_subtype_of(), check_klass, object_klass),
+      LLVMValue::jbyte_constant(0)),
+    is_instance, not_instance);
+
+  builder()->SetInsertPoint(is_instance);
+  builder()->CreateBr(merge1);
+
+  builder()->SetInsertPoint(not_instance);
+  builder()->CreateBr(merge1);
+
+  // First merge
+  builder()->SetInsertPoint(merge1);
+  PHINode *nonnull_result = builder()->CreatePHI(
+    SharkType::jint_type(), "nonnull_result");
+  nonnull_result->addIncoming(
+    LLVMValue::jint_constant(IC_IS_INSTANCE), is_instance);
+  nonnull_result->addIncoming(
+    LLVMValue::jint_constant(IC_NOT_INSTANCE), not_instance);
+  BasicBlock *nonnull_block = builder()->GetInsertBlock();
+  builder()->CreateBr(merge2);
+  
+  // Second merge
+  builder()->SetInsertPoint(merge2);
+  current_state()->merge(null_state, null_block, nonnull_block);
+  PHINode *result = builder()->CreatePHI(
+    SharkType::jint_type(), "result");
+  result->addIncoming(LLVMValue::jint_constant(IC_IS_NULL), null_block);
+  result->addIncoming(nonnull_result, nonnull_block);
+
+  // We can finally pop the object!
+  Value *object = pop()->jobject_value();
+
+  // Handle the result
+  if (bc() == Bytecodes::_checkcast) {
+    BasicBlock *failure = function()->CreateBlock("failure");
+    BasicBlock *success = function()->CreateBlock("success");
+
+    builder()->CreateCondBr(
+      builder()->CreateICmpNE(
+        result, LLVMValue::jint_constant(IC_NOT_INSTANCE)),
+      success, failure);
+
+    builder()->SetInsertPoint(failure);
+    builder()->CreateUnimplemented(__FILE__, __LINE__);
+    builder()->CreateUnreachable();
+
+    builder()->SetInsertPoint(success);
+    push(SharkValue::create_generic(klass, object));
+  }
+  else {
+    push(
+      SharkValue::create_jint(
+        builder()->CreateIntCast(
+          builder()->CreateICmpEQ(
+            result, LLVMValue::jint_constant(IC_IS_INSTANCE)),
+          SharkType::jint_type(), false)));
+  }
+}
+
+void SharkTopLevelBlock::do_new()
+{
+  bool will_link;
+  ciInstanceKlass* klass = iter()->get_klass(will_link)->as_instance_klass();
+  assert(will_link, "typeflow responsibility");
+
+  BasicBlock *tlab_alloc          = NULL;
+  BasicBlock *got_tlab            = NULL;
+  BasicBlock *heap_alloc          = NULL;
+  BasicBlock *retry               = NULL;
+  BasicBlock *got_heap            = NULL;
+  BasicBlock *initialize          = NULL;
+  BasicBlock *got_fast            = NULL;
+  BasicBlock *slow_alloc_and_init = NULL;
+  BasicBlock *got_slow            = NULL;
+  BasicBlock *push_object         = NULL;
+
+  SharkState *fast_state = NULL;
+  
+  Value *tlab_object = NULL;
+  Value *heap_object = NULL;
+  Value *fast_object = NULL;
+  Value *slow_object = NULL;
+  Value *object      = NULL;
+
+  SharkConstantPool constants(this);
+
+  // The fast path
+  if (!Klass::layout_helper_needs_slow_path(klass->layout_helper())) {
+    if (UseTLAB) {
+      tlab_alloc        = function()->CreateBlock("tlab_alloc");
+      got_tlab          = function()->CreateBlock("got_tlab");
+    }
+    heap_alloc          = function()->CreateBlock("heap_alloc");
+    retry               = function()->CreateBlock("retry");
+    got_heap            = function()->CreateBlock("got_heap");
+    initialize          = function()->CreateBlock("initialize");
+    slow_alloc_and_init = function()->CreateBlock("slow_alloc_and_init");
+    push_object         = function()->CreateBlock("push_object");
+
+    builder()->CreateCondBr(
+      builder()->CreateICmpEQ(
+        constants.tag_at(iter()->get_klass_index()),
+        LLVMValue::jbyte_constant(JVM_CONSTANT_Class)),
+      UseTLAB ? tlab_alloc : heap_alloc, slow_alloc_and_init);
+    
+    size_t size_in_bytes = klass->size_helper() << LogHeapWordSize;
+
+    // Thread local allocation
+    if (UseTLAB) {
+      builder()->SetInsertPoint(tlab_alloc);
+
+      Value *top_addr = builder()->CreateAddressOfStructEntry(
+        thread(), Thread::tlab_top_offset(),
+        PointerType::getUnqual(SharkType::intptr_type()),
+        "top_addr");
+
+      Value *end = builder()->CreateValueOfStructEntry(
+        thread(), Thread::tlab_end_offset(),
+        SharkType::intptr_type(),
+        "end");
+
+      Value *old_top = builder()->CreateLoad(top_addr, "old_top");
+      Value *new_top = builder()->CreateAdd(
+        old_top, LLVMValue::intptr_constant(size_in_bytes));
+
+      builder()->CreateCondBr(
+        builder()->CreateICmpULE(new_top, end),
+        got_tlab, heap_alloc);
+
+      builder()->SetInsertPoint(got_tlab);
+      tlab_object = builder()->CreateIntToPtr(
+        old_top, SharkType::jobject_type(), "tlab_object");
+
+      builder()->CreateStore(new_top, top_addr);
+      builder()->CreateBr(initialize);
+    }
+
+    // Heap allocation
+    builder()->SetInsertPoint(heap_alloc);
+
+    Value *top_addr = builder()->CreateIntToPtr(
+	builder()->pointer_constant(Universe::heap()->top_addr()),
+      PointerType::getUnqual(SharkType::intptr_type()),
+      "top_addr");
+
+    Value *end = builder()->CreateLoad(
+      builder()->CreateIntToPtr(
+        builder()->pointer_constant(Universe::heap()->end_addr()),
+        PointerType::getUnqual(SharkType::intptr_type())),
+      "end");
+
+    builder()->CreateBr(retry);
+    builder()->SetInsertPoint(retry);
+
+    Value *old_top = builder()->CreateLoad(top_addr, "top");
+    Value *new_top = builder()->CreateAdd(
+      old_top, LLVMValue::intptr_constant(size_in_bytes));
+
+    builder()->CreateCondBr(
+      builder()->CreateICmpULE(new_top, end),
+      got_heap, slow_alloc_and_init);
+
+    builder()->SetInsertPoint(got_heap);
+    heap_object = builder()->CreateIntToPtr(
+      old_top, SharkType::jobject_type(), "heap_object");
+
+    Value *check = builder()->CreateCmpxchgPtr(new_top, top_addr, old_top);
+    builder()->CreateCondBr(
+      builder()->CreateICmpEQ(old_top, check),
+      initialize, retry);
+
+    // Initialize the object
+    builder()->SetInsertPoint(initialize);
+    if (tlab_object) {
+      PHINode *phi = builder()->CreatePHI(
+        SharkType::jobject_type(), "fast_object");
+      phi->addIncoming(tlab_object, got_tlab);
+      phi->addIncoming(heap_object, got_heap);
+      fast_object = phi;
+    }
+    else {
+      fast_object = heap_object;
+    }
+
+    builder()->CreateMemset(
+      builder()->CreateBitCast(
+        fast_object, PointerType::getUnqual(SharkType::jbyte_type())),
+      LLVMValue::jbyte_constant(0),
+      LLVMValue::jint_constant(size_in_bytes),
+      LLVMValue::jint_constant(HeapWordSize));
+
+    Value *mark_addr = builder()->CreateAddressOfStructEntry(
+      fast_object, in_ByteSize(oopDesc::mark_offset_in_bytes()),
+      PointerType::getUnqual(SharkType::intptr_type()),
+      "mark_addr");
+
+    Value *klass_addr = builder()->CreateAddressOfStructEntry(
+      fast_object, in_ByteSize(oopDesc::klass_offset_in_bytes()),
+      PointerType::getUnqual(SharkType::jobject_type()),
+      "klass_addr");
+
+    // Set the mark
+    intptr_t mark;
+    if (UseBiasedLocking) {
+      Unimplemented();
+    }
+    else {
+      mark = (intptr_t) markOopDesc::prototype();
+    }
+    builder()->CreateStore(LLVMValue::intptr_constant(mark), mark_addr);
+
+    // Set the class
+    Value *rtklass = constants.object_at(iter()->get_klass_index());
+    builder()->CreateStore(rtklass, klass_addr);
+    got_fast = builder()->GetInsertBlock();
+
+    builder()->CreateBr(push_object);
+    builder()->SetInsertPoint(slow_alloc_and_init);
+    fast_state = current_state()->copy();
+  }
+
+  // The slow path
+  call_vm(
+    SharkRuntime::new_instance(),
+    LLVMValue::jint_constant(iter()->get_klass_index()));
+  slow_object = function()->CreateGetVMResult();
+  got_slow = builder()->GetInsertBlock();
+
+  // Push the object
+  if (push_object) {
+    builder()->CreateBr(push_object);
+    builder()->SetInsertPoint(push_object);
+  }
+  if (fast_object) {
+    PHINode *phi = builder()->CreatePHI(SharkType::jobject_type(), "object");
+    phi->addIncoming(fast_object, got_fast);
+    phi->addIncoming(slow_object, got_slow);
+    object = phi;
+    current_state()->merge(fast_state, got_fast, got_slow);
+  }
+  else {
+    object = slow_object;
+  }
+
+  SharkValue *result = SharkValue::create_jobject(object);
+  result->set_zero_checked(true);
+  push(result);
+}
+
+void SharkTopLevelBlock::do_newarray()
+{
+  BasicType type = (BasicType) iter()->get_index();
+
+  call_vm(
+    SharkRuntime::newarray(),
+    LLVMValue::jint_constant(type),
+    pop()->jint_value());
+
+  SharkValue *result = SharkValue::create_generic(
+    ciArrayKlass::make(ciType::make(type)),
+    function()->CreateGetVMResult());
+  result->set_zero_checked(true);
+  push(result);
+}
+
+void SharkTopLevelBlock::do_anewarray()
+{
+  bool will_link;
+  ciKlass *klass = iter()->get_klass(will_link);
+  assert(will_link, "typeflow responsibility");
+
+  ciObjArrayKlass *array_klass = ciObjArrayKlass::make(klass);
+  if (!array_klass->is_loaded()) {
+    Unimplemented();
+  }
+
+  call_vm(
+    SharkRuntime::anewarray(),
+    LLVMValue::jint_constant(iter()->get_klass_index()),
+    pop()->jint_value());
+
+  SharkValue *result = SharkValue::create_generic(
+    array_klass, function()->CreateGetVMResult());
+  result->set_zero_checked(true);
+  push(result);
+}
+
+void SharkTopLevelBlock::do_multianewarray()
+{
+  bool will_link;
+  ciArrayKlass *array_klass = iter()->get_klass(will_link)->as_array_klass();
+  assert(will_link, "typeflow responsibility");
+
+  // The dimensions are stack values, so we use their slots for the
+  // dimensions array.  Note that we are storing them in the reverse
+  // of normal stack order.
+  int ndims = iter()->get_dimensions();
+
+  Value *dimensions = function()->CreateAddressOfFrameEntry(
+    function()->stack_slots_offset() + max_stack() - xstack_depth(),
+    ArrayType::get(SharkType::jint_type(), ndims),
+    "dimensions");
+
+  for (int i = 0; i < ndims; i++) {
+    builder()->CreateStore(
+      xstack(ndims - 1 - i)->jint_value(),
+      builder()->CreateStructGEP(dimensions, i));
+  }
+
+  call_vm(
+    SharkRuntime::multianewarray(),
+    LLVMValue::jint_constant(iter()->get_klass_index()),
+    LLVMValue::jint_constant(ndims),
+    builder()->CreateStructGEP(dimensions, 0));
+
+  // Now we can pop the dimensions off the stack
+  for (int i = 0; i < ndims; i++)
+    pop();
+
+  SharkValue *result = SharkValue::create_generic(
+    array_klass, function()->CreateGetVMResult());
+  result->set_zero_checked(true);
+  push(result);
+}
+
+void SharkTopLevelBlock::do_monitorenter()
+{
+  SharkValue *lockee = pop();
+  check_null(lockee);
+  Value *object = lockee->jobject_value();
+
+  // Find a free monitor, or one already allocated for this object
+  BasicBlock *loop_top    = function()->CreateBlock("loop_top");
+  BasicBlock *loop_iter   = function()->CreateBlock("loop_iter");
+  BasicBlock *loop_check  = function()->CreateBlock("loop_check");
+  BasicBlock *no_monitor  = function()->CreateBlock("no_monitor");
+  BasicBlock *got_monitor = function()->CreateBlock("got_monitor");
+
+  BasicBlock *entry_block = builder()->GetInsertBlock();
+  builder()->CreateBr(loop_check);
+
+  builder()->SetInsertPoint(loop_check);
+  PHINode *index = builder()->CreatePHI(SharkType::jint_type(), "index");
+  index->addIncoming(
+    LLVMValue::jint_constant(function()->monitor_count() - 1), entry_block);
+  builder()->CreateCondBr(
+    builder()->CreateICmpUGE(index, LLVMValue::jint_constant(0)),
+    loop_top, no_monitor);
+
+  builder()->SetInsertPoint(loop_top);
+  SharkMonitor* monitor = function()->monitor(index);
+  Value *smo = monitor->object();
+  builder()->CreateCondBr(
+    builder()->CreateOr(
+      builder()->CreateICmpEQ(smo, LLVMValue::null()),
+      builder()->CreateICmpEQ(smo, object)),
+    got_monitor, loop_iter);
+
+  builder()->SetInsertPoint(loop_iter);
+  index->addIncoming(
+    builder()->CreateSub(index, LLVMValue::jint_constant(1)), loop_iter);
+  builder()->CreateBr(loop_check);
+
+  builder()->SetInsertPoint(no_monitor);
+  builder()->CreateShouldNotReachHere(__FILE__, __LINE__);
+  builder()->CreateUnreachable();
+
+  // Acquire the lock
+  builder()->SetInsertPoint(got_monitor);
+  monitor->acquire(this, object);
+  check_pending_exception();
+}
+
+void SharkTopLevelBlock::do_monitorexit()
+{
+  SharkValue *lockee = pop();
+  // The monitorexit can't throw an NPE because the verifier checks
+  // that the monitor operations are block structured before we
+  // compile.
+  // check_null(lockee);
+  Value *object = lockee->jobject_value();
+
+  // Find the monitor associated with this object
+  BasicBlock *loop_top    = function()->CreateBlock("loop_top");
+  BasicBlock *loop_iter   = function()->CreateBlock("loop_iter");
+  BasicBlock *loop_check  = function()->CreateBlock("loop_check");
+  BasicBlock *no_monitor  = function()->CreateBlock("no_monitor");
+  BasicBlock *got_monitor = function()->CreateBlock("got_monitor");
+
+  BasicBlock *entry_block = builder()->GetInsertBlock();
+  builder()->CreateBr(loop_check);
+
+  builder()->SetInsertPoint(loop_check);
+  PHINode *index = builder()->CreatePHI(SharkType::jint_type(), "index");
+  index->addIncoming(
+    LLVMValue::jint_constant(function()->monitor_count() - 1), entry_block);
+  builder()->CreateCondBr(
+    builder()->CreateICmpUGE(index, LLVMValue::jint_constant(0)),
+    loop_top, no_monitor);
+
+  builder()->SetInsertPoint(loop_top);
+  SharkMonitor* monitor = function()->monitor(index);
+  Value *smo = monitor->object();
+  builder()->CreateCondBr(
+    builder()->CreateICmpEQ(smo, object),
+    got_monitor, loop_iter);
+
+  builder()->SetInsertPoint(loop_iter);
+  index->addIncoming(
+    builder()->CreateSub(index, LLVMValue::jint_constant(1)), loop_iter);
+  builder()->CreateBr(loop_check);
+
+  builder()->SetInsertPoint(no_monitor);
+  builder()->CreateShouldNotReachHere(__FILE__, __LINE__);
+  builder()->CreateUnreachable();
+
+  // Release the lock
+  builder()->SetInsertPoint(got_monitor);
+  monitor->release(this);
+  // The monitorexit can't throw an NPE because the verifier checks
+  // that the monitor operations are block structured before we
+  // compile.
+  // check_pending_exception();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp	Wed Mar 04 10:41:13 2009 -0500
@@ -0,0 +1,344 @@
+/*
+ * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2008, 2009 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+class SharkTopLevelBlock : public SharkBlock {
+ public:
+  SharkTopLevelBlock(SharkFunction* function, ciTypeFlow::Block* ciblock)
+    : SharkBlock(function->builder(), function->target(), function->iter()),
+      _function(function),
+      _ciblock(ciblock),
+      _entered(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;
+  }
+
+ public:
+  llvm::Value* thread() const
+  {
+    return function()->thread();
+  }
+
+  // Typeflow properties
+ public:
+  int index() const
+  {
+    return ciblock()->pre_order();
+  }
+  bool has_trap() const
+  {
+    return ciblock()->has_trap();
+  }
+  int trap_index() const
+  {
+    return ciblock()->trap_index();
+  }
+  bool is_private_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_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();
+  }
+  SharkTopLevelBlock* successor(int index) const
+  {
+    return function()->block(ciblock()->successors()->at(index)->pre_order());
+  }
+  SharkTopLevelBlock* bci_successor(int bci) const;
+
+  // 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();
+  }
+
+  // Code generation
+ public:
+  void emit_IR();
+
+  // Helpers
+ private:
+  void do_zero_check(SharkValue* value);
+  llvm::Value* lookup_for_ldc();
+  llvm::Value* lookup_for_field_access();
+
+  // VM calls
+ private:
+  llvm::CallInst* call_vm_nocheck(llvm::Constant* callee,
+                                  llvm::Value**   args_start,
+                                  llvm::Value**   args_end)
+  {
+    current_state()->decache_for_VM_call();
+    function()->set_last_Java_frame();
+    llvm::CallInst *res = builder()->CreateCall(callee, args_start, args_end);
+    function()->reset_last_Java_frame();
+    current_state()->cache_after_VM_call();
+    return res;
+  }
+
+  llvm::CallInst* call_vm(llvm::Constant* callee,
+                          llvm::Value**   args_start,
+                          llvm::Value**   args_end)
+  {
+    llvm::CallInst* res = call_vm_nocheck(callee, args_start, args_end);
+    check_pending_exception();
+    return res;
+  }
+
+ public:
+  llvm::CallInst* call_vm(llvm::Constant* callee)
+  {
+    llvm::Value *args[] = {thread()};
+    return call_vm(callee, args, args + 1);
+  }
+  llvm::CallInst* call_vm(llvm::Constant* callee,
+                          llvm::Value*    arg1)
+  {
+    llvm::Value *args[] = {thread(), arg1};
+    return call_vm(callee, args, args + 2);
+  }
+  llvm::CallInst* call_vm(llvm::Constant* callee,
+                          llvm::Value*    arg1,
+                          llvm::Value*    arg2)
+  {
+    llvm::Value *args[] = {thread(), arg1, arg2};
+    return call_vm(callee, args, args + 3);
+  }
+  llvm::CallInst* call_vm(llvm::Constant* callee,
+                          llvm::Value*    arg1,
+                          llvm::Value*    arg2,
+                          llvm::Value*    arg3)
+  {
+    llvm::Value *args[] = {thread(), arg1, arg2, arg3};
+    return call_vm(callee, args, args + 4);
+  }
+
+  llvm::CallInst* call_vm_nocheck(llvm::Constant* callee)
+  {
+    llvm::Value *args[] = {thread()};
+    return call_vm_nocheck(callee, args, args + 1);
+  }
+  llvm::CallInst* call_vm_nocheck(llvm::Constant* callee,
+                                  llvm::Value*    arg1)
+  {
+    llvm::Value *args[] = {thread(), arg1};
+    return call_vm_nocheck(callee, args, args + 2);
+  }
+  llvm::CallInst* call_vm_nocheck(llvm::Constant* callee,
+                                  llvm::Value*    arg1,
+                                  llvm::Value*    arg2)
+  {
+    llvm::Value *args[] = {thread(), arg1, arg2};
+    return call_vm_nocheck(callee, args, args + 3);
+  }
+  llvm::CallInst* call_vm_nocheck(llvm::Constant* callee,
+                                  llvm::Value*    arg1,
+                                  llvm::Value*    arg2,
+                                  llvm::Value*    arg3)
+  {
+    llvm::Value *args[] = {thread(), arg1, arg2, arg3};
+    return call_vm_nocheck(callee, args, args + 4);
+  }
+
+  // Whole-method synchronization
+ public:
+  void acquire_method_lock();  
+  void release_method_lock();  
+
+  // Error checking
+ private:
+  void check_bounds(SharkValue* array, SharkValue* index);
+  void check_pending_exception(bool attempt_catch = true);
+  void handle_exception(llvm::Value* exception, bool attempt_catch = true);
+
+  // Safepoints
+ private:
+  void add_safepoint();
+
+  // Returns
+ private:
+  void call_register_finalizer(llvm::Value* receiver);
+  void handle_return(BasicType type, llvm::Value* exception);
+  void release_locked_monitors();
+
+  // 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(llvm::ICmpInst::Predicate p, SharkValue* b, SharkValue* a);
+
+  // tableswitch and lookupswitch
+ private:
+  void do_switch();
+
+  // invoke*
+ private:
+  enum CallType {
+    CALL_DIRECT,
+    CALL_VIRTUAL,
+    CALL_INTERFACE
+  };
+  CallType get_call_type(ciMethod* method);
+  llvm::Value* get_callee(CallType    call_type,
+                          ciMethod*   method,
+                          SharkValue* receiver);
+
+  llvm::Value* get_direct_callee(ciMethod* method);
+  llvm::Value* get_virtual_callee(SharkValue* receiver, ciMethod* method);
+
+  llvm::Value* get_virtual_callee(llvm::Value* cache, SharkValue* receiver);
+  llvm::Value* get_interface_callee(SharkValue* receiver);
+
+  void do_call();
+
+  // checkcast and instanceof
+ private:
+  void do_instance_check();
+
+  // 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();
+};
--- a/ports/hotspot/src/share/vm/shark/shark_globals.hpp	Wed Mar 04 11:01:54 2009 +0100
+++ b/ports/hotspot/src/share/vm/shark/shark_globals.hpp	Wed Mar 04 10:41:13 2009 -0500
@@ -32,6 +32,10 @@
   product(intx, MaxNodeLimit, 65000,                                          \
           "Maximum number of nodes")                                          \
                                                                               \
+  /* inlining */                                                              \
+  product(intx, SharkMaxInlineSize, 32,                                       \
+          "Maximum bytecode size of methods to inline when using Shark")      \
+                                                                              \
   /* compiler debugging */                                                    \
   develop(uintx, SharkStartAt, 0,                                             \
           "First method to consider when using Shark")                        \
@@ -48,8 +52,8 @@
   develop(ccstr, SharkPrintBitcodeOf, NULL,                                   \
           "Print the LLVM bitcode of the specified method")                   \
                                                                               \
-  develop(ccstr, SharkPrintAsmOf, NULL,                                   \
-          "Print the asm of the specified method")                   \
+  develop(ccstr, SharkPrintAsmOf, NULL,                                       \
+          "Print the asm of the specified method")                            \
                                                                               \
   develop(bool, SharkTraceBytecodes, false,                                   \
           "Trace bytecode compilation")                                       \