--- old/src/cpu/x86/vm/assembler_x86.cpp	2009-01-20 02:13:54.000000000 -0800
+++ new/src/cpu/x86/vm/assembler_x86.cpp	2009-01-20 02:13:54.000000000 -0800
@@ -6244,6 +6244,28 @@
   return off;
 }
 
+void MacroAssembler::load_sized_value(Register dst, Address src,
+                                      int size_in_bytes, bool is_signed) {
+  switch (size_in_bytes ^ (is_signed ? -1 : 0)) {
+#ifndef _LP64
+  // For case 8, caller is responsible for manually loading
+  // the high word into another register.
+  case ~8:  // fall through:
+  case  8:  movl(               dst, src ); break;
+#else
+  case ~8:  // fall through:
+  case  8:  movq(               dst, src ); break;
+#endif
+  case ~4:  // fall through:
+  case  4:  movl(               dst, src ); break;
+  case ~2:  load_signed_word(   dst, src ); break;
+  case  2:  load_unsigned_word( dst, src ); break;
+  case ~1:  load_signed_byte(   dst, src ); break;
+  case  1:  load_unsigned_byte( dst, src ); break;
+  default:  ShouldNotReachHere();
+  }
+}
+
 void MacroAssembler::mov32(AddressLiteral dst, Register src) {
   if (reachable(dst)) {
     movl(as_Address(dst), src);
@@ -7094,6 +7116,241 @@
 }
 
 
+RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr, Register tmp) {
+  intptr_t value = *delayed_value_addr;
+  if (value != 0)
+    return value;
+  movptr(tmp, ExternalAddress((address) delayed_value_addr));
+#ifdef ASSERT
+  Label L;
+  testl(tmp, tmp);
+  jccb(Assembler::notZero, L);
+  hlt();
+  bind(L);
+#endif
+  return tmp;
+}
+
+
+void MacroAssembler::lookup_interface_method(Register recv_klass,
+                                             Register intf_klass,
+                                             RegisterConstant itable_index,
+                                             Register method_result,
+                                             Register scan_temp,
+                                             Label& L_no_such_interface) {
+  assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
+  assert(itable_index.is_constant() || itable_index.as_register() == method_result,
+         "caller must use same register for non-constant itable index as for method");
+
+  // Compute start of first itableOffsetEntry (which is at the end of the vtable)
+  int vtable_base = instanceKlass::vtable_start_offset() * wordSize;
+  int scan_step   = itableOffsetEntry::size() * wordSize;
+  int vte_size    = vtableEntry::size() * wordSize;
+  Address::ScaleFactor times_vte_scale = Address::times_ptr;
+  assert(vte_size == wordSize, "else adjust times_vte_scale");
+
+  movl(scan_temp, Address(recv_klass, instanceKlass::vtable_length_offset() * wordSize));
+  lea( scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base));
+  if (HeapWordsPerLong > 1) {
+    // Round up to align_object_offset boundary
+    round_to(scan_temp, BytesPerLong);
+  }
+
+  // Adjust recv_klass by scaled itable_index, so we can free itable_index.
+  assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
+  lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr));
+
+  // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
+  //   if (scan->interface() == intf) {
+  //     result = (klass + scan->offset() + itable_index);
+  //   }
+  // }
+  Label search, found_method;
+
+  for (int peel = 1; peel >= 0; peel--) {
+    movptr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes()));
+    cmpptr(intf_klass, method_result);
+    jccb(Assembler::notEqual, search);
+
+    // Got a hit.
+    movl(method_result, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes()));
+    movptr(method_result, Address(recv_klass, method_result, Address::times_1));
+
+    if (!peel)  break;
+    jmp(found_method);
+
+    bind(search);
+    // Check that the previous entry is non-null.  A null entry means that
+    // the reciever class doesn't implement the interface, and wasn't the
+    // same as when the caller was compiled.
+    testptr(method_result, method_result);
+    jcc(Assembler::zero, L_no_such_interface);
+    addptr(scan_temp, scan_step);
+  }
+
+  bind(found_method);
+}
+
+
+// Test sub_klass against super_klass.
+// Fall through on failure, but branch to L_success if there is a match.
+// Use up the given temp_reg, but don't kill any other register.
+// Update the sub's secondary super cache if necesary.
+void MacroAssembler::check_klass_subtype(Register sub_klass,
+                                         Register super_klass,
+                                         Register temp_reg,
+                                         Label& L_success) {
+  Label L_failure;              // fallthrough label
+
+  assert_different_registers(sub_klass, super_klass, temp_reg);
+
+  // a couple of useful fields in sub_klass:
+  int ss_offset = (klassOopDesc::header_size() * HeapWordSize +
+                   Klass::secondary_supers_offset_in_bytes());
+  int sc_offset = (klassOopDesc::header_size() * HeapWordSize +
+                   Klass::secondary_super_cache_offset_in_bytes());
+  Address secondary_supers_addr(sub_klass, ss_offset);
+  Address super_cache_addr(     sub_klass, sc_offset);
+
+  int sco_offset = (klassOopDesc::header_size() * HeapWordSize +
+                    Klass::super_check_offset_offset_in_bytes());
+  Address super_check_offset_addr(super_klass, sco_offset);
+
+  // if the pointers are equal, we are done (e.g., String[] elements)
+  cmpptr(sub_klass, super_klass);
+  jcc(Assembler::equal, L_success);
+
+  // check the supertype display:
+  movl(temp_reg, super_check_offset_addr);
+  Address super_check_addr(sub_klass, temp_reg, Address::times_1, 0);
+  cmpptr(super_klass, super_check_addr); // load displayed supertype
+  jcc(Assembler::equal, L_success);
+
+  // if it was a primary super, we can just fail immediately
+  cmpl(temp_reg, sc_offset);
+  jcc(Assembler::notEqual, L_failure);
+
+  // Now do a linear scan of the secondary super-klass chain.
+  // This code is rarely used, so simplicity is a virtue here.
+  {
+    // The repne_scan instruction uses fixed registers, which we must spill.
+    // Don't bother to figure out pre-existing connections with the input regs.
+    push(rax);
+    push(rcx);
+    push(rdi);
+    push(super_klass);
+
+    movptr(rdi, secondary_supers_addr);
+    // Load the array length.
+    movl(rcx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));
+    // Skip to start of data.
+    addptr(rdi, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
+    // Scan rcx words at [edi] for occurance of rax,
+    // Set NZ/Z based on last compare
+    pop(rax);   // super_klass value, even if it was in rdi or rcx
+
+
+#ifdef _LP64
+    // This part is tricky, as values in supers array could be 32 or 64 bit wide
+    // and we store values in objArrays always encoded, thus we need to encode
+    // the value of rax before repne.  Note that rax is dead after the repne.
+    if (UseCompressedOops) {
+      encode_heap_oop_not_null(rax);
+      repne_scanl();
+    } else
+#endif // _LP64
+      repne_scan();
+
+    // Unspill the temp. registers:
+    pop(rdi);
+    pop(rcx);
+    pop(rax);
+  }
+  jcc(Assembler::notEqual, L_failure);
+
+  // Success.  Cache the super we found and proceed in triumph.
+  movptr(super_cache_addr, super_klass);
+
+  jmp(L_success);
+
+  // Fall through on failure!
+  bind(L_failure);
+}
+
+
+// registers on entry:
+//  - rax ('check' register): required MethodType
+//  - rcx: method handle
+//  - rdx, rsi, or ?: killable temp
+void MacroAssembler::check_method_handle_type(Register mtype_reg, Register mh_reg,
+                                              Register temp_reg,
+                                              Label& wrong_method_type) {
+  if (UseCompressedOops)  unimplemented();  // field accesses must decode
+  // compare method type against that of the receiver
+  cmpptr(mtype_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)));
+  jcc(Assembler::notEqual, wrong_method_type);
+}
+
+
+void MacroAssembler::load_method_handle_vmslots(Register vmslots_reg, Register mh_reg,
+                                                Register temp_reg) {
+  if (UseCompressedOops)  unimplemented();  // field accesses must decode
+  // load mh.type.form.vmslots
+  if (java_dyn_MethodHandle::vmslots_offset_in_bytes() != 0) {
+    // hoist vmslots into every mh to avoid dependent load chain
+    movl(vmslots_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmslots_offset_in_bytes, temp_reg)));
+  } else {
+    Register temp2_reg = vmslots_reg;
+    movptr(temp2_reg, Address(mh_reg,    delayed_value(java_dyn_MethodHandle::type_offset_in_bytes, temp_reg)));
+    movptr(temp2_reg, Address(temp2_reg, delayed_value(java_dyn_MethodType::form_offset_in_bytes, temp_reg)));
+    movl(vmslots_reg, Address(temp2_reg, delayed_value(java_dyn_MethodTypeForm::vmslots_offset_in_bytes, temp_reg)));
+  }
+}
+
+
+// registers on entry:
+//  - rcx: method handle
+//  - rdx: killable temp (interpreted only)
+//  - rax: killable temp (compiled only)
+void MacroAssembler::jump_to_method_handle_entry(Register mh_reg, Register temp_reg) {
+  assert(mh_reg == rcx, "caller must put MH object in rcx");
+  assert_different_registers(mh_reg, temp_reg);
+
+  if (UseCompressedOops)  unimplemented();  // field accesses must decode
+
+  // pick out the interpreted side of the handler
+  movptr(temp_reg, Address(mh_reg, delayed_value(java_dyn_MethodHandle::vmentry_offset_in_bytes, temp_reg)));
+
+  // off we go...
+  jmp(Address(temp_reg, MethodEntry::from_interpreted_entry_offset_in_bytes()));
+
+  // for the various stubs which take control at this point,
+  // see MethodHandles::generate_method_handle_stub
+}
+
+
+Address MacroAssembler::argument_address(RegisterConstant arg_slot,
+                                         int extra_slot_offset) {
+  // cf. TemplateTable::prepare_invoke(), if (load_receiver).
+  int stackElementSize = Interpreter::stackElementSize();
+  int offset = Interpreter::expr_offset_in_bytes(extra_slot_offset+0);
+#ifdef ASSERT
+  int offset1 = Interpreter::expr_offset_in_bytes(extra_slot_offset+1);
+  assert(offset1 - offset == stackElementSize, "correct arithmetic");
+#endif
+  Register             scale_reg    = noreg;
+  Address::ScaleFactor scale_factor = Address::no_scale;
+  if (arg_slot.is_constant()) {
+    offset += arg_slot.as_constant() * stackElementSize;
+  } else {
+    scale_reg    = arg_slot.as_register();
+    scale_factor = Address::times(stackElementSize);
+  }
+  offset += wordSize;           // return PC is on stack
+  return Address(rsp, scale_reg, scale_factor, offset);
+}
+
+
 void MacroAssembler::verify_oop_addr(Address addr, const char* s) {
   if (!VerifyOops) return;
 
