changeset 1:cef23de210a4

Bunch of fixes to get Zero to build.
author Roman Kennke <rkennke@redhat.com>
date Mon, 30 Jul 2012 13:57:49 +0200
parents a9efa2633708
children 264be8bc2c98
files hotspot.patch psgc-bind-procs.patch series zero-makefile.patch zero-new-math.patch zero-segfault.patch
diffstat 6 files changed, 940 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot.patch	Mon Jul 30 13:57:49 2012 +0200
@@ -0,0 +1,742 @@
+--- old/make/linux/platform_zero.in	2012-07-26 11:59:59.762620781 -0400
++++ new/make/linux/platform_zero.in	2012-07-26 11:59:59.527600874 -0400
+@@ -14,4 +14,4 @@
+ 
+ gnu_dis_arch = zero
+ 
+-sysdefs = -DLINUX -D_GNU_SOURCE -DCC_INTERP -DZERO -D@ZERO_ARCHDEF@ -DZERO_LIBARCH=\"@ZERO_LIBARCH@\"
++sysdefs = -DLINUX -D_GNU_SOURCE -DCC_INTERP -DZERO -DTARGET_ARCH_NYI_6939861=1 -D@ZERO_ARCHDEF@ -DZERO_LIBARCH=\"@ZERO_LIBARCH@\"
+--- old/src/cpu/zero/vm/assembler_zero.cpp	2012-07-26 12:00:00.277664407 -0400
++++ new/src/cpu/zero/vm/assembler_zero.cpp	2012-07-26 12:00:00.120651108 -0400
+@@ -91,3 +91,11 @@
+ address ShouldNotCallThisEntry() {
+   return (address) should_not_call;
+ }
++
++static void zero_null_fn() {
++  return;
++}
++
++address ZeroNullStubEntry(address fn) {
++  return (address) fn;
++}
+--- old/src/cpu/zero/vm/assembler_zero.hpp	2012-07-26 12:00:00.664697192 -0400
++++ new/src/cpu/zero/vm/assembler_zero.hpp	2012-07-26 12:00:00.536686349 -0400
+@@ -65,5 +65,6 @@
+ 
+ address ShouldNotCallThisStub();
+ address ShouldNotCallThisEntry();
++address ZeroNullStubEntry(address fn);
+ 
+ #endif // CPU_ZERO_VM_ASSEMBLER_ZERO_HPP
+--- old/src/cpu/zero/vm/copy_zero.hpp	2012-07-26 12:00:01.529770463 -0400
++++ new/src/cpu/zero/vm/copy_zero.hpp	2012-07-26 12:00:01.017727097 -0400
+@@ -169,7 +169,7 @@
+ }
+ 
+ static void pd_fill_to_bytes(void* to, size_t count, jubyte value) {
+-  memset(to, value, count);
++  if ( count > 0 ) memset(to, value, count);
+ }
+ 
+ static void pd_zero_to_words(HeapWord* tohw, size_t count) {
+@@ -177,7 +177,7 @@
+ }
+ 
+ static void pd_zero_to_bytes(void* to, size_t count) {
+-  memset(to, 0, count);
++  if ( count > 0 ) memset(to, 0, count);
+ }
+ 
+ #endif // CPU_ZERO_VM_COPY_ZERO_HPP
+--- old/src/cpu/zero/vm/cppInterpreter_zero.cpp	2012-07-26 12:00:01.934804777 -0400
++++ new/src/cpu/zero/vm/cppInterpreter_zero.cpp	2012-07-26 12:00:01.806793934 -0400
+@@ -36,6 +36,7 @@
+ #include "oops/oop.inline.hpp"
+ #include "prims/jvmtiExport.hpp"
+ #include "prims/jvmtiThreadState.hpp"
++#include "prims/methodHandles.hpp"
+ #include "runtime/arguments.hpp"
+ #include "runtime/deoptimization.hpp"
+ #include "runtime/frame.inline.hpp"
+@@ -65,6 +66,14 @@
+   CALL_VM_NOCHECK_NOFIX(func)                   \
+   fixup_after_potential_safepoint()
+ 
++
++#ifdef DEBUG
++#define CPPINT_DEBUG( Z_code_ ) Z_code_
++CPPINT_DEBUG ( static const char *FFng_Zero_Flag = "CPPINT_DEBUG_ON\n"; ) 
++#else
++#define CPPINT_DEBUG( Z_code_ )
++#endif
++
+ int CppInterpreter::normal_entry(methodOop method, intptr_t UNUSED, TRAPS) {
+   JavaThread *thread = (JavaThread *) THREAD;
+ 
+@@ -699,6 +708,9 @@
+     method_handle = adapter;
+   }
+ 
++  CPPINT_DEBUG( tty->print_cr( "Process method_handle sp: 0x%x unwind_sp: 0x%x result_slots: %d.", \
++			       stack->sp(), unwind_sp, result_slots ); )
++
+   // Start processing
+   process_method_handle(method_handle, THREAD);
+   if (HAS_PENDING_EXCEPTION)
+@@ -718,6 +730,8 @@
+   }
+ 
+   // Check
++  CPPINT_DEBUG( tty->print_cr( "Exiting method_handle_entry,  sp: 0x%x unwind_sp: 0x%x result_slots: %d.", \
++			       stack->sp(), unwind_sp, result_slots ); )
+   assert(stack->sp() == unwind_sp - result_slots, "should be");
+ 
+   // No deoptimized frames on the stack
+@@ -725,6 +739,7 @@
+ }
+ 
+ void CppInterpreter::process_method_handle(oop method_handle, TRAPS) {
++
+   JavaThread *thread = (JavaThread *) THREAD;
+   ZeroStack *stack = thread->zero_stack();
+   intptr_t *vmslots = stack->sp();
+@@ -739,6 +754,7 @@
+     (MethodHandles::EntryKind) (((intptr_t) entry) & 0xffffffff);
+ 
+   methodOop method = NULL;
++  CPPINT_DEBUG( tty->print_cr( "\nEntering %s 0x%x.",MethodHandles::entry_name(entry_kind), (char *)vmslots ); )
+   switch (entry_kind) {
+   case MethodHandles::_invokestatic_mh:
+     direct_to_method = true;
+@@ -811,11 +827,15 @@
+   case MethodHandles::_bound_int_mh:
+   case MethodHandles::_bound_long_mh:
+     {
+-      BasicType arg_type  = T_ILLEGAL;
+-      int       arg_mask  = -1;
+-      int       arg_slots = -1;
+-      MethodHandles::get_ek_bound_mh_info(
+-        entry_kind, arg_type, arg_mask, arg_slots);
++      //     BasicType arg_type  = T_ILLEGAL;
++      //     int       arg_mask  = -1;
++      //     int       arg_slots = -1;
++      //     MethodHandles::get_ek_bound_mh_info(
++      //      entry_kind, arg_type, arg_mask, arg_slots);
++      BasicType arg_type = MethodHandles::ek_bound_mh_arg_type(entry_kind);
++      int arg_mask = 0;
++      int arg_slots = type2size[arg_type];;
++
+       int arg_slot =
+         java_lang_invoke_BoundMethodHandle::vmargslot(method_handle);
+ 
+@@ -961,10 +981,13 @@
+         java_lang_invoke_AdapterMethodHandle::conversion(method_handle);
+       int arg2 = MethodHandles::adapter_conversion_vminfo(conv);
+ 
+-      int swap_bytes = 0, rotate = 0;
+-      MethodHandles::get_ek_adapter_opt_swap_rot_info(
+-        entry_kind, swap_bytes, rotate);
+-      int swap_slots = swap_bytes >> LogBytesPerWord;
++      // int swap_bytes = 0, rotate = 0;
++      //     MethodHandles::get_ek_adapter_opt_swap_rot_info(
++      //        entry_kind, swap_bytes, rotate);
++      int swap_slots = MethodHandles::ek_adapter_opt_swap_slots(entry_kind);
++      int rotate = MethodHandles::ek_adapter_opt_swap_mode(entry_kind);
++      int swap_bytes = swap_slots * Interpreter::stackElementSize;
++      swap_slots = swap_bytes >> LogBytesPerWord;
+ 
+       intptr_t tmp;
+       switch (rotate) {
+@@ -1080,12 +1103,309 @@
+     }
+     break;
+ 
+-  default:
+-    tty->print_cr("unhandled entry_kind %s",
++  case MethodHandles::_adapter_opt_spread_0:
++  case MethodHandles::_adapter_opt_spread_1_ref:
++  case MethodHandles::_adapter_opt_spread_2_ref:
++  case MethodHandles::_adapter_opt_spread_3_ref:
++  case MethodHandles::_adapter_opt_spread_4_ref:
++  case MethodHandles::_adapter_opt_spread_5_ref:
++  case MethodHandles::_adapter_opt_spread_ref:
++  case MethodHandles::_adapter_opt_spread_byte:
++  case MethodHandles::_adapter_opt_spread_char:
++  case MethodHandles::_adapter_opt_spread_short:
++  case MethodHandles::_adapter_opt_spread_int:
++  case MethodHandles::_adapter_opt_spread_long:
++  case MethodHandles::_adapter_opt_spread_float:
++  case MethodHandles::_adapter_opt_spread_double:
++    {
++
++      // spread an array out into a group of arguments
++
++      int arg_slot =
++        java_lang_invoke_AdapterMethodHandle::vmargslot(method_handle);
++      // Fetch the argument, which we will cast to the required array type.
++      oop arg = VMSLOTS_OBJECT(arg_slot);
++
++      BasicType elem_type      =
++        MethodHandles::ek_adapter_opt_spread_type(entry_kind);
++      int       elem_slots     = 
++        type2size[elem_type];  // 1 or 2
++      int       array_slots    = 
++        1;  // array is always a T_OBJECT
++      int       length_offset  = 
++        arrayOopDesc::length_offset_in_bytes();
++      int       elem0_offset   = 
++        arrayOopDesc::base_offset_in_bytes(elem_type);
++      int       length_constant = 
++        MethodHandles::ek_adapter_opt_spread_count(entry_kind);
++      int       array_length = 0;
++      void      *array_elem0 = NULL;       
++
++      CPPINT_DEBUG( tty->print_cr( \
++        "ENTERING _adapter_opt_spread: %s %d %d 0x%x 0x%x", \
++        type2name(elem_type), arg_slot, length_constant, (char *)arg, stack->sp() ); )
++
++      // If the spread count is -1, the length is "variable" ie controlled
++      // by the array length.
++      // See ek_adapter_opt_spread_count in methodHandles.hpp
++      // If array lenth is 0 or spread count is 0 , we will remove the argslot.
++
++      bool length_can_be_zero = (length_constant == 0);
++      if (length_constant < 0) {
++        // some adapters with variable length must handle the zero case
++        if (!OptimizeMethodHandles ||
++            elem_type != T_OBJECT)
++          length_can_be_zero = true;
++      }
++
++      if (arg == NULL) {
++        CPPINT_DEBUG( tty->print_cr( \
++          "arg NULL implies Array_length == 0, remove slot." ); )
++        // remove arg slot
++        remove_vmslots(arg_slot, 1, THREAD); // doesn't trap
++        vmslots = stack->sp(); // unused, but let the compiler figure that out
++        CPPINT_DEBUG( tty->print_cr( \
++          " >> Would LEAVE _adapter_opt_spread with NPE." ); )
++#ifdef _NOT_DEF_
++	// queue a nullpointer exception for the caller
++        stack->set_sp(calculate_unwind_sp(stack, method_handle));
++        CALL_VM_NOCHECK_NOFIX(
++          throw_exception(
++            thread,
++            vmSymbols::java_lang_NullPointerException()));
++        // NB all oops trashed!
++        assert(HAS_PENDING_EXCEPTION, "should do");
++        return;
++#endif
++      } else {    //  (arg != NULL) 
++        klassOop objKlassOop = arg->klass();
++        klassOop klassOf = java_lang_Class::as_klassOop(
++          java_lang_invoke_AdapterMethodHandle::argument(method_handle));
++
++        if (objKlassOop != klassOf &&
++            !objKlassOop->klass_part()->is_subtype_of(klassOf)) {
++          CPPINT_DEBUG( tty->print_cr( \
++            "CLASS CAST ERROR #1 in _adapter_opt_spread." ); )
++          ResourceMark rm(THREAD);
++          const char* objName = Klass::cast(objKlassOop)->external_name();
++          const char* klassName = Klass::cast(klassOf)->external_name();
++          char* message = SharedRuntime::generate_class_cast_message(
++            objName, klassName);
++
++          stack->set_sp(calculate_unwind_sp(stack, method_handle));
++          CALL_VM_NOCHECK_NOFIX(
++            throw_exception(
++              thread,
++              vmSymbols::java_lang_ClassCastException(), message));
++          // NB all oops trashed!
++          assert(HAS_PENDING_EXCEPTION, "should do");
++          return;
++        }
++
++        // Check the array type.
++
++        klassOop array_klass_oop = NULL;
++        BasicType array_type = java_lang_Class::as_BasicType(
++          java_lang_invoke_AdapterMethodHandle::argument(method_handle),
++            &array_klass_oop);
++        arrayKlassHandle array_klass(THREAD, array_klass_oop);
++
++        assert(array_type == T_OBJECT, "");
++        assert(Klass::cast(array_klass_oop)->oop_is_array(), "");
++        if (!(array_type == T_OBJECT) || 
++            !(Klass::cast(array_klass_oop)->oop_is_array())) {
++          CPPINT_DEBUG( tty->print_cr( \
++            "CLASS CAST ERROR #2 not an array in _adapter_opt_spread." ); )
++          ResourceMark rm(THREAD);
++          const char* objName = Klass::cast(objKlassOop)->external_name();
++          const char* klassName = Klass::cast(klassOf)->external_name();
++          char* message = SharedRuntime::generate_class_cast_message(
++            objName, klassName);
++          stack->set_sp(calculate_unwind_sp(stack, method_handle));
++          CALL_VM_NOCHECK_NOFIX(
++            throw_exception(
++              thread,
++              vmSymbols::java_lang_ClassCastException(), message));
++          // NB all oops trashed!
++          assert(HAS_PENDING_EXCEPTION, "should do");
++          return;
++        }
++
++        klassOop element_klass_oop = NULL;
++        BasicType element_type = 
++          java_lang_Class::as_BasicType(array_klass->component_mirror(),
++            &element_klass_oop);
++        KlassHandle element_klass(THREAD, element_klass_oop);
++	if ((elem_type != T_OBJECT) && (elem_type != element_type)) {
++          CPPINT_DEBUG( tty->print_cr( \
++            "CLASS CAST ERROR #3 invalid type %s != %s in _adapter_opt_spread.", \
++            type2name(elem_type), type2name(element_type)  ); )
++          ResourceMark rm(THREAD);
++          const char* objName = Klass::cast(objKlassOop)->external_name();
++          const char* klassName = Klass::cast(klassOf)->external_name();
++          char* message = SharedRuntime::generate_class_cast_message(
++            objName, klassName);
++          stack->set_sp(calculate_unwind_sp(stack, method_handle));
++          CALL_VM_NOCHECK_NOFIX(
++            throw_exception(
++              thread,
++              vmSymbols::java_lang_ClassCastException(), message));
++          // NB all oops trashed!
++          assert(HAS_PENDING_EXCEPTION, "should do");
++          return;
++        }
++
++        array_length = arrayOop(arg)->length();
++
++        // Check the required length.
++        if (length_constant > 0) { // must match ?
++          if ( array_length != length_constant ) {
++            CPPINT_DEBUG( tty->print_cr( \
++              "ARRY INDEX ERROR #4 invalid array length in _adapter_opt_spread." ); )
++            //fixme  ArrayIndexOutOfBoundsException ?
++            ResourceMark rm(THREAD);
++            const char* objName = Klass::cast(objKlassOop)->external_name();
++            const char* klassName = Klass::cast(klassOf)->external_name();
++            char* message = SharedRuntime::generate_class_cast_message(
++              objName, klassName);
++
++            stack->set_sp(calculate_unwind_sp(stack, method_handle));
++            CALL_VM_NOCHECK_NOFIX(
++              throw_exception(
++                thread,
++                vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message));
++            // NB all oops trashed!
++            assert(HAS_PENDING_EXCEPTION, "should do");
++            return;
++          }
++        // use array_length ?
++        } else { // length_constant == [ -1 or 0 ] 
++          if ( (array_length > 0) || length_can_be_zero ) {
++            // use array_length.
++          } else { // array_length 0 and not length_can_be_zero
++            CPPINT_DEBUG( tty->print_cr( \
++              "ARRY INDEX ERROR #5 arry length 0 in _adapter_opt_spread." ); )
++            //fixme   ArrayIndexOutOfBoundsException ?
++            ResourceMark rm(THREAD);
++            const char* objName = Klass::cast(objKlassOop)->external_name();
++            const char* klassName = Klass::cast(klassOf)->external_name();
++            char* message = SharedRuntime::generate_class_cast_message(
++              objName, klassName);
++
++            stack->set_sp(calculate_unwind_sp(stack, method_handle));
++            CALL_VM_NOCHECK_NOFIX(
++              throw_exception(
++                thread,
++                vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message));
++            // NB all oops trashed!
++            assert(HAS_PENDING_EXCEPTION, "should do");
++            return;
++          }
++        }
++
++        // Array length checked out.  Now insert any required arg slots.
++        // array_length - 1 more slots if array_length > 0
++        // otherwise  if array_length == 0 remove arg_slot.
++
++        if ( array_length > 0 ) {
++          int slots = (array_length * elem_slots) - 1;
++          CPPINT_DEBUG( tty->print_cr( \
++            "array_length %d %d slots needed in _adapter_opt_spread.",\
++              array_length, slots); )
++          debug_only(if (elem_slots == 2) \
++            assert ((slots % 2 == 1)," bad slots calc"));
++          if ( slots > 0 ) {
++            intptr_t *unwind_sp = 
++            calculate_unwind_sp(stack, method_handle);
++            insert_vmslots(arg_slot, slots, THREAD);
++            if (HAS_PENDING_EXCEPTION) {
++              // all oops trashed
++              stack->set_sp(unwind_sp);
++              return;
++            }
++          }
++          vmslots = stack->sp();
++          arg_slot += slots;
++
++          array_elem0 = arrayOop(arg)->base(elem_type);
++
++          // Copy from the array to the new arg slots.
++          // [from native : Beware:  Arguments that are shallow 
++          // on the stack are deep in the array,
++          // and vice versa.  So a downward-growing stack (the usual) 
++          // has to be copied elementwise in reverse order 
++          // from the source array.]
++
++          void * array_elem = array_elem0;
++          int top_slot = arg_slot;
++
++          debug_only(if (elem_slots == 2) \
++            assert ((((ulong)(char *)&vmslots[top_slot]) % \
++              (u_int)type2aelembytes(elem_type) == 0), \
++                " bad arg alignment"));
++
++          CPPINT_DEBUG( tty->print_cr( \
++            "BEGIN ARRY LOOP %d %d 0x%x 0x%x _adapter_opt_spread.",\
++              array_length, top_slot, &vmslots[top_slot], array_elem  ); )
++
++          for (int index = 0; index < array_length; index++) {
++            switch (elem_type) {
++            case T_BYTE:
++              SET_VMSLOTS_INT(*(jint*)array_elem, top_slot);
++              break;
++            case T_CHAR:
++              SET_VMSLOTS_INT(*(jint*)array_elem, top_slot);
++              break;
++            case T_SHORT:
++              SET_VMSLOTS_INT(*(jint*)array_elem, top_slot);
++              break;
++            case T_INT:
++              SET_VMSLOTS_INT(*(jint*)array_elem, top_slot);
++              break;
++            case T_FLOAT:
++              SET_VMSLOTS_FLOAT(*(jfloat*)array_elem,top_slot);
++              break;
++            case T_LONG:
++              SET_VMSLOTS_LONG(*(jlong*)array_elem, top_slot);
++              break;
++            case T_DOUBLE:
++              SET_VMSLOTS_DOUBLE(*(jdouble*)array_elem, top_slot);
++              break;
++            case T_OBJECT:
++              SET_VMSLOTS_OBJECT(*(oopDesc**)array_elem, top_slot);
++              break;
++            default:
++              tty->print_cr("unhandled type %s", type2name(elem_type));
++              ShouldNotReachHere();
++            }
++            array_elem = (void*)((char *)array_elem +
++              type2aelembytes(element_type));
++            top_slot -= elem_slots;
++          }
++          arg_slot++;
++        }
++      }
++      if ((array_length == 0) && (arg != NULL)) {
++        CPPINT_DEBUG( tty->print_cr( \
++          "Array_length == 0, will remove slot." ); )
++        // remove arg slot
++        remove_vmslots(arg_slot, 1, THREAD); // doesn't trap
++         // unused, but let the compiler figure that out
++        vmslots = stack->sp();
++        //
++      }
++      CPPINT_DEBUG( tty->print_cr( \
++        "LEAVING _adapter_opt_spread: %s 0x%x 0x%x \n", \
++          type2name(elem_type), (char *)arg, (char *)stack->sp() ); )
++    }
++        break;
++    default:
++      tty->print_cr("unhandled entry_kind %s",
+                   MethodHandles::entry_name(entry_kind));
+-    ShouldNotReachHere();
++      ShouldNotReachHere();
+   }
+ 
++
+   // Continue along the chain
+   if (direct_to_method) {
+     if (method == NULL) {
+@@ -1138,6 +1458,7 @@
+     tty->print_cr("dst_rtype = %s", type2name(dst_rtype));
+     ShouldNotReachHere();
+   }
++  CPPINT_DEBUG( tty->print_cr( "LEAVING %s\n",MethodHandles::entry_name(entry_kind) ); )
+ }
+ 
+ // The new slots will be inserted before slot insert_before.
+--- old/src/cpu/zero/vm/frame_zero.inline.hpp	2012-07-26 12:00:02.430846787 -0400
++++ new/src/cpu/zero/vm/frame_zero.inline.hpp	2012-07-26 12:00:02.295835354 -0400
+@@ -36,6 +36,8 @@
+   _deopt_state = unknown;
+ }
+ 
++inline address  frame::sender_pc()           const { ShouldNotCallThis();  }
++
+ inline frame::frame(ZeroFrame* zf, intptr_t* sp) {
+   _zeroframe = zf;
+   _sp = sp;
+--- old/src/cpu/zero/vm/methodHandles_zero.cpp	2012-07-26 12:00:02.828880511 -0400
++++ new/src/cpu/zero/vm/methodHandles_zero.cpp	2012-07-26 12:00:02.695869244 -0400
+@@ -28,6 +28,8 @@
+ #include "memory/allocation.inline.hpp"
+ #include "prims/methodHandles.hpp"
+ 
++#define __ _masm->
++
+ int MethodHandles::adapter_conversion_ops_supported_mask() {
+   return ((1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY)
+          |(1<<java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW)
+@@ -38,12 +40,73 @@
+          |(1<<java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS)
+          |(1<<java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS)
+          |(1<<java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS)
+-         //|(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG!
++         |(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS)
+          );
+-  // FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS.
+ }
+ 
+ void MethodHandles::generate_method_handle_stub(MacroAssembler*          masm,
+                                                 MethodHandles::EntryKind ek) {
+   init_entry(ek, (MethodHandleEntry *) ek);
+ }
++void MethodHandles::RicochetFrame::generate_ricochet_blob(MacroAssembler* _masm,
++                                                          // output params:
++                                                          int* bounce_offset,
++                                                          int* exception_offset,
++                                                          int* frame_size_in_words) {
++  (*frame_size_in_words) = 0;
++  address start = __ pc();
++  (*bounce_offset) = __ pc() - start;
++  (*exception_offset) = __ pc() - start;
++}
++
++frame MethodHandles::ricochet_frame_sender(const frame& fr, RegisterMap *map) {
++  //RicochetFrame* f = RicochetFrame::from_frame(fr);
++  // Cf. is_interpreted_frame path of frame::sender
++  //  intptr_t* younger_sp = fr.sp();
++  //  intptr_t* sp         = fr.sender_sp();
++  //  return frame(sp, younger_sp, this_frame_adjusted_stack);
++  ShouldNotCallThis();  
++}
++
++void MethodHandles::ricochet_frame_oops_do(const frame& fr, OopClosure* blk, const RegisterMap* reg_map) {
++  //  ResourceMark rm;
++  //  RicochetFrame* f = RicochetFrame::from_frame(fr);
++
++  // pick up the argument type descriptor:
++  //  Thread* thread = Thread::current();
++  // process fixed part
++  //  blk->do_oop((oop*)f->saved_target_addr());
++  //  blk->do_oop((oop*)f->saved_args_layout_addr());
++
++  // process variable arguments:
++  //  if (cookie.is_null())  return;  // no arguments to describe
++
++  // the cookie is actually the invokeExact method for my target
++  // his argument signature is what I'm interested in
++  //  assert(cookie->is_method(), "");
++  //  methodHandle invoker(thread, methodOop(cookie()));
++  //  assert(invoker->name() == vmSymbols::invokeExact_name(), "must be this kind of method");
++  //  assert(!invoker->is_static(), "must have MH argument");
++  //  int slot_count = invoker->size_of_parameters();
++  //  assert(slot_count >= 1, "must include 'this'");
++  //  intptr_t* base = f->saved_args_base();
++  //  intptr_t* retval = NULL;
++  //  if (f->has_return_value_slot())
++  //    retval = f->return_value_slot_addr();
++  //  int slot_num = slot_count - 1;
++  //  intptr_t* loc = &base[slot_num];
++  //blk->do_oop((oop*) loc);   // original target, which is irrelevant
++  //  int arg_num = 0;
++  //  for (SignatureStream ss(invoker->signature()); !ss.is_done(); ss.next()) {
++  //    if (ss.at_return_type())  continue;
++  //    BasicType ptype = ss.type();
++  //    if (ptype == T_ARRAY)  ptype = T_OBJECT; // fold all refs to T_OBJECT
++  //    assert(ptype >= T_BOOLEAN && ptype <= T_OBJECT, "not array or void");
++  //    slot_num -= type2size[ptype];
++  //    loc = &base[slot_num];
++  //    bool is_oop = (ptype == T_OBJECT && loc != retval);
++  //    if (is_oop)  blk->do_oop((oop*)loc);
++  //    arg_num += 1;
++  //  }
++  //  assert(slot_num == 0, "must have processed all the arguments");
++}
+--- old/src/cpu/zero/vm/methodHandles_zero.hpp	2012-07-26 12:00:03.229914480 -0400
++++ new/src/cpu/zero/vm/methodHandles_zero.hpp	2012-07-26 12:00:03.114904738 -0400
+@@ -29,3 +29,26 @@
+   adapter_code_size = 0
+ };
+ 
++class RicochetFrame : public ResourceObj {
++  friend class MethodHandles;
++ private:
++  /*
++    RF field            x86                 SPARC
++    sender_pc           *(rsp+0)            I7-0x8
++    sender_link         rbp                 I6+BIAS
++    exact_sender_sp     rsi/r13             I5_savedSP
++    conversion          *(rcx+&amh_conv)    L5_conv
++    saved_args_base     rax                 L4_sab (cf. Gargs = G4)
++    saved_args_layout   #NULL               L3_sal
++    saved_target        *(rcx+&mh_vmtgt)    L2_stgt
++    continuation        #STUB_CON           L1_cont
++   */
++ public:
++
++static void generate_ricochet_blob(MacroAssembler* _masm,
++                                     // output params:
++                                     int* bounce_offset,
++                                     int* exception_offset,
++                                     int* frame_size_in_words);
++
++};
+--- old/src/cpu/zero/vm/sharedRuntime_zero.cpp	2012-07-26 12:00:03.623947857 -0400
++++ new/src/cpu/zero/vm/sharedRuntime_zero.cpp	2012-07-26 12:00:03.509938200 -0400
+@@ -35,6 +35,7 @@
+ #include "runtime/sharedRuntime.hpp"
+ #include "runtime/vframeArray.hpp"
+ #include "vmreg_zero.inline.hpp"
++
+ #ifdef COMPILER1
+ #include "c1/c1_Runtime1.hpp"
+ #endif
+@@ -47,6 +48,12 @@
+ #endif
+ 
+ 
++
++static address zero_null_code_stub() {
++  address start = ShouldNotCallThisStub();
++  return start;
++}
++
+ int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
+                                            VMRegPair *regs,
+                                            int total_args_passed,
+@@ -63,9 +70,9 @@
+                         AdapterFingerPrint *fingerprint) {
+   return AdapterHandlerLibrary::new_entry(
+     fingerprint,
+-    ShouldNotCallThisStub(),
+-    ShouldNotCallThisStub(),
+-    ShouldNotCallThisStub());
++    ZeroNullStubEntry( CAST_FROM_FN_PTR(address,zero_null_code_stub) ),
++    ZeroNullStubEntry( CAST_FROM_FN_PTR(address,zero_null_code_stub) ),
++    ZeroNullStubEntry( CAST_FROM_FN_PTR(address,zero_null_code_stub) ));
+ }
+ 
+ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
+@@ -96,19 +103,20 @@
+   ShouldNotCallThis();
+ }
+ 
++JRT_LEAF(void, zero_stub())
++  ShouldNotCallThis();
++JRT_END
++
+ static RuntimeStub* generate_empty_runtime_stub(const char* name) {
+-  CodeBuffer buffer(name, 0, 0);
+-  return RuntimeStub::new_runtime_stub(name, &buffer, 0, 0, NULL, false);
++  return CAST_FROM_FN_PTR(RuntimeStub*,zero_stub);
+ }
+ 
+ static SafepointBlob* generate_empty_safepoint_blob() {
+-  CodeBuffer buffer("handler_blob", 0, 0);
+-  return SafepointBlob::create(&buffer, NULL, 0);
++  return CAST_FROM_FN_PTR(SafepointBlob*,zero_stub);
+ }
+ 
+ static DeoptimizationBlob* generate_empty_deopt_blob() {
+-  CodeBuffer buffer("handler_blob", 0, 0);
+-  return DeoptimizationBlob::create(&buffer, NULL, 0, 0, 0, 0);
++  return CAST_FROM_FN_PTR(DeoptimizationBlob*,zero_stub);
+ }
+ 
+ 
+@@ -124,6 +132,7 @@
+   return generate_empty_runtime_stub("resolve_blob");
+ }
+ 
++
+ int SharedRuntime::c_calling_convention(const BasicType *sig_bt,
+                                          VMRegPair *regs,
+                                          int total_args_passed) {
+--- old/src/share/vm/runtime/sharedRuntime.cpp	2012-07-26 12:00:04.113989373 -0400
++++ new/src/share/vm/runtime/sharedRuntime.cpp	2012-07-26 12:00:03.921973101 -0400
+@@ -120,6 +120,7 @@
+ //----------------------------generate_ricochet_blob---------------------------
+ void SharedRuntime::generate_ricochet_blob() {
+   if (!EnableInvokeDynamic)  return;  // leave it as a null
++  ZERO_ONLY( return; )
+ 
+   // allocate space for the code
+   ResourceMark rm;
+--- old/src/share/vm/runtime/vmStructs.cpp	2012-07-26 12:00:04.610031384 -0400
++++ new/src/share/vm/runtime/vmStructs.cpp	2012-07-26 12:00:04.484020710 -0400
+@@ -836,10 +836,10 @@
+   /* CodeBlobs (NOTE: incomplete, but only a little) */                                                                              \
+   /***************************************************/                                                                              \
+                                                                                                                                      \
+-  X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _sender_pc,                                     address))                   \
+-  X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _exact_sender_sp,                              intptr_t*))                  \
+-  X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _sender_link,                                  intptr_t*))                  \
+-  X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _saved_args_base,                              intptr_t*))                  \
++  NOT_ZERO(X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _sender_pc,                                     address)))                   \
++  NOT_ZERO(X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _exact_sender_sp,                              intptr_t*)))                  \
++  NOT_ZERO(X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _sender_link,                                  intptr_t*)))                  \
++  NOT_ZERO(X86_ONLY(nonstatic_field(MethodHandles::RicochetFrame, _saved_args_base,                              intptr_t*)))                  \
+                                                                                                                                      \
+      static_field(SharedRuntime,               _ricochet_blob,                                RicochetBlob*)                         \
+                                                                                                                                      \
+@@ -2495,7 +2495,7 @@
+   /* frame              */                                                \
+   /**********************/                                                \
+                                                                           \
+-  X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset))      \
++  NOT_ZERO(X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset)))      \
+   declare_constant(frame::pc_return_offset)                               \
+                                                                           \
+   /*************/                                                         \
+--- old/src/share/vm/shark/sharkCompiler.cpp	2012-07-26 12:00:05.105073316 -0400
++++ new/src/share/vm/shark/sharkCompiler.cpp	2012-07-26 12:00:04.971061965 -0400
+@@ -319,7 +319,8 @@
+   // finish with the exception of the VM thread, so we can consider
+   // ourself the owner of the execution engine lock even though we
+   // can't actually acquire it at this time.
+-  assert(Thread::current()->is_VM_thread(), "must be called by VM thread");
++  assert(JavaThread::current()->thread_state() == _thread_in_vm, "must run in vm mode");
++//assert(Thread::current()->is_VM_thread(), "must be called by VM thread");
+   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+ 
+   SharkEntry *entry = (SharkEntry *) code;
+--- old/src/share/vm/utilities/macros.hpp	2012-07-26 12:00:05.529109235 -0400
++++ new/src/share/vm/utilities/macros.hpp	2012-07-26 12:00:05.388097290 -0400
+@@ -177,6 +177,22 @@
+ #define NOT_WIN64(code) code
+ #endif
+ 
++#if defined(ZERO)
++#define ZERO_ONLY(code) code
++#define NOT_ZERO(code)
++#else
++#define ZERO_ONLY(code) 
++#define NOT_ZERO(code) code
++#endif
++
++#if defined(SHARK)
++#define SHARK_ONLY(code) code
++#define NOT_SHARK(code)
++#else
++#define SHARK_ONLY(code) 
++#define NOT_SHARK(code) code
++#endif
++
+ #if defined(IA32) || defined(AMD64)
+ #define X86
+ #define X86_ONLY(code) code
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/psgc-bind-procs.patch	Mon Jul 30 13:57:49 2012 +0200
@@ -0,0 +1,117 @@
+# HG changeset patch
+# Parent 144e4e0a3b16431210ba8c49030e33129803e7ef
+diff --git a/src/os/linux/vm/os_linux.cpp b/src/os/linux/vm/os_linux.cpp
+--- a/src/os/linux/vm/os_linux.cpp
++++ b/src/os/linux/vm/os_linux.cpp
+@@ -4356,14 +4356,108 @@
+   }
+ }
+ 
++// TODO: This is almost 100% copied from os_solaris.cpp,
++// it can and should be extracted into a shared method.
++static bool assign_distribution(uint*           id_array,
++                                uint           id_length,
++                                uint*          distribution,
++                                uint           distribution_length) {
++  // Quick check to see if we won't succeed.
++  if (id_length < distribution_length) {
++    return false;
++  }
++  // Assign processor ids to the distribution.
++  // Try to shuffle processors to distribute work across boards,
++  // assuming 4 processors per board.
++  const uint processors_per_board = ProcessDistributionStride;
++  // Find the maximum processor id.
++  uint max_id = 0;
++  for (uint m = 0; m < id_length; m += 1) {
++    max_id = MAX2(max_id, id_array[m]);
++  }
++  // The next id, to limit loops.
++  const uint limit_id = max_id + 1;
++  // Make up markers for available processors.
++  bool* available_id = NEW_C_HEAP_ARRAY(bool, limit_id, mtInternal);
++  for (uint c = 0; c < limit_id; c += 1) {
++    available_id[c] = false;
++  }
++  for (uint a = 0; a < id_length; a += 1) {
++    available_id[id_array[a]] = true;
++  }
++  // Step by "boards", then by "slot", copying to "assigned".
++  // NEEDS_CLEANUP: The assignment of processors should be stateful,
++  //                remembering which processors have been assigned by
++  //                previous calls, etc., so as to distribute several
++  //                independent calls of this method.  What we'd like is
++  //                It would be nice to have an API that let us ask
++  //                how many processes are bound to a processor,
++  //                but we don't have that, either.
++  //                In the short term, "board" is static so that
++  //                subsequent distributions don't all start at board 0.
++  static uint board = 0;
++  uint assigned = 0;
++  // Until we've found enough processors ....
++  while (assigned < distribution_length) {
++    // ... find the next available processor in the board.
++    for (uint slot = 0; slot < processors_per_board; slot += 1) {
++      uint try_id = board * processors_per_board + slot;
++      if ((try_id < limit_id) && (available_id[try_id] == true)) {
++        distribution[assigned] = try_id;
++        available_id[try_id] = false;
++        assigned += 1;
++        break;
++      }
++    }
++    board += 1;
++    if (board * processors_per_board + 0 >= limit_id) {
++      board = 0;
++    }
++  }
++  if (available_id != NULL) {
++    FREE_C_HEAP_ARRAY(bool, available_id, mtInternal);
++  }
++  return true;
++}
++
+ bool os::distribute_processes(uint length, uint* distribution) {
+-  // Not yet implemented.
++
++  cpu_set_t cpu_set;
++
++  int result =  pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu_set);
++
++  if (result == 0) {
++
++    uint cpu_ids_length;
++    uint *cpu_ids;
++    uint cpu_ids_found = 0;
++
++    cpu_ids_length = CPU_COUNT(&cpu_set);
++
++    cpu_ids = NEW_C_HEAP_ARRAY(uint, cpu_ids_length, mtInternal);
++
++    for (uint i = 0; i < CPU_SETSIZE && cpu_ids_found < cpu_ids_length; i++) {
++      if (CPU_ISSET(i, &cpu_set)) {
++	cpu_ids[cpu_ids_found] = i;
++	cpu_ids_found++;
++      }
++    }
++    bool result = assign_distribution(cpu_ids, cpu_ids_length, distribution, length);
++
++    FREE_C_HEAP_ARRAY(uint, cpu_ids, mtInternal);
++
++    return result;
++  }
+   return false;
+ }
+ 
+ bool os::bind_to_processor(uint processor_id) {
+-  // Not yet implemented.
+-  return false;
++  cpu_set_t cpu_set;
++  CPU_ZERO(&cpu_set);
++  CPU_SET(processor_id, &cpu_set);
++  pthread_t current_thread = pthread_self();
++  int result = pthread_setaffinity_np(current_thread, sizeof(cpu_set), &cpu_set);
++  return result;
+ }
+ 
+ ///
--- a/series	Tue Jul 24 10:09:03 2012 +0200
+++ b/series	Mon Jul 30 13:57:49 2012 +0200
@@ -1,1 +1,6 @@
 linux_thread_name.patch
+hotspot.patch
+zero-makefile.patch
+zero-segfault.patch
+zero-new-math.patch
+psgc-bind-procs.patch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zero-makefile.patch	Mon Jul 30 13:57:49 2012 +0200
@@ -0,0 +1,36 @@
+# HG changeset patch
+# Parent db2aaabd9e401399bd8e426afb67608e87d352cd
+diff --git a/make/Makefile b/make/Makefile
+--- a/make/Makefile
++++ b/make/Makefile
+@@ -402,14 +402,30 @@
+     ifeq ($(JVM_VARIANT_ZEROSHARK), true)
+         $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
+ 		$(install-file)
++        $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo):	$(SHARK_DIR)/%.debuginfo
++		$(install-file)
++        $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz:		$(SHARK_DIR)/%.diz
++		$(install-file)
+         $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX):       $(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
+ 		$(install-file)
++        $(EXPORT_SERVER_DIR)/%.debuginfo:		$(SHARK_DIR)/%.debuginfo
++		$(install-file)
++        $(EXPORT_SERVER_DIR)/%.diz:			$(SHARK_DIR)/%.diz
++		$(install-file)
+     endif
+     ifeq ($(JVM_VARIANT_ZERO), true)
+         $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
+ 		$(install-file)
++        $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo:		$(ZERO_DIR)/%.debuginfo
++		$(install-file)
++        $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz:		$(ZERO_DIR)/%.diz
++		$(install-file)
+         $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX):       $(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
+ 		$(install-file)
++        $(EXPORT_SERVER_DIR)/%.debuginfo:		$(ZERO_DIR)/%.debuginfo
++		$(install-file)
++        $(EXPORT_SERVER_DIR)/%.diz:			$(ZERO_DIR)/%.diz
++		$(install-file)
+     endif
+ endif
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zero-new-math.patch	Mon Jul 30 13:57:49 2012 +0200
@@ -0,0 +1,26 @@
+# HG changeset patch
+# Parent dbe08e8d5dca671e570718f04b0e6f6be5afc02d
+diff --git a/src/cpu/zero/vm/cppInterpreter_zero.cpp b/src/cpu/zero/vm/cppInterpreter_zero.cpp
+--- a/src/cpu/zero/vm/cppInterpreter_zero.cpp
++++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp
+@@ -1714,6 +1714,8 @@
+   case Interpreter::java_lang_math_log:
+   case Interpreter::java_lang_math_log10:
+   case Interpreter::java_lang_math_sqrt:
++  case Interpreter::java_lang_math_pow:
++  case Interpreter::java_lang_math_exp:
+     entry_point = ((InterpreterGenerator*) this)->generate_math_entry(kind);
+     break;
+ 
+diff --git a/src/share/vm/interpreter/cppInterpreter.cpp b/src/share/vm/interpreter/cppInterpreter.cpp
+--- a/src/share/vm/interpreter/cppInterpreter.cpp
++++ b/src/share/vm/interpreter/cppInterpreter.cpp
+@@ -125,6 +125,8 @@
+     method_entry(java_lang_math_sqrt  );
+     method_entry(java_lang_math_log   );
+     method_entry(java_lang_math_log10 );
++    method_entry(java_lang_math_pow );
++    method_entry(java_lang_math_exp );
+     method_entry(java_lang_ref_reference_get);
+     Interpreter::_native_entry_begin = Interpreter::code()->code_end();
+     method_entry(native);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/zero-segfault.patch	Mon Jul 30 13:57:49 2012 +0200
@@ -0,0 +1,14 @@
+# HG changeset patch
+# Parent bbe0f6e46610f23cf483e928e5d30558364e03c3
+diff --git a/src/share/vm/asm/codeBuffer.cpp b/src/share/vm/asm/codeBuffer.cpp
+--- a/src/share/vm/asm/codeBuffer.cpp
++++ b/src/share/vm/asm/codeBuffer.cpp
+@@ -674,7 +674,7 @@
+     }
+   }
+ 
+-  if (dest->blob() == NULL) {
++  if (dest->blob() == NULL && dest_filled != 0x0) {
+     // Destination is a final resting place, not just another buffer.
+     // Normalize uninitialized bytes in the final padding.
+     Copy::fill_to_bytes(dest_filled, dest_end - dest_filled,