Merge

Tue, 10 Mar 2009 08:52:16 -0700

author
kvn
date
Tue, 10 Mar 2009 08:52:16 -0700
changeset 1060
2f2f54ed12ce
parent 1055
bcedf688d882
parent 1059
337400e7a5dd
child 1062
fcf566137dbf
child 1076
6af0a709d52b

Merge

src/cpu/x86/vm/interp_masm_x86_32.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/interp_masm_x86_64.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp	Mon Mar 09 11:32:57 2009 -0400
     1.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp	Tue Mar 10 08:52:16 2009 -0700
     1.3 @@ -2615,6 +2615,158 @@
     1.4    }
     1.5  }
     1.6  
     1.7 +RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr,
     1.8 +                                               Register tmp,
     1.9 +                                               int offset) {
    1.10 +  intptr_t value = *delayed_value_addr;
    1.11 +  if (value != 0)
    1.12 +    return RegisterConstant(value + offset);
    1.13 +
    1.14 +  // load indirectly to solve generation ordering problem
    1.15 +  Address a(tmp, (address) delayed_value_addr);
    1.16 +  load_ptr_contents(a, tmp);
    1.17 +
    1.18 +#ifdef ASSERT
    1.19 +  tst(tmp);
    1.20 +  breakpoint_trap(zero, xcc);
    1.21 +#endif
    1.22 +
    1.23 +  if (offset != 0)
    1.24 +    add(tmp, offset, tmp);
    1.25 +
    1.26 +  return RegisterConstant(tmp);
    1.27 +}
    1.28 +
    1.29 +
    1.30 +void MacroAssembler::regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) {
    1.31 +  assert(dest.register_or_noreg() != G0, "lost side effect");
    1.32 +  if ((src.is_constant() && src.as_constant() == 0) ||
    1.33 +      (src.is_register() && src.as_register() == G0)) {
    1.34 +    // do nothing
    1.35 +  } else if (dest.is_register()) {
    1.36 +    add(dest.as_register(), ensure_rs2(src, temp), dest.as_register());
    1.37 +  } else if (src.is_constant()) {
    1.38 +    intptr_t res = dest.as_constant() + src.as_constant();
    1.39 +    dest = RegisterConstant(res); // side effect seen by caller
    1.40 +  } else {
    1.41 +    assert(temp != noreg, "cannot handle constant += register");
    1.42 +    add(src.as_register(), ensure_rs2(dest, temp), temp);
    1.43 +    dest = RegisterConstant(temp); // side effect seen by caller
    1.44 +  }
    1.45 +}
    1.46 +
    1.47 +void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) {
    1.48 +  assert(dest.register_or_noreg() != G0, "lost side effect");
    1.49 +  if (!is_simm13(src.constant_or_zero()))
    1.50 +    src = (src.as_constant() & 0xFF);
    1.51 +  if ((src.is_constant() && src.as_constant() == 0) ||
    1.52 +      (src.is_register() && src.as_register() == G0)) {
    1.53 +    // do nothing
    1.54 +  } else if (dest.is_register()) {
    1.55 +    sll_ptr(dest.as_register(), src, dest.as_register());
    1.56 +  } else if (src.is_constant()) {
    1.57 +    intptr_t res = dest.as_constant() << src.as_constant();
    1.58 +    dest = RegisterConstant(res); // side effect seen by caller
    1.59 +  } else {
    1.60 +    assert(temp != noreg, "cannot handle constant <<= register");
    1.61 +    set(dest.as_constant(), temp);
    1.62 +    sll_ptr(temp, src, temp);
    1.63 +    dest = RegisterConstant(temp); // side effect seen by caller
    1.64 +  }
    1.65 +}
    1.66 +
    1.67 +
    1.68 +// Look up the method for a megamorphic invokeinterface call.
    1.69 +// The target method is determined by <intf_klass, itable_index>.
    1.70 +// The receiver klass is in recv_klass.
    1.71 +// On success, the result will be in method_result, and execution falls through.
    1.72 +// On failure, execution transfers to the given label.
    1.73 +void MacroAssembler::lookup_interface_method(Register recv_klass,
    1.74 +                                             Register intf_klass,
    1.75 +                                             RegisterConstant itable_index,
    1.76 +                                             Register method_result,
    1.77 +                                             Register scan_temp,
    1.78 +                                             Register sethi_temp,
    1.79 +                                             Label& L_no_such_interface) {
    1.80 +  assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
    1.81 +  assert(itable_index.is_constant() || itable_index.as_register() == method_result,
    1.82 +         "caller must use same register for non-constant itable index as for method");
    1.83 +
    1.84 +  // Compute start of first itableOffsetEntry (which is at the end of the vtable)
    1.85 +  int vtable_base = instanceKlass::vtable_start_offset() * wordSize;
    1.86 +  int scan_step   = itableOffsetEntry::size() * wordSize;
    1.87 +  int vte_size    = vtableEntry::size() * wordSize;
    1.88 +
    1.89 +  lduw(recv_klass, instanceKlass::vtable_length_offset() * wordSize, scan_temp);
    1.90 +  // %%% We should store the aligned, prescaled offset in the klassoop.
    1.91 +  // Then the next several instructions would fold away.
    1.92 +
    1.93 +  int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0);
    1.94 +  int itb_offset = vtable_base;
    1.95 +  if (round_to_unit != 0) {
    1.96 +    // hoist first instruction of round_to(scan_temp, BytesPerLong):
    1.97 +    itb_offset += round_to_unit - wordSize;
    1.98 +  }
    1.99 +  int itb_scale = exact_log2(vtableEntry::size() * wordSize);
   1.100 +  sll(scan_temp, itb_scale,  scan_temp);
   1.101 +  add(scan_temp, itb_offset, scan_temp);
   1.102 +  if (round_to_unit != 0) {
   1.103 +    // Round up to align_object_offset boundary
   1.104 +    // see code for instanceKlass::start_of_itable!
   1.105 +    // Was: round_to(scan_temp, BytesPerLong);
   1.106 +    // Hoisted: add(scan_temp, BytesPerLong-1, scan_temp);
   1.107 +    and3(scan_temp, -round_to_unit, scan_temp);
   1.108 +  }
   1.109 +  add(recv_klass, scan_temp, scan_temp);
   1.110 +
   1.111 +  // Adjust recv_klass by scaled itable_index, so we can free itable_index.
   1.112 +  RegisterConstant itable_offset = itable_index;
   1.113 +  regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize));
   1.114 +  regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes());
   1.115 +  add(recv_klass, ensure_rs2(itable_offset, sethi_temp), recv_klass);
   1.116 +
   1.117 +  // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
   1.118 +  //   if (scan->interface() == intf) {
   1.119 +  //     result = (klass + scan->offset() + itable_index);
   1.120 +  //   }
   1.121 +  // }
   1.122 +  Label search, found_method;
   1.123 +
   1.124 +  for (int peel = 1; peel >= 0; peel--) {
   1.125 +    // %%%% Could load both offset and interface in one ldx, if they were
   1.126 +    // in the opposite order.  This would save a load.
   1.127 +    ld_ptr(scan_temp, itableOffsetEntry::interface_offset_in_bytes(), method_result);
   1.128 +
   1.129 +    // Check that this entry is non-null.  A null entry means that
   1.130 +    // the receiver class doesn't implement the interface, and wasn't the
   1.131 +    // same as when the caller was compiled.
   1.132 +    bpr(Assembler::rc_z, false, Assembler::pn, method_result, L_no_such_interface);
   1.133 +    delayed()->cmp(method_result, intf_klass);
   1.134 +
   1.135 +    if (peel) {
   1.136 +      brx(Assembler::equal,    false, Assembler::pt, found_method);
   1.137 +    } else {
   1.138 +      brx(Assembler::notEqual, false, Assembler::pn, search);
   1.139 +      // (invert the test to fall through to found_method...)
   1.140 +    }
   1.141 +    delayed()->add(scan_temp, scan_step, scan_temp);
   1.142 +
   1.143 +    if (!peel)  break;
   1.144 +
   1.145 +    bind(search);
   1.146 +  }
   1.147 +
   1.148 +  bind(found_method);
   1.149 +
   1.150 +  // Got a hit.
   1.151 +  int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
   1.152 +  // scan_temp[-scan_step] points to the vtable offset we need
   1.153 +  ito_offset -= scan_step;
   1.154 +  lduw(scan_temp, ito_offset, scan_temp);
   1.155 +  ld_ptr(recv_klass, scan_temp, method_result);
   1.156 +}
   1.157 +
   1.158 +
   1.159  void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
   1.160                                            Register temp_reg,
   1.161                                            Label& done, Label* slow_case,
   1.162 @@ -4057,6 +4209,24 @@
   1.163    card_table_write(bs->byte_map_base, tmp, store_addr);
   1.164  }
   1.165  
   1.166 +// Loading values by size and signed-ness
   1.167 +void MacroAssembler::load_sized_value(Register s1, RegisterConstant s2, Register d,
   1.168 +                                      int size_in_bytes, bool is_signed) {
   1.169 +  switch (size_in_bytes ^ (is_signed ? -1 : 0)) {
   1.170 +  case ~8:  // fall through:
   1.171 +  case  8:  ld_long( s1, s2, d ); break;
   1.172 +  case ~4:  ldsw(    s1, s2, d ); break;
   1.173 +  case  4:  lduw(    s1, s2, d ); break;
   1.174 +  case ~2:  ldsh(    s1, s2, d ); break;
   1.175 +  case  2:  lduh(    s1, s2, d ); break;
   1.176 +  case ~1:  ldsb(    s1, s2, d ); break;
   1.177 +  case  1:  ldub(    s1, s2, d ); break;
   1.178 +  default:  ShouldNotReachHere();
   1.179 +  }
   1.180 +}
   1.181 +
   1.182 +
   1.183 +
   1.184  void MacroAssembler::load_klass(Register src_oop, Register klass) {
   1.185    // The number of bytes in this code is used by
   1.186    // MachCallDynamicJavaNode::ret_addr_offset()
     2.1 --- a/src/cpu/sparc/vm/assembler_sparc.hpp	Mon Mar 09 11:32:57 2009 -0400
     2.2 +++ b/src/cpu/sparc/vm/assembler_sparc.hpp	Tue Mar 10 08:52:16 2009 -0700
     2.3 @@ -384,6 +384,12 @@
     2.4  
     2.5    inline bool is_simm13(int offset = 0);  // check disp+offset for overflow
     2.6  
     2.7 +  Address plus_disp(int disp) const {     // bump disp by a small amount
     2.8 +    Address a = (*this);
     2.9 +    a._disp += disp;
    2.10 +    return a;
    2.11 +  }
    2.12 +
    2.13    Address split_disp() const {            // deal with disp overflow
    2.14      Address a = (*this);
    2.15      int hi_disp = _disp & ~0x3ff;
    2.16 @@ -1082,6 +1088,7 @@
    2.17    inline void add(    Register s1, Register s2, Register d );
    2.18    inline void add(    Register s1, int simm13a, Register d, relocInfo::relocType rtype = relocInfo::none);
    2.19    inline void add(    Register s1, int simm13a, Register d, RelocationHolder const& rspec);
    2.20 +  inline void add(    Register s1, RegisterConstant s2, Register d, int offset = 0);
    2.21    inline void add(    const Address&  a,              Register d, int offset = 0);
    2.22  
    2.23    void addcc(  Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3  | cc_bit_op3) | rs1(s1) | rs2(s2) ); }
    2.24 @@ -1298,6 +1305,16 @@
    2.25    inline void ld(   const Address& a, Register d, int offset = 0 );
    2.26    inline void ldd(  const Address& a, Register d, int offset = 0 );
    2.27  
    2.28 +  inline void ldub(  Register s1, RegisterConstant s2, Register d );
    2.29 +  inline void ldsb(  Register s1, RegisterConstant s2, Register d );
    2.30 +  inline void lduh(  Register s1, RegisterConstant s2, Register d );
    2.31 +  inline void ldsh(  Register s1, RegisterConstant s2, Register d );
    2.32 +  inline void lduw(  Register s1, RegisterConstant s2, Register d );
    2.33 +  inline void ldsw(  Register s1, RegisterConstant s2, Register d );
    2.34 +  inline void ldx(   Register s1, RegisterConstant s2, Register d );
    2.35 +  inline void ld(    Register s1, RegisterConstant s2, Register d );
    2.36 +  inline void ldd(   Register s1, RegisterConstant s2, Register d );
    2.37 +
    2.38    // pp 177
    2.39  
    2.40    void ldsba(  Register s1, Register s2, int ia, Register d ) {             emit_long( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
    2.41 @@ -1518,6 +1535,13 @@
    2.42    inline void st(   Register d, const Address& a, int offset = 0 );
    2.43    inline void std(  Register d, const Address& a, int offset = 0 );
    2.44  
    2.45 +  inline void stb(  Register d, Register s1, RegisterConstant s2 );
    2.46 +  inline void sth(  Register d, Register s1, RegisterConstant s2 );
    2.47 +  inline void stw(  Register d, Register s1, RegisterConstant s2 );
    2.48 +  inline void stx(  Register d, Register s1, RegisterConstant s2 );
    2.49 +  inline void std(  Register d, Register s1, RegisterConstant s2 );
    2.50 +  inline void st(   Register d, Register s1, RegisterConstant s2 );
    2.51 +
    2.52    // pp 177
    2.53  
    2.54    void stba(  Register d, Register s1, Register s2, int ia ) {             emit_long( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); }
    2.55 @@ -1835,6 +1859,7 @@
    2.56    // Functions for isolating 64 bit shifts for LP64
    2.57    inline void sll_ptr( Register s1, Register s2, Register d );
    2.58    inline void sll_ptr( Register s1, int imm6a,   Register d );
    2.59 +  inline void sll_ptr( Register s1, RegisterConstant s2, Register d );
    2.60    inline void srl_ptr( Register s1, Register s2, Register d );
    2.61    inline void srl_ptr( Register s1, int imm6a,   Register d );
    2.62  
    2.63 @@ -1940,20 +1965,47 @@
    2.64    // st_ptr will perform st for 32 bit VM's and stx for 64 bit VM's
    2.65    inline void ld_ptr(   Register s1, Register s2, Register d );
    2.66    inline void ld_ptr(   Register s1, int simm13a, Register d);
    2.67 +  inline void ld_ptr(   Register s1, RegisterConstant s2, Register d );
    2.68    inline void ld_ptr(  const Address& a, Register d, int offset = 0 );
    2.69    inline void st_ptr(  Register d, Register s1, Register s2 );
    2.70    inline void st_ptr(  Register d, Register s1, int simm13a);
    2.71 +  inline void st_ptr(  Register d, Register s1, RegisterConstant s2 );
    2.72    inline void st_ptr(  Register d, const Address& a, int offset = 0 );
    2.73  
    2.74    // ld_long will perform ld for 32 bit VM's and ldx for 64 bit VM's
    2.75    // st_long will perform st for 32 bit VM's and stx for 64 bit VM's
    2.76    inline void ld_long( Register s1, Register s2, Register d );
    2.77    inline void ld_long( Register s1, int simm13a, Register d );
    2.78 +  inline void ld_long( Register s1, RegisterConstant s2, Register d );
    2.79    inline void ld_long( const Address& a, Register d, int offset = 0 );
    2.80    inline void st_long( Register d, Register s1, Register s2 );
    2.81    inline void st_long( Register d, Register s1, int simm13a );
    2.82 +  inline void st_long( Register d, Register s1, RegisterConstant s2 );
    2.83    inline void st_long( Register d, const Address& a, int offset = 0 );
    2.84  
    2.85 +  // Loading values by size and signed-ness
    2.86 +  void load_sized_value(Register s1, RegisterConstant s2, Register d,
    2.87 +                        int size_in_bytes, bool is_signed);
    2.88 +
    2.89 +  // Helpers for address formation.
    2.90 +  // They update the dest in place, whether it is a register or constant.
    2.91 +  // They emit no code at all if src is a constant zero.
    2.92 +  // If dest is a constant and src is a register, the temp argument
    2.93 +  // is required, and becomes the result.
    2.94 +  // If dest is a register and src is a non-simm13 constant,
    2.95 +  // the temp argument is required, and is used to materialize the constant.
    2.96 +  void regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src,
    2.97 +                       Register temp = noreg );
    2.98 +  void regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src,
    2.99 +                       Register temp = noreg );
   2.100 +  RegisterConstant ensure_rs2(RegisterConstant rs2, Register sethi_temp) {
   2.101 +    guarantee(sethi_temp != noreg, "constant offset overflow");
   2.102 +    if (is_simm13(rs2.constant_or_zero()))
   2.103 +      return rs2;               // register or short constant
   2.104 +    set(rs2.as_constant(), sethi_temp);
   2.105 +    return sethi_temp;
   2.106 +  }
   2.107 +
   2.108    // --------------------------------------------------
   2.109  
   2.110   public:
   2.111 @@ -2267,6 +2319,14 @@
   2.112    );
   2.113    void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
   2.114  
   2.115 +  // interface method calling
   2.116 +  void lookup_interface_method(Register recv_klass,
   2.117 +                               Register intf_klass,
   2.118 +                               RegisterConstant itable_index,
   2.119 +                               Register method_result,
   2.120 +                               Register temp_reg, Register temp2_reg,
   2.121 +                               Label& no_such_interface);
   2.122 +
   2.123    // Stack overflow checking
   2.124  
   2.125    // Note: this clobbers G3_scratch
   2.126 @@ -2281,6 +2341,8 @@
   2.127    // stack overflow + shadow pages.  Clobbers tsp and scratch registers.
   2.128    void bang_stack_size(Register Rsize, Register Rtsp, Register Rscratch);
   2.129  
   2.130 +  virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset);
   2.131 +
   2.132    void verify_tlab();
   2.133  
   2.134    Condition negate_condition(Condition cond);
     3.1 --- a/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Mon Mar 09 11:32:57 2009 -0400
     3.2 +++ b/src/cpu/sparc/vm/assembler_sparc.inline.hpp	Tue Mar 10 08:52:16 2009 -0700
     3.3 @@ -143,6 +143,49 @@
     3.4  inline void Assembler::ld(  Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); }
     3.5  #endif
     3.6  
     3.7 +inline void Assembler::ldub(  Register s1, RegisterConstant s2, Register d) {
     3.8 +  if (s2.is_register())  ldsb(s1, s2.as_register(), d);
     3.9 +  else                   ldsb(s1, s2.as_constant(), d);
    3.10 +}
    3.11 +inline void Assembler::ldsb(  Register s1, RegisterConstant s2, Register d) {
    3.12 +  if (s2.is_register())  ldsb(s1, s2.as_register(), d);
    3.13 +  else                   ldsb(s1, s2.as_constant(), d);
    3.14 +}
    3.15 +inline void Assembler::lduh(  Register s1, RegisterConstant s2, Register d) {
    3.16 +  if (s2.is_register())  ldsh(s1, s2.as_register(), d);
    3.17 +  else                   ldsh(s1, s2.as_constant(), d);
    3.18 +}
    3.19 +inline void Assembler::ldsh(  Register s1, RegisterConstant s2, Register d) {
    3.20 +  if (s2.is_register())  ldsh(s1, s2.as_register(), d);
    3.21 +  else                   ldsh(s1, s2.as_constant(), d);
    3.22 +}
    3.23 +inline void Assembler::lduw(  Register s1, RegisterConstant s2, Register d) {
    3.24 +  if (s2.is_register())  ldsw(s1, s2.as_register(), d);
    3.25 +  else                   ldsw(s1, s2.as_constant(), d);
    3.26 +}
    3.27 +inline void Assembler::ldsw(  Register s1, RegisterConstant s2, Register d) {
    3.28 +  if (s2.is_register())  ldsw(s1, s2.as_register(), d);
    3.29 +  else                   ldsw(s1, s2.as_constant(), d);
    3.30 +}
    3.31 +inline void Assembler::ldx(   Register s1, RegisterConstant s2, Register d) {
    3.32 +  if (s2.is_register())  ldx(s1, s2.as_register(), d);
    3.33 +  else                   ldx(s1, s2.as_constant(), d);
    3.34 +}
    3.35 +inline void Assembler::ld(    Register s1, RegisterConstant s2, Register d) {
    3.36 +  if (s2.is_register())  ld(s1, s2.as_register(), d);
    3.37 +  else                   ld(s1, s2.as_constant(), d);
    3.38 +}
    3.39 +inline void Assembler::ldd(   Register s1, RegisterConstant s2, Register d) {
    3.40 +  if (s2.is_register())  ldd(s1, s2.as_register(), d);
    3.41 +  else                   ldd(s1, s2.as_constant(), d);
    3.42 +}
    3.43 +
    3.44 +// form effective addresses this way:
    3.45 +inline void Assembler::add(   Register s1, RegisterConstant s2, Register d, int offset) {
    3.46 +  if (s2.is_register())  add(s1, s2.as_register(), d);
    3.47 +  else                 { add(s1, s2.as_constant() + offset, d); offset = 0; }
    3.48 +  if (offset != 0)       add(d,  offset,                    d);
    3.49 +}
    3.50  
    3.51  inline void Assembler::ld(   const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ld(   a.base(), a.disp() + offset, d ); }
    3.52  inline void Assembler::ldsb( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldsb( a.base(), a.disp() + offset, d ); }
    3.53 @@ -200,6 +243,27 @@
    3.54  inline void Assembler::st(  Register d, Register s1, Register s2) { stw(d, s1, s2); }
    3.55  inline void Assembler::st(  Register d, Register s1, int simm13a) { stw(d, s1, simm13a); }
    3.56  
    3.57 +inline void Assembler::stb(  Register d, Register s1, RegisterConstant s2) {
    3.58 +  if (s2.is_register())  stb(d, s1, s2.as_register());
    3.59 +  else                   stb(d, s1, s2.as_constant());
    3.60 +}
    3.61 +inline void Assembler::sth(  Register d, Register s1, RegisterConstant s2) {
    3.62 +  if (s2.is_register())  sth(d, s1, s2.as_register());
    3.63 +  else                   sth(d, s1, s2.as_constant());
    3.64 +}
    3.65 +inline void Assembler::stx(  Register d, Register s1, RegisterConstant s2) {
    3.66 +  if (s2.is_register())  stx(d, s1, s2.as_register());
    3.67 +  else                   stx(d, s1, s2.as_constant());
    3.68 +}
    3.69 +inline void Assembler::std( Register d, Register s1, RegisterConstant s2) {
    3.70 +  if (s2.is_register())  std(d, s1, s2.as_register());
    3.71 +  else                   std(d, s1, s2.as_constant());
    3.72 +}
    3.73 +inline void Assembler::st(  Register d, Register s1, RegisterConstant s2) {
    3.74 +  if (s2.is_register())  st(d, s1, s2.as_register());
    3.75 +  else                   st(d, s1, s2.as_constant());
    3.76 +}
    3.77 +
    3.78  inline void Assembler::stb( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stb( d, a.base(), a.disp() + offset); }
    3.79  inline void Assembler::sth( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); sth( d, a.base(), a.disp() + offset); }
    3.80  inline void Assembler::stw( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stw( d, a.base(), a.disp() + offset); }
    3.81 @@ -244,6 +308,14 @@
    3.82  #endif
    3.83  }
    3.84  
    3.85 +inline void MacroAssembler::ld_ptr( Register s1, RegisterConstant s2, Register d ) {
    3.86 +#ifdef _LP64
    3.87 +  Assembler::ldx( s1, s2, d);
    3.88 +#else
    3.89 +  Assembler::ld(  s1, s2, d);
    3.90 +#endif
    3.91 +}
    3.92 +
    3.93  inline void MacroAssembler::ld_ptr( const Address& a, Register d, int offset ) {
    3.94  #ifdef _LP64
    3.95    Assembler::ldx(  a, d, offset );
    3.96 @@ -268,6 +340,14 @@
    3.97  #endif
    3.98  }
    3.99  
   3.100 +inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterConstant s2 ) {
   3.101 +#ifdef _LP64
   3.102 +  Assembler::stx( d, s1, s2);
   3.103 +#else
   3.104 +  Assembler::st( d, s1, s2);
   3.105 +#endif
   3.106 +}
   3.107 +
   3.108  inline void MacroAssembler::st_ptr(  Register d, const Address& a, int offset) {
   3.109  #ifdef _LP64
   3.110    Assembler::stx(  d, a, offset);
   3.111 @@ -293,6 +373,14 @@
   3.112  #endif
   3.113  }
   3.114  
   3.115 +inline void MacroAssembler::ld_long( Register s1, RegisterConstant s2, Register d ) {
   3.116 +#ifdef _LP64
   3.117 +  Assembler::ldx(s1, s2, d);
   3.118 +#else
   3.119 +  Assembler::ldd(s1, s2, d);
   3.120 +#endif
   3.121 +}
   3.122 +
   3.123  inline void MacroAssembler::ld_long( const Address& a, Register d, int offset ) {
   3.124  #ifdef _LP64
   3.125    Assembler::ldx(a, d, offset );
   3.126 @@ -317,6 +405,14 @@
   3.127  #endif
   3.128  }
   3.129  
   3.130 +inline void MacroAssembler::st_long( Register d, Register s1, RegisterConstant s2 ) {
   3.131 +#ifdef _LP64
   3.132 +  Assembler::stx(d, s1, s2);
   3.133 +#else
   3.134 +  Assembler::std(d, s1, s2);
   3.135 +#endif
   3.136 +}
   3.137 +
   3.138  inline void MacroAssembler::st_long( Register d, const Address& a, int offset ) {
   3.139  #ifdef _LP64
   3.140    Assembler::stx(d, a, offset);
   3.141 @@ -359,6 +455,11 @@
   3.142  #endif
   3.143  }
   3.144  
   3.145 +inline void MacroAssembler::sll_ptr( Register s1, RegisterConstant s2, Register d ) {
   3.146 +  if (s2.is_register())  sll_ptr(s1, s2.as_register(), d);
   3.147 +  else                   sll_ptr(s1, s2.as_constant(), d);
   3.148 +}
   3.149 +
   3.150  // Use the right branch for the platform
   3.151  
   3.152  inline void MacroAssembler::br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) {
     4.1 --- a/src/cpu/sparc/vm/sparc.ad	Mon Mar 09 11:32:57 2009 -0400
     4.2 +++ b/src/cpu/sparc/vm/sparc.ad	Tue Mar 10 08:52:16 2009 -0700
     4.3 @@ -1,5 +1,5 @@
     4.4  //
     4.5 -// Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
     4.6 +// Copyright 1998-2009 Sun Microsystems, Inc.  All Rights Reserved.
     4.7  // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.8  //
     4.9  // This code is free software; you can redistribute it and/or modify it
    4.10 @@ -5286,55 +5286,91 @@
    4.11    ins_cost(MEMORY_REF_COST);
    4.12  
    4.13    size(4);
    4.14 -  format %{ "LDSB   $mem,$dst" %}
    4.15 +  format %{ "LDSB   $mem,$dst\t! byte" %}
    4.16    opcode(Assembler::ldsb_op3);
    4.17    ins_encode(simple_form3_mem_reg( mem, dst ) );
    4.18    ins_pipe(iload_mask_mem);
    4.19  %}
    4.20  
    4.21 -// Load Byte (8bit UNsigned) into an int reg
    4.22 -instruct loadUB(iRegI dst, memory mem, immI_255 bytemask) %{
    4.23 -  match(Set dst (AndI (LoadB mem) bytemask));
    4.24 +// Load Byte (8bit signed) into a Long Register
    4.25 +instruct loadB2L(iRegL dst, memory mem) %{
    4.26 +  match(Set dst (ConvI2L (LoadB mem)));
    4.27    ins_cost(MEMORY_REF_COST);
    4.28  
    4.29    size(4);
    4.30 -  format %{ "LDUB   $mem,$dst" %}
    4.31 +  format %{ "LDSB   $mem,$dst\t! byte -> long" %}
    4.32 +  opcode(Assembler::ldsb_op3);
    4.33 +  ins_encode(simple_form3_mem_reg( mem, dst ) );
    4.34 +  ins_pipe(iload_mask_mem);
    4.35 +%}
    4.36 +
    4.37 +// Load Unsigned Byte (8bit UNsigned) into an int reg
    4.38 +instruct loadUB(iRegI dst, memory mem) %{
    4.39 +  match(Set dst (LoadUB mem));
    4.40 +  ins_cost(MEMORY_REF_COST);
    4.41 +
    4.42 +  size(4);
    4.43 +  format %{ "LDUB   $mem,$dst\t! ubyte" %}
    4.44    opcode(Assembler::ldub_op3);
    4.45    ins_encode(simple_form3_mem_reg( mem, dst ) );
    4.46    ins_pipe(iload_mask_mem);
    4.47  %}
    4.48  
    4.49 -// Load Byte (8bit UNsigned) into a Long Register
    4.50 -instruct loadUBL(iRegL dst, memory mem, immL_FF bytemask) %{
    4.51 -  match(Set dst (AndL (ConvI2L (LoadB mem)) bytemask));
    4.52 +// Load Unsigned Byte (8bit UNsigned) into a Long Register
    4.53 +instruct loadUB2L(iRegL dst, memory mem) %{
    4.54 +  match(Set dst (ConvI2L (LoadUB mem)));
    4.55    ins_cost(MEMORY_REF_COST);
    4.56  
    4.57    size(4);
    4.58 -  format %{ "LDUB   $mem,$dst" %}
    4.59 +  format %{ "LDUB   $mem,$dst\t! ubyte -> long" %}
    4.60    opcode(Assembler::ldub_op3);
    4.61    ins_encode(simple_form3_mem_reg( mem, dst ) );
    4.62    ins_pipe(iload_mask_mem);
    4.63  %}
    4.64  
    4.65 -// Load Unsigned Short/Char (16bit UNsigned) into a Long Register
    4.66 -instruct loadUS2L(iRegL dst, memory mem, immL_FFFF bytemask) %{
    4.67 -  match(Set dst (AndL (ConvI2L (LoadUS mem)) bytemask));
    4.68 +// Load Short (16bit signed)
    4.69 +instruct loadS(iRegI dst, memory mem) %{
    4.70 +  match(Set dst (LoadS mem));
    4.71    ins_cost(MEMORY_REF_COST);
    4.72  
    4.73    size(4);
    4.74 -  format %{ "LDUH   $mem,$dst" %}
    4.75 +  format %{ "LDSH   $mem,$dst\t! short" %}
    4.76 +  opcode(Assembler::ldsh_op3);
    4.77 +  ins_encode(simple_form3_mem_reg( mem, dst ) );
    4.78 +  ins_pipe(iload_mask_mem);
    4.79 +%}
    4.80 +
    4.81 +// Load Short (16bit signed) into a Long Register
    4.82 +instruct loadS2L(iRegL dst, memory mem) %{
    4.83 +  match(Set dst (ConvI2L (LoadS mem)));
    4.84 +  ins_cost(MEMORY_REF_COST);
    4.85 +
    4.86 +  size(4);
    4.87 +  format %{ "LDSH   $mem,$dst\t! short -> long" %}
    4.88 +  opcode(Assembler::ldsh_op3);
    4.89 +  ins_encode(simple_form3_mem_reg( mem, dst ) );
    4.90 +  ins_pipe(iload_mask_mem);
    4.91 +%}
    4.92 +
    4.93 +// Load Unsigned Short/Char (16bit UNsigned)
    4.94 +instruct loadUS(iRegI dst, memory mem) %{
    4.95 +  match(Set dst (LoadUS mem));
    4.96 +  ins_cost(MEMORY_REF_COST);
    4.97 +
    4.98 +  size(4);
    4.99 +  format %{ "LDUH   $mem,$dst\t! ushort/char" %}
   4.100    opcode(Assembler::lduh_op3);
   4.101    ins_encode(simple_form3_mem_reg( mem, dst ) );
   4.102    ins_pipe(iload_mask_mem);
   4.103  %}
   4.104  
   4.105 -// Load Unsigned Short/Char (16bit unsigned)
   4.106 -instruct loadUS(iRegI dst, memory mem) %{
   4.107 -  match(Set dst (LoadUS mem));
   4.108 +// Load Unsigned Short/Char (16bit UNsigned) into a Long Register
   4.109 +instruct loadUS2L(iRegL dst, memory mem) %{
   4.110 +  match(Set dst (ConvI2L (LoadUS mem)));
   4.111    ins_cost(MEMORY_REF_COST);
   4.112  
   4.113    size(4);
   4.114 -  format %{ "LDUH   $mem,$dst" %}
   4.115 +  format %{ "LDUH   $mem,$dst\t! ushort/char -> long" %}
   4.116    opcode(Assembler::lduh_op3);
   4.117    ins_encode(simple_form3_mem_reg( mem, dst ) );
   4.118    ins_pipe(iload_mask_mem);
   4.119 @@ -5344,9 +5380,33 @@
   4.120  instruct loadI(iRegI dst, memory mem) %{
   4.121    match(Set dst (LoadI mem));
   4.122    ins_cost(MEMORY_REF_COST);
   4.123 -  size(4);
   4.124 -
   4.125 -  format %{ "LDUW   $mem,$dst" %}
   4.126 +
   4.127 +  size(4);
   4.128 +  format %{ "LDUW   $mem,$dst\t! int" %}
   4.129 +  opcode(Assembler::lduw_op3);
   4.130 +  ins_encode(simple_form3_mem_reg( mem, dst ) );
   4.131 +  ins_pipe(iload_mem);
   4.132 +%}
   4.133 +
   4.134 +// Load Integer into a Long Register
   4.135 +instruct loadI2L(iRegL dst, memory mem) %{
   4.136 +  match(Set dst (ConvI2L (LoadI mem)));
   4.137 +  ins_cost(MEMORY_REF_COST);
   4.138 +
   4.139 +  size(4);
   4.140 +  format %{ "LDSW   $mem,$dst\t! int -> long" %}
   4.141 +  opcode(Assembler::ldsw_op3);
   4.142 +  ins_encode(simple_form3_mem_reg( mem, dst ) );
   4.143 +  ins_pipe(iload_mem);
   4.144 +%}
   4.145 +
   4.146 +// Load Unsigned Integer into a Long Register
   4.147 +instruct loadUI2L(iRegL dst, memory mem) %{
   4.148 +  match(Set dst (LoadUI2L mem));
   4.149 +  ins_cost(MEMORY_REF_COST);
   4.150 +
   4.151 +  size(4);
   4.152 +  format %{ "LDUW   $mem,$dst\t! uint -> long" %}
   4.153    opcode(Assembler::lduw_op3);
   4.154    ins_encode(simple_form3_mem_reg( mem, dst ) );
   4.155    ins_pipe(iload_mem);
   4.156 @@ -5356,6 +5416,7 @@
   4.157  instruct loadL(iRegL dst, memory mem ) %{
   4.158    match(Set dst (LoadL mem));
   4.159    ins_cost(MEMORY_REF_COST);
   4.160 +
   4.161    size(4);
   4.162    format %{ "LDX    $mem,$dst\t! long" %}
   4.163    opcode(Assembler::ldx_op3);
   4.164 @@ -5471,13 +5532,11 @@
   4.165  
   4.166     format %{ "LDUW   $mem,$dst\t! compressed ptr" %}
   4.167     ins_encode %{
   4.168 -     Register base = as_Register($mem$$base);
   4.169 -     Register index = as_Register($mem$$index);
   4.170 -     Register dst = $dst$$Register;
   4.171 +     Register index = $mem$$index$$Register;
   4.172       if (index != G0) {
   4.173 -       __ lduw(base, index, dst);
   4.174 +       __ lduw($mem$$base$$Register, index, $dst$$Register);
   4.175       } else {
   4.176 -       __ lduw(base, $mem$$disp, dst);
   4.177 +       __ lduw($mem$$base$$Register, $mem$$disp, $dst$$Register);
   4.178       }
   4.179     %}
   4.180     ins_pipe(iload_mem);
   4.181 @@ -5521,18 +5580,6 @@
   4.182    ins_pipe(iload_mem);
   4.183  %}
   4.184  
   4.185 -// Load Short (16bit signed)
   4.186 -instruct loadS(iRegI dst, memory mem) %{
   4.187 -  match(Set dst (LoadS mem));
   4.188 -  ins_cost(MEMORY_REF_COST);
   4.189 -
   4.190 -  size(4);
   4.191 -  format %{ "LDSH   $mem,$dst" %}
   4.192 -  opcode(Assembler::ldsh_op3);
   4.193 -  ins_encode(simple_form3_mem_reg( mem, dst ) );
   4.194 -  ins_pipe(iload_mask_mem);
   4.195 -%}
   4.196 -
   4.197  // Load Double
   4.198  instruct loadD(regD dst, memory mem) %{
   4.199    match(Set dst (LoadD mem));
     5.1 --- a/src/cpu/sparc/vm/vtableStubs_sparc.cpp	Mon Mar 09 11:32:57 2009 -0400
     5.2 +++ b/src/cpu/sparc/vm/vtableStubs_sparc.cpp	Tue Mar 10 08:52:16 2009 -0700
     5.3 @@ -106,6 +106,15 @@
     5.4    __ delayed()->nop();
     5.5  
     5.6    masm->flush();
     5.7 +
     5.8 +  if (PrintMiscellaneous && (WizardMode || Verbose)) {
     5.9 +    tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d",
    5.10 +                  vtable_index, s->entry_point(),
    5.11 +                  (int)(s->code_end() - s->entry_point()),
    5.12 +                  (int)(s->code_end() - __ pc()));
    5.13 +  }
    5.14 +  guarantee(__ pc() <= s->code_end(), "overflowed buffer");
    5.15 +
    5.16    s->set_exception_points(npe_addr, ame_addr);
    5.17    return s;
    5.18  }
    5.19 @@ -113,9 +122,9 @@
    5.20  
    5.21  // NOTE:  %%%% if any change is made to this stub make sure that the function
    5.22  //             pd_code_size_limit is changed to ensure the correct size for VtableStub
    5.23 -VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
    5.24 +VtableStub* VtableStubs::create_itable_stub(int itable_index) {
    5.25    const int sparc_code_length = VtableStub::pd_code_size_limit(false);
    5.26 -  VtableStub* s = new(sparc_code_length) VtableStub(false, vtable_index);
    5.27 +  VtableStub* s = new(sparc_code_length) VtableStub(false, itable_index);
    5.28    ResourceMark rm;
    5.29    CodeBuffer cb(s->entry_point(), sparc_code_length);
    5.30    MacroAssembler* masm = new MacroAssembler(&cb);
    5.31 @@ -139,7 +148,6 @@
    5.32    // are passed in the %o registers.  Instead, longs are passed in G1 and G4
    5.33    // and so those registers are not available here.
    5.34    __ save(SP,-frame::register_save_words*wordSize,SP);
    5.35 -  Register I0_receiver = I0;    // Location of receiver after save
    5.36  
    5.37  #ifndef PRODUCT
    5.38    if (CountCompiledCalls) {
    5.39 @@ -151,63 +159,31 @@
    5.40    }
    5.41  #endif /* PRODUCT */
    5.42  
    5.43 -  // load start of itable entries into L0 register
    5.44 -  const int base = instanceKlass::vtable_start_offset() * wordSize;
    5.45 -  __ ld(Address(G3_klassOop, 0, instanceKlass::vtable_length_offset() * wordSize), L0);
    5.46 +  Label throw_icce;
    5.47  
    5.48 -  // %%% Could store the aligned, prescaled offset in the klassoop.
    5.49 -  __ sll(L0, exact_log2(vtableEntry::size() * wordSize), L0);
    5.50 -  // see code for instanceKlass::start_of_itable!
    5.51 -  const int vtable_alignment = align_object_offset(1);
    5.52 -  assert(vtable_alignment == 1 || vtable_alignment == 2, "");
    5.53 -  const int odd_bit = vtableEntry::size() * wordSize;
    5.54 -  if (vtable_alignment == 2) {
    5.55 -    __ and3(L0, odd_bit, L1);   // isolate the odd bit
    5.56 -  }
    5.57 -  __ add(G3_klassOop, L0, L0);
    5.58 -  if (vtable_alignment == 2) {
    5.59 -    __ add(L0, L1, L0);         // double the odd bit, to align up
    5.60 -  }
    5.61 -
    5.62 -  // Loop over all itable entries until desired interfaceOop (G5_interface) found
    5.63 -  __ bind(search);
    5.64 -
    5.65 -  // %%%% Could load both offset and interface in one ldx, if they were
    5.66 -  // in the opposite order.  This would save a load.
    5.67 -  __ ld_ptr(L0, base + itableOffsetEntry::interface_offset_in_bytes(), L1);
    5.68 -
    5.69 -  // If the entry is NULL then we've reached the end of the table
    5.70 -  // without finding the expected interface, so throw an exception
    5.71 -  Label throw_icce;
    5.72 -  __ bpr(Assembler::rc_z, false, Assembler::pn, L1, throw_icce);
    5.73 -  __ delayed()->cmp(G5_interface, L1);
    5.74 -  __ brx(Assembler::notEqual, true, Assembler::pn, search);
    5.75 -  __ delayed()->add(L0, itableOffsetEntry::size() * wordSize, L0);
    5.76 -
    5.77 -  // entry found and L0 points to it, move offset of vtable for interface into L0
    5.78 -  __ ld(L0, base + itableOffsetEntry::offset_offset_in_bytes(), L0);
    5.79 -
    5.80 -  // Compute itableMethodEntry and get methodOop(G5_method) and entrypoint(L0) for compiler
    5.81 -  const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes();
    5.82 -  __ add(G3_klassOop, L0, L1);
    5.83 -  __ ld_ptr(L1, method_offset, G5_method);
    5.84 +  Register L5_method = L5;
    5.85 +  __ lookup_interface_method(// inputs: rec. class, interface, itable index
    5.86 +                             G3_klassOop, G5_interface, itable_index,
    5.87 +                             // outputs: method, scan temp. reg
    5.88 +                             L5_method, L2, L3,
    5.89 +                             throw_icce);
    5.90  
    5.91  #ifndef PRODUCT
    5.92    if (DebugVtables) {
    5.93      Label L01;
    5.94 -    __ ld_ptr(L1, method_offset, G5_method);
    5.95 -    __ bpr(Assembler::rc_nz, false, Assembler::pt, G5_method, L01);
    5.96 +    __ bpr(Assembler::rc_nz, false, Assembler::pt, L5_method, L01);
    5.97      __ delayed()->nop();
    5.98      __ stop("methodOop is null");
    5.99      __ bind(L01);
   5.100 -    __ verify_oop(G5_method);
   5.101 +    __ verify_oop(L5_method);
   5.102    }
   5.103  #endif
   5.104  
   5.105    // If the following load is through a NULL pointer, we'll take an OS
   5.106    // exception that should translate into an AbstractMethodError.  We need the
   5.107    // window count to be correct at that time.
   5.108 -  __ restore();                 // Restore registers BEFORE the AME point
   5.109 +  __ restore(L5_method, 0, G5_method);
   5.110 +  // Restore registers *before* the AME point.
   5.111  
   5.112    address ame_addr = __ pc();   // if the vtable entry is null, the method is abstract
   5.113    __ ld_ptr(G5_method, in_bytes(methodOopDesc::from_compiled_offset()), G3_scratch);
   5.114 @@ -225,6 +201,12 @@
   5.115  
   5.116    masm->flush();
   5.117  
   5.118 +  if (PrintMiscellaneous && (WizardMode || Verbose)) {
   5.119 +    tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d",
   5.120 +                  itable_index, s->entry_point(),
   5.121 +                  (int)(s->code_end() - s->entry_point()),
   5.122 +                  (int)(s->code_end() - __ pc()));
   5.123 +  }
   5.124    guarantee(__ pc() <= s->code_end(), "overflowed buffer");
   5.125  
   5.126    s->set_exception_points(npe_addr, ame_addr);
   5.127 @@ -243,8 +225,7 @@
   5.128                          (UseCompressedOops ? 2*BytesPerInstWord : 0);
   5.129        return basic + slop;
   5.130      } else {
   5.131 -      // save, ld, ld, sll, and, add, add, ld, cmp, br, add, ld, add, ld, ld, jmp, restore, sethi, jmpl, restore
   5.132 -      const int basic = (20 LP64_ONLY(+ 6)) * BytesPerInstWord +
   5.133 +      const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord +
   5.134                          // shift;add for load_klass
   5.135                          (UseCompressedOops ? 2*BytesPerInstWord : 0);
   5.136        return (basic + slop);
     6.1 --- a/src/cpu/x86/vm/assembler_x86.cpp	Mon Mar 09 11:32:57 2009 -0400
     6.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp	Tue Mar 10 08:52:16 2009 -0700
     6.3 @@ -1,5 +1,5 @@
     6.4  /*
     6.5 - * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
     6.6 + * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
     6.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.8   *
     6.9   * This code is free software; you can redistribute it and/or modify it
    6.10 @@ -129,13 +129,19 @@
    6.11  // Convert the raw encoding form into the form expected by the constructor for
    6.12  // Address.  An index of 4 (rsp) corresponds to having no index, so convert
    6.13  // that to noreg for the Address constructor.
    6.14 -Address Address::make_raw(int base, int index, int scale, int disp) {
    6.15 +Address Address::make_raw(int base, int index, int scale, int disp, bool disp_is_oop) {
    6.16 +  RelocationHolder rspec;
    6.17 +  if (disp_is_oop) {
    6.18 +    rspec = Relocation::spec_simple(relocInfo::oop_type);
    6.19 +  }
    6.20    bool valid_index = index != rsp->encoding();
    6.21    if (valid_index) {
    6.22      Address madr(as_Register(base), as_Register(index), (Address::ScaleFactor)scale, in_ByteSize(disp));
    6.23 +    madr._rspec = rspec;
    6.24      return madr;
    6.25    } else {
    6.26      Address madr(as_Register(base), noreg, Address::no_scale, in_ByteSize(disp));
    6.27 +    madr._rspec = rspec;
    6.28      return madr;
    6.29    }
    6.30  }
    6.31 @@ -3892,6 +3898,21 @@
    6.32    emit_operand(src, dst);
    6.33  }
    6.34  
    6.35 +void Assembler::movsbq(Register dst, Address src) {
    6.36 +  InstructionMark im(this);
    6.37 +  prefixq(src, dst);
    6.38 +  emit_byte(0x0F);
    6.39 +  emit_byte(0xBE);
    6.40 +  emit_operand(dst, src);
    6.41 +}
    6.42 +
    6.43 +void Assembler::movsbq(Register dst, Register src) {
    6.44 +  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
    6.45 +  emit_byte(0x0F);
    6.46 +  emit_byte(0xBE);
    6.47 +  emit_byte(0xC0 | encode);
    6.48 +}
    6.49 +
    6.50  void Assembler::movslq(Register dst, int32_t imm32) {
    6.51    // dbx shows movslq(rcx, 3) as movq     $0x0000000049000000,(%rbx)
    6.52    // and movslq(r8, 3); as movl     $0x0000000048000000,(%rbx)
    6.53 @@ -3925,6 +3946,51 @@
    6.54    emit_byte(0xC0 | encode);
    6.55  }
    6.56  
    6.57 +void Assembler::movswq(Register dst, Address src) {
    6.58 +  InstructionMark im(this);
    6.59 +  prefixq(src, dst);
    6.60 +  emit_byte(0x0F);
    6.61 +  emit_byte(0xBF);
    6.62 +  emit_operand(dst, src);
    6.63 +}
    6.64 +
    6.65 +void Assembler::movswq(Register dst, Register src) {
    6.66 +  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
    6.67 +  emit_byte(0x0F);
    6.68 +  emit_byte(0xBF);
    6.69 +  emit_byte(0xC0 | encode);
    6.70 +}
    6.71 +
    6.72 +void Assembler::movzbq(Register dst, Address src) {
    6.73 +  InstructionMark im(this);
    6.74 +  prefixq(src, dst);
    6.75 +  emit_byte(0x0F);
    6.76 +  emit_byte(0xB6);
    6.77 +  emit_operand(dst, src);
    6.78 +}
    6.79 +
    6.80 +void Assembler::movzbq(Register dst, Register src) {
    6.81 +  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
    6.82 +  emit_byte(0x0F);
    6.83 +  emit_byte(0xB6);
    6.84 +  emit_byte(0xC0 | encode);
    6.85 +}
    6.86 +
    6.87 +void Assembler::movzwq(Register dst, Address src) {
    6.88 +  InstructionMark im(this);
    6.89 +  prefixq(src, dst);
    6.90 +  emit_byte(0x0F);
    6.91 +  emit_byte(0xB7);
    6.92 +  emit_operand(dst, src);
    6.93 +}
    6.94 +
    6.95 +void Assembler::movzwq(Register dst, Register src) {
    6.96 +  int encode = prefixq_and_encode(dst->encoding(), src->encoding());
    6.97 +  emit_byte(0x0F);
    6.98 +  emit_byte(0xB7);
    6.99 +  emit_byte(0xC0 | encode);
   6.100 +}
   6.101 +
   6.102  void Assembler::negq(Register dst) {
   6.103    int encode = prefixq_and_encode(dst->encoding());
   6.104    emit_byte(0xF7);
   6.105 @@ -6197,8 +6263,11 @@
   6.106    return off;
   6.107  }
   6.108  
   6.109 -// word => int32 which seems bad for 64bit
   6.110 -int MacroAssembler::load_signed_word(Register dst, Address src) {
   6.111 +// Note: load_signed_short used to be called load_signed_word.
   6.112 +// Although the 'w' in x86 opcodes refers to the term "word" in the assembler
   6.113 +// manual, which means 16 bits, that usage is found nowhere in HotSpot code.
   6.114 +// The term "word" in HotSpot means a 32- or 64-bit machine word.
   6.115 +int MacroAssembler::load_signed_short(Register dst, Address src) {
   6.116    int off;
   6.117    if (LP64_ONLY(true ||) VM_Version::is_P6()) {
   6.118      // This is dubious to me since it seems safe to do a signed 16 => 64 bit
   6.119 @@ -6207,7 +6276,7 @@
   6.120      off = offset();
   6.121      movswl(dst, src); // movsxw
   6.122    } else {
   6.123 -    off = load_unsigned_word(dst, src);
   6.124 +    off = load_unsigned_short(dst, src);
   6.125      shll(dst, 16);
   6.126      sarl(dst, 16);
   6.127    }
   6.128 @@ -6229,7 +6298,8 @@
   6.129    return off;
   6.130  }
   6.131  
   6.132 -int MacroAssembler::load_unsigned_word(Register dst, Address src) {
   6.133 +// Note: load_unsigned_short used to be called load_unsigned_word.
   6.134 +int MacroAssembler::load_unsigned_short(Register dst, Address src) {
   6.135    // According to Intel Doc. AP-526, "Zero-Extension of Short", p.16,
   6.136    // and "3.9 Partial Register Penalties", p. 22).
   6.137    int off;
   6.138 @@ -6244,6 +6314,28 @@
   6.139    return off;
   6.140  }
   6.141  
   6.142 +void MacroAssembler::load_sized_value(Register dst, Address src,
   6.143 +                                      int size_in_bytes, bool is_signed) {
   6.144 +  switch (size_in_bytes ^ (is_signed ? -1 : 0)) {
   6.145 +#ifndef _LP64
   6.146 +  // For case 8, caller is responsible for manually loading
   6.147 +  // the second word into another register.
   6.148 +  case ~8:  // fall through:
   6.149 +  case  8:  movl(                dst, src ); break;
   6.150 +#else
   6.151 +  case ~8:  // fall through:
   6.152 +  case  8:  movq(                dst, src ); break;
   6.153 +#endif
   6.154 +  case ~4:  // fall through:
   6.155 +  case  4:  movl(                dst, src ); break;
   6.156 +  case ~2:  load_signed_short(   dst, src ); break;
   6.157 +  case  2:  load_unsigned_short( dst, src ); break;
   6.158 +  case ~1:  load_signed_byte(    dst, src ); break;
   6.159 +  case  1:  load_unsigned_byte(  dst, src ); break;
   6.160 +  default:  ShouldNotReachHere();
   6.161 +  }
   6.162 +}
   6.163 +
   6.164  void MacroAssembler::mov32(AddressLiteral dst, Register src) {
   6.165    if (reachable(dst)) {
   6.166      movl(as_Address(dst), src);
   6.167 @@ -7050,6 +7142,81 @@
   6.168  }
   6.169  
   6.170  
   6.171 +// Look up the method for a megamorphic invokeinterface call.
   6.172 +// The target method is determined by <intf_klass, itable_index>.
   6.173 +// The receiver klass is in recv_klass.
   6.174 +// On success, the result will be in method_result, and execution falls through.
   6.175 +// On failure, execution transfers to the given label.
   6.176 +void MacroAssembler::lookup_interface_method(Register recv_klass,
   6.177 +                                             Register intf_klass,
   6.178 +                                             RegisterConstant itable_index,
   6.179 +                                             Register method_result,
   6.180 +                                             Register scan_temp,
   6.181 +                                             Label& L_no_such_interface) {
   6.182 +  assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
   6.183 +  assert(itable_index.is_constant() || itable_index.as_register() == method_result,
   6.184 +         "caller must use same register for non-constant itable index as for method");
   6.185 +
   6.186 +  // Compute start of first itableOffsetEntry (which is at the end of the vtable)
   6.187 +  int vtable_base = instanceKlass::vtable_start_offset() * wordSize;
   6.188 +  int itentry_off = itableMethodEntry::method_offset_in_bytes();
   6.189 +  int scan_step   = itableOffsetEntry::size() * wordSize;
   6.190 +  int vte_size    = vtableEntry::size() * wordSize;
   6.191 +  Address::ScaleFactor times_vte_scale = Address::times_ptr;
   6.192 +  assert(vte_size == wordSize, "else adjust times_vte_scale");
   6.193 +
   6.194 +  movl(scan_temp, Address(recv_klass, instanceKlass::vtable_length_offset() * wordSize));
   6.195 +
   6.196 +  // %%% Could store the aligned, prescaled offset in the klassoop.
   6.197 +  lea(scan_temp, Address(recv_klass, scan_temp, times_vte_scale, vtable_base));
   6.198 +  if (HeapWordsPerLong > 1) {
   6.199 +    // Round up to align_object_offset boundary
   6.200 +    // see code for instanceKlass::start_of_itable!
   6.201 +    round_to(scan_temp, BytesPerLong);
   6.202 +  }
   6.203 +
   6.204 +  // Adjust recv_klass by scaled itable_index, so we can free itable_index.
   6.205 +  assert(itableMethodEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
   6.206 +  lea(recv_klass, Address(recv_klass, itable_index, Address::times_ptr, itentry_off));
   6.207 +
   6.208 +  // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
   6.209 +  //   if (scan->interface() == intf) {
   6.210 +  //     result = (klass + scan->offset() + itable_index);
   6.211 +  //   }
   6.212 +  // }
   6.213 +  Label search, found_method;
   6.214 +
   6.215 +  for (int peel = 1; peel >= 0; peel--) {
   6.216 +    movptr(method_result, Address(scan_temp, itableOffsetEntry::interface_offset_in_bytes()));
   6.217 +    cmpptr(intf_klass, method_result);
   6.218 +
   6.219 +    if (peel) {
   6.220 +      jccb(Assembler::equal, found_method);
   6.221 +    } else {
   6.222 +      jccb(Assembler::notEqual, search);
   6.223 +      // (invert the test to fall through to found_method...)
   6.224 +    }
   6.225 +
   6.226 +    if (!peel)  break;
   6.227 +
   6.228 +    bind(search);
   6.229 +
   6.230 +    // Check that the previous entry is non-null.  A null entry means that
   6.231 +    // the receiver class doesn't implement the interface, and wasn't the
   6.232 +    // same as when the caller was compiled.
   6.233 +    testptr(method_result, method_result);
   6.234 +    jcc(Assembler::zero, L_no_such_interface);
   6.235 +    addptr(scan_temp, scan_step);
   6.236 +  }
   6.237 +
   6.238 +  bind(found_method);
   6.239 +
   6.240 +  // Got a hit.
   6.241 +  movl(scan_temp, Address(scan_temp, itableOffsetEntry::offset_offset_in_bytes()));
   6.242 +  movptr(method_result, Address(recv_klass, scan_temp, Address::times_1));
   6.243 +}
   6.244 +
   6.245 +
   6.246  void MacroAssembler::ucomisd(XMMRegister dst, AddressLiteral src) {
   6.247    ucomisd(dst, as_Address(src));
   6.248  }
   6.249 @@ -7095,6 +7262,31 @@
   6.250  }
   6.251  
   6.252  
   6.253 +RegisterConstant MacroAssembler::delayed_value(intptr_t* delayed_value_addr,
   6.254 +                                               Register tmp,
   6.255 +                                               int offset) {
   6.256 +  intptr_t value = *delayed_value_addr;
   6.257 +  if (value != 0)
   6.258 +    return RegisterConstant(value + offset);
   6.259 +
   6.260 +  // load indirectly to solve generation ordering problem
   6.261 +  movptr(tmp, ExternalAddress((address) delayed_value_addr));
   6.262 +
   6.263 +#ifdef ASSERT
   6.264 +  Label L;
   6.265 +  testl(tmp, tmp);
   6.266 +  jccb(Assembler::notZero, L);
   6.267 +  hlt();
   6.268 +  bind(L);
   6.269 +#endif
   6.270 +
   6.271 +  if (offset != 0)
   6.272 +    addptr(tmp, offset);
   6.273 +
   6.274 +  return RegisterConstant(tmp);
   6.275 +}
   6.276 +
   6.277 +
   6.278  void MacroAssembler::verify_oop_addr(Address addr, const char* s) {
   6.279    if (!VerifyOops) return;
   6.280  
     7.1 --- a/src/cpu/x86/vm/assembler_x86.hpp	Mon Mar 09 11:32:57 2009 -0400
     7.2 +++ b/src/cpu/x86/vm/assembler_x86.hpp	Tue Mar 10 08:52:16 2009 -0700
     7.3 @@ -1,5 +1,5 @@
     7.4  /*
     7.5 - * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
     7.6 + * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
     7.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.8   *
     7.9   * This code is free software; you can redistribute it and/or modify it
    7.10 @@ -153,6 +153,21 @@
    7.11      times_8  =  3,
    7.12      times_ptr = LP64_ONLY(times_8) NOT_LP64(times_4)
    7.13    };
    7.14 +  static ScaleFactor times(int size) {
    7.15 +    assert(size >= 1 && size <= 8 && is_power_of_2(size), "bad scale size");
    7.16 +    if (size == 8)  return times_8;
    7.17 +    if (size == 4)  return times_4;
    7.18 +    if (size == 2)  return times_2;
    7.19 +    return times_1;
    7.20 +  }
    7.21 +  static int scale_size(ScaleFactor scale) {
    7.22 +    assert(scale != no_scale, "");
    7.23 +    assert(((1 << (int)times_1) == 1 &&
    7.24 +            (1 << (int)times_2) == 2 &&
    7.25 +            (1 << (int)times_4) == 4 &&
    7.26 +            (1 << (int)times_8) == 8), "");
    7.27 +    return (1 << (int)scale);
    7.28 +  }
    7.29  
    7.30   private:
    7.31    Register         _base;
    7.32 @@ -197,6 +212,22 @@
    7.33             "inconsistent address");
    7.34    }
    7.35  
    7.36 +  Address(Register base, RegisterConstant index, ScaleFactor scale = times_1, int disp = 0)
    7.37 +    : _base (base),
    7.38 +      _index(index.register_or_noreg()),
    7.39 +      _scale(scale),
    7.40 +      _disp (disp + (index.constant_or_zero() * scale_size(scale))) {
    7.41 +    if (!index.is_register())  scale = Address::no_scale;
    7.42 +    assert(!_index->is_valid() == (scale == Address::no_scale),
    7.43 +           "inconsistent address");
    7.44 +  }
    7.45 +
    7.46 +  Address plus_disp(int disp) const {
    7.47 +    Address a = (*this);
    7.48 +    a._disp += disp;
    7.49 +    return a;
    7.50 +  }
    7.51 +
    7.52    // The following two overloads are used in connection with the
    7.53    // ByteSize type (see sizes.hpp).  They simplify the use of
    7.54    // ByteSize'd arguments in assembly code. Note that their equivalent
    7.55 @@ -224,6 +255,17 @@
    7.56      assert(!index->is_valid() == (scale == Address::no_scale),
    7.57             "inconsistent address");
    7.58    }
    7.59 +
    7.60 +  Address(Register base, RegisterConstant index, ScaleFactor scale, ByteSize disp)
    7.61 +    : _base (base),
    7.62 +      _index(index.register_or_noreg()),
    7.63 +      _scale(scale),
    7.64 +      _disp (in_bytes(disp) + (index.constant_or_zero() * scale_size(scale))) {
    7.65 +    if (!index.is_register())  scale = Address::no_scale;
    7.66 +    assert(!_index->is_valid() == (scale == Address::no_scale),
    7.67 +           "inconsistent address");
    7.68 +  }
    7.69 +
    7.70  #endif // ASSERT
    7.71  
    7.72    // accessors
    7.73 @@ -236,11 +278,10 @@
    7.74    // Convert the raw encoding form into the form expected by the constructor for
    7.75    // Address.  An index of 4 (rsp) corresponds to having no index, so convert
    7.76    // that to noreg for the Address constructor.
    7.77 -  static Address make_raw(int base, int index, int scale, int disp);
    7.78 +  static Address make_raw(int base, int index, int scale, int disp, bool disp_is_oop);
    7.79  
    7.80    static Address make_array(ArrayAddress);
    7.81  
    7.82 -
    7.83   private:
    7.84    bool base_needs_rex() const {
    7.85      return _base != noreg && _base->encoding() >= 8;
    7.86 @@ -1097,6 +1138,9 @@
    7.87    void movsbl(Register dst, Register src);
    7.88  
    7.89  #ifdef _LP64
    7.90 +  void movsbq(Register dst, Address src);
    7.91 +  void movsbq(Register dst, Register src);
    7.92 +
    7.93    // Move signed 32bit immediate to 64bit extending sign
    7.94    void movslq(Address dst, int32_t imm64);
    7.95    void movslq(Register dst, int32_t imm64);
    7.96 @@ -1109,6 +1153,11 @@
    7.97    void movswl(Register dst, Address src);
    7.98    void movswl(Register dst, Register src);
    7.99  
   7.100 +#ifdef _LP64
   7.101 +  void movswq(Register dst, Address src);
   7.102 +  void movswq(Register dst, Register src);
   7.103 +#endif
   7.104 +
   7.105    void movw(Address dst, int imm16);
   7.106    void movw(Register dst, Address src);
   7.107    void movw(Address dst, Register src);
   7.108 @@ -1116,9 +1165,19 @@
   7.109    void movzbl(Register dst, Address src);
   7.110    void movzbl(Register dst, Register src);
   7.111  
   7.112 +#ifdef _LP64
   7.113 +  void movzbq(Register dst, Address src);
   7.114 +  void movzbq(Register dst, Register src);
   7.115 +#endif
   7.116 +
   7.117    void movzwl(Register dst, Address src);
   7.118    void movzwl(Register dst, Register src);
   7.119  
   7.120 +#ifdef _LP64
   7.121 +  void movzwq(Register dst, Address src);
   7.122 +  void movzwq(Register dst, Register src);
   7.123 +#endif
   7.124 +
   7.125    void mull(Address src);
   7.126    void mull(Register src);
   7.127  
   7.128 @@ -1393,17 +1452,20 @@
   7.129  
   7.130    // The following 4 methods return the offset of the appropriate move instruction
   7.131  
   7.132 -  // Support for fast byte/word loading with zero extension (depending on particular CPU)
   7.133 +  // Support for fast byte/short loading with zero extension (depending on particular CPU)
   7.134    int load_unsigned_byte(Register dst, Address src);
   7.135 -  int load_unsigned_word(Register dst, Address src);
   7.136 -
   7.137 -  // Support for fast byte/word loading with sign extension (depending on particular CPU)
   7.138 +  int load_unsigned_short(Register dst, Address src);
   7.139 +
   7.140 +  // Support for fast byte/short loading with sign extension (depending on particular CPU)
   7.141    int load_signed_byte(Register dst, Address src);
   7.142 -  int load_signed_word(Register dst, Address src);
   7.143 +  int load_signed_short(Register dst, Address src);
   7.144  
   7.145    // Support for sign-extension (hi:lo = extend_sign(lo))
   7.146    void extend_sign(Register hi, Register lo);
   7.147  
   7.148 +  // Loading values by size and signed-ness
   7.149 +  void load_sized_value(Register dst, Address src, int size_in_bytes, bool is_signed);
   7.150 +
   7.151    // Support for inc/dec with optimal instruction selection depending on value
   7.152  
   7.153    void increment(Register reg, int value = 1) { LP64_ONLY(incrementq(reg, value)) NOT_LP64(incrementl(reg, value)) ; }
   7.154 @@ -1721,6 +1783,14 @@
   7.155    );
   7.156    void tlab_refill(Label& retry_tlab, Label& try_eden, Label& slow_case);
   7.157  
   7.158 +  // interface method calling
   7.159 +  void lookup_interface_method(Register recv_klass,
   7.160 +                               Register intf_klass,
   7.161 +                               RegisterConstant itable_index,
   7.162 +                               Register method_result,
   7.163 +                               Register scan_temp,
   7.164 +                               Label& no_such_interface);
   7.165 +
   7.166    //----
   7.167    void set_word_if_not_zero(Register reg); // sets reg to 1 if not zero, otherwise 0
   7.168  
   7.169 @@ -1763,6 +1833,10 @@
   7.170    // stack overflow + shadow pages.  Also, clobbers tmp
   7.171    void bang_stack_size(Register size, Register tmp);
   7.172  
   7.173 +  virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr,
   7.174 +                                         Register tmp,
   7.175 +                                         int offset);
   7.176 +
   7.177    // Support for serializing memory accesses between threads
   7.178    void serialize_memory(Register thread, Register tmp);
   7.179  
     8.1 --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Mon Mar 09 11:32:57 2009 -0400
     8.2 +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Tue Mar 10 08:52:16 2009 -0700
     8.3 @@ -554,8 +554,8 @@
     8.4    __ jcc (Assembler::zero, noLoop);
     8.5  
     8.6    // compare first characters
     8.7 -  __ load_unsigned_word(rcx, Address(rdi, 0));
     8.8 -  __ load_unsigned_word(rbx, Address(rsi, 0));
     8.9 +  __ load_unsigned_short(rcx, Address(rdi, 0));
    8.10 +  __ load_unsigned_short(rbx, Address(rsi, 0));
    8.11    __ subl(rcx, rbx);
    8.12    __ jcc(Assembler::notZero, haveResult);
    8.13    // starting loop
    8.14 @@ -574,8 +574,8 @@
    8.15    Label loop;
    8.16    __ align(wordSize);
    8.17    __ bind(loop);
    8.18 -  __ load_unsigned_word(rcx, Address(rdi, rax, Address::times_2, 0));
    8.19 -  __ load_unsigned_word(rbx, Address(rsi, rax, Address::times_2, 0));
    8.20 +  __ load_unsigned_short(rcx, Address(rdi, rax, Address::times_2, 0));
    8.21 +  __ load_unsigned_short(rbx, Address(rsi, rax, Address::times_2, 0));
    8.22    __ subl(rcx, rbx);
    8.23    __ jcc(Assembler::notZero, haveResult);
    8.24    __ increment(rax);
     9.1 --- a/src/cpu/x86/vm/cppInterpreter_x86.cpp	Mon Mar 09 11:32:57 2009 -0400
     9.2 +++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp	Tue Mar 10 08:52:16 2009 -0700
     9.3 @@ -513,7 +513,7 @@
     9.4      // compute full expression stack limit
     9.5  
     9.6      const Address size_of_stack    (rbx, methodOopDesc::max_stack_offset());
     9.7 -    __ load_unsigned_word(rdx, size_of_stack);                            // get size of expression stack in words
     9.8 +    __ load_unsigned_short(rdx, size_of_stack);                           // get size of expression stack in words
     9.9      __ negptr(rdx);                                                       // so we can subtract in next step
    9.10      // Allocate expression stack
    9.11      __ lea(rsp, Address(rsp, rdx, Address::times_ptr));
    9.12 @@ -659,7 +659,7 @@
    9.13      // Always give one monitor to allow us to start interp if sync method.
    9.14      // Any additional monitors need a check when moving the expression stack
    9.15      const int one_monitor = frame::interpreter_frame_monitor_size() * wordSize;
    9.16 -  __ load_unsigned_word(rax, size_of_stack);                            // get size of expression stack in words
    9.17 +  __ load_unsigned_short(rax, size_of_stack);                           // get size of expression stack in words
    9.18    __ lea(rax, Address(noreg, rax, Interpreter::stackElementScale(), one_monitor));
    9.19    __ lea(rax, Address(rax, rdx, Interpreter::stackElementScale(), overhead_size));
    9.20  
    9.21 @@ -863,13 +863,13 @@
    9.22      __ bind(notByte);
    9.23      __ cmpl(rdx, stos);
    9.24      __ jcc(Assembler::notEqual, notShort);
    9.25 -    __ load_signed_word(rax, field_address);
    9.26 +    __ load_signed_short(rax, field_address);
    9.27      __ jmp(xreturn_path);
    9.28  
    9.29      __ bind(notShort);
    9.30      __ cmpl(rdx, ctos);
    9.31      __ jcc(Assembler::notEqual, notChar);
    9.32 -    __ load_unsigned_word(rax, field_address);
    9.33 +    __ load_unsigned_short(rax, field_address);
    9.34      __ jmp(xreturn_path);
    9.35  
    9.36      __ bind(notChar);
    9.37 @@ -937,7 +937,7 @@
    9.38    const Register locals = rdi;
    9.39  
    9.40    // get parameter size (always needed)
    9.41 -  __ load_unsigned_word(rcx, size_of_parameters);
    9.42 +  __ load_unsigned_short(rcx, size_of_parameters);
    9.43  
    9.44    // rbx: methodOop
    9.45    // rcx: size of parameters
    9.46 @@ -1062,7 +1062,7 @@
    9.47    // allocate space for parameters
    9.48    __ movptr(method, STATE(_method));
    9.49    __ verify_oop(method);
    9.50 -  __ load_unsigned_word(t, Address(method, methodOopDesc::size_of_parameters_offset()));
    9.51 +  __ load_unsigned_short(t, Address(method, methodOopDesc::size_of_parameters_offset()));
    9.52    __ shll(t, 2);
    9.53  #ifdef _LP64
    9.54    __ subptr(rsp, t);
    9.55 @@ -1659,11 +1659,11 @@
    9.56    // const Address monitor(rbp, frame::interpreter_frame_initial_sp_offset * wordSize - (int)sizeof(BasicObjectLock));
    9.57  
    9.58    // get parameter size (always needed)
    9.59 -  __ load_unsigned_word(rcx, size_of_parameters);
    9.60 +  __ load_unsigned_short(rcx, size_of_parameters);
    9.61  
    9.62    // rbx: methodOop
    9.63    // rcx: size of parameters
    9.64 -  __ load_unsigned_word(rdx, size_of_locals);                      // get size of locals in words
    9.65 +  __ load_unsigned_short(rdx, size_of_locals);                     // get size of locals in words
    9.66  
    9.67    __ subptr(rdx, rcx);                                             // rdx = no. of additional locals
    9.68  
    9.69 @@ -1949,7 +1949,7 @@
    9.70    __ movptr(rbx, STATE(_result._to_call._callee));
    9.71  
    9.72    // callee left args on top of expression stack, remove them
    9.73 -  __ load_unsigned_word(rcx, Address(rbx, methodOopDesc::size_of_parameters_offset()));
    9.74 +  __ load_unsigned_short(rcx, Address(rbx, methodOopDesc::size_of_parameters_offset()));
    9.75    __ lea(rsp, Address(rsp, rcx, Address::times_ptr));
    9.76  
    9.77    __ movl(rcx, Address(rbx, methodOopDesc::result_index_offset()));
    9.78 @@ -2119,7 +2119,7 @@
    9.79    // Make it look like call_stub calling conventions
    9.80  
    9.81    // Get (potential) receiver
    9.82 -  __ load_unsigned_word(rcx, size_of_parameters);                     // get size of parameters in words
    9.83 +  __ load_unsigned_short(rcx, size_of_parameters);                   // get size of parameters in words
    9.84  
    9.85    ExternalAddress recursive(CAST_FROM_FN_PTR(address, RecursiveInterpreterActivation));
    9.86    __ pushptr(recursive.addr());                                      // make it look good in the debugger
    10.1 --- a/src/cpu/x86/vm/interp_masm_x86_32.cpp	Mon Mar 09 11:32:57 2009 -0400
    10.2 +++ b/src/cpu/x86/vm/interp_masm_x86_32.cpp	Tue Mar 10 08:52:16 2009 -0700
    10.3 @@ -192,7 +192,7 @@
    10.4  void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset) {
    10.5    assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
    10.6    assert(cache != index, "must use different registers");
    10.7 -  load_unsigned_word(index, Address(rsi, bcp_offset));
    10.8 +  load_unsigned_short(index, Address(rsi, bcp_offset));
    10.9    movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
   10.10    assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
   10.11    shlptr(index, 2); // convert from field index to ConstantPoolCacheEntry index
   10.12 @@ -202,7 +202,7 @@
   10.13  void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset) {
   10.14    assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
   10.15    assert(cache != tmp, "must use different register");
   10.16 -  load_unsigned_word(tmp, Address(rsi, bcp_offset));
   10.17 +  load_unsigned_short(tmp, Address(rsi, bcp_offset));
   10.18    assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
   10.19                                 // convert from field index to ConstantPoolCacheEntry index
   10.20                                 // and from word offset to byte offset
   10.21 @@ -1031,7 +1031,7 @@
   10.22  
   10.23    // If the mdp is valid, it will point to a DataLayout header which is
   10.24    // consistent with the bcp.  The converse is highly probable also.
   10.25 -  load_unsigned_word(rdx, Address(rcx, in_bytes(DataLayout::bci_offset())));
   10.26 +  load_unsigned_short(rdx, Address(rcx, in_bytes(DataLayout::bci_offset())));
   10.27    addptr(rdx, Address(rbx, methodOopDesc::const_offset()));
   10.28    lea(rdx, Address(rdx, constMethodOopDesc::codes_offset()));
   10.29    cmpptr(rdx, rsi);
    11.1 --- a/src/cpu/x86/vm/interp_masm_x86_64.cpp	Mon Mar 09 11:32:57 2009 -0400
    11.2 +++ b/src/cpu/x86/vm/interp_masm_x86_64.cpp	Tue Mar 10 08:52:16 2009 -0700
    11.3 @@ -190,7 +190,7 @@
    11.4                                                             int bcp_offset) {
    11.5    assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
    11.6    assert(cache != index, "must use different registers");
    11.7 -  load_unsigned_word(index, Address(r13, bcp_offset));
    11.8 +  load_unsigned_short(index, Address(r13, bcp_offset));
    11.9    movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
   11.10    assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
   11.11    // convert from field index to ConstantPoolCacheEntry index
   11.12 @@ -203,7 +203,7 @@
   11.13                                                                 int bcp_offset) {
   11.14    assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
   11.15    assert(cache != tmp, "must use different register");
   11.16 -  load_unsigned_word(tmp, Address(r13, bcp_offset));
   11.17 +  load_unsigned_short(tmp, Address(r13, bcp_offset));
   11.18    assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
   11.19    // convert from field index to ConstantPoolCacheEntry index
   11.20    // and from word offset to byte offset
   11.21 @@ -1063,8 +1063,8 @@
   11.22  
   11.23    // If the mdp is valid, it will point to a DataLayout header which is
   11.24    // consistent with the bcp.  The converse is highly probable also.
   11.25 -  load_unsigned_word(c_rarg2,
   11.26 -                     Address(c_rarg3, in_bytes(DataLayout::bci_offset())));
   11.27 +  load_unsigned_short(c_rarg2,
   11.28 +                      Address(c_rarg3, in_bytes(DataLayout::bci_offset())));
   11.29    addptr(c_rarg2, Address(rbx, methodOopDesc::const_offset()));
   11.30    lea(c_rarg2, Address(c_rarg2, constMethodOopDesc::codes_offset()));
   11.31    cmpptr(c_rarg2, r13);
    12.1 --- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Mon Mar 09 11:32:57 2009 -0400
    12.2 +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp	Tue Mar 10 08:52:16 2009 -0700
    12.3 @@ -662,13 +662,13 @@
    12.4      __ bind(notByte);
    12.5      __ cmpl(rdx, stos);
    12.6      __ jcc(Assembler::notEqual, notShort);
    12.7 -    __ load_signed_word(rax, field_address);
    12.8 +    __ load_signed_short(rax, field_address);
    12.9      __ jmp(xreturn_path);
   12.10  
   12.11      __ bind(notShort);
   12.12      __ cmpl(rdx, ctos);
   12.13      __ jcc(Assembler::notEqual, notChar);
   12.14 -    __ load_unsigned_word(rax, field_address);
   12.15 +    __ load_unsigned_short(rax, field_address);
   12.16      __ jmp(xreturn_path);
   12.17  
   12.18      __ bind(notChar);
   12.19 @@ -723,7 +723,7 @@
   12.20    const Address access_flags      (rbx, methodOopDesc::access_flags_offset());
   12.21  
   12.22    // get parameter size (always needed)
   12.23 -  __ load_unsigned_word(rcx, size_of_parameters);
   12.24 +  __ load_unsigned_short(rcx, size_of_parameters);
   12.25  
   12.26    // native calls don't need the stack size check since they have no expression stack
   12.27    // and the arguments are already on the stack and we only add a handful of words
   12.28 @@ -838,7 +838,7 @@
   12.29    // allocate space for parameters
   12.30    __ get_method(method);
   12.31    __ verify_oop(method);
   12.32 -  __ load_unsigned_word(t, Address(method, methodOopDesc::size_of_parameters_offset()));
   12.33 +  __ load_unsigned_short(t, Address(method, methodOopDesc::size_of_parameters_offset()));
   12.34    __ shlptr(t, Interpreter::logStackElementSize());
   12.35    __ addptr(t, 2*wordSize);     // allocate two more slots for JNIEnv and possible mirror
   12.36    __ subptr(rsp, t);
   12.37 @@ -1155,14 +1155,14 @@
   12.38    const Address access_flags      (rbx, methodOopDesc::access_flags_offset());
   12.39  
   12.40    // get parameter size (always needed)
   12.41 -  __ load_unsigned_word(rcx, size_of_parameters);
   12.42 +  __ load_unsigned_short(rcx, size_of_parameters);
   12.43  
   12.44    // rbx,: methodOop
   12.45    // rcx: size of parameters
   12.46  
   12.47    // rsi: sender_sp (could differ from sp+wordSize if we were called via c2i )
   12.48  
   12.49 -  __ load_unsigned_word(rdx, size_of_locals);       // get size of locals in words
   12.50 +  __ load_unsigned_short(rdx, size_of_locals);       // get size of locals in words
   12.51    __ subl(rdx, rcx);                                // rdx = no. of additional locals
   12.52  
   12.53    // see if we've got enough room on the stack for locals plus overhead.
   12.54 @@ -1558,7 +1558,7 @@
   12.55      // Compute size of arguments for saving when returning to deoptimized caller
   12.56      __ get_method(rax);
   12.57      __ verify_oop(rax);
   12.58 -    __ load_unsigned_word(rax, Address(rax, in_bytes(methodOopDesc::size_of_parameters_offset())));
   12.59 +    __ load_unsigned_short(rax, Address(rax, in_bytes(methodOopDesc::size_of_parameters_offset())));
   12.60      __ shlptr(rax, Interpreter::logStackElementSize());
   12.61      __ restore_locals();
   12.62      __ subptr(rdi, rax);
    13.1 --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Mon Mar 09 11:32:57 2009 -0400
    13.2 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp	Tue Mar 10 08:52:16 2009 -0700
    13.3 @@ -650,7 +650,7 @@
    13.4      __ cmpl(rdx, stos);
    13.5      __ jcc(Assembler::notEqual, notShort);
    13.6      // stos
    13.7 -    __ load_signed_word(rax, field_address);
    13.8 +    __ load_signed_short(rax, field_address);
    13.9      __ jmp(xreturn_path);
   13.10  
   13.11      __ bind(notShort);
   13.12 @@ -662,7 +662,7 @@
   13.13      __ bind(okay);
   13.14  #endif
   13.15      // ctos
   13.16 -    __ load_unsigned_word(rax, field_address);
   13.17 +    __ load_unsigned_short(rax, field_address);
   13.18  
   13.19      __ bind(xreturn_path);
   13.20  
   13.21 @@ -702,7 +702,7 @@
   13.22    const Address access_flags      (rbx, methodOopDesc::access_flags_offset());
   13.23  
   13.24    // get parameter size (always needed)
   13.25 -  __ load_unsigned_word(rcx, size_of_parameters);
   13.26 +  __ load_unsigned_short(rcx, size_of_parameters);
   13.27  
   13.28    // native calls don't need the stack size check since they have no
   13.29    // expression stack and the arguments are already on the stack and
   13.30 @@ -819,9 +819,9 @@
   13.31    // allocate space for parameters
   13.32    __ get_method(method);
   13.33    __ verify_oop(method);
   13.34 -  __ load_unsigned_word(t,
   13.35 -                        Address(method,
   13.36 -                                methodOopDesc::size_of_parameters_offset()));
   13.37 +  __ load_unsigned_short(t,
   13.38 +                         Address(method,
   13.39 +                                 methodOopDesc::size_of_parameters_offset()));
   13.40    __ shll(t, Interpreter::logStackElementSize());
   13.41  
   13.42    __ subptr(rsp, t);
   13.43 @@ -1165,13 +1165,13 @@
   13.44    const Address access_flags(rbx, methodOopDesc::access_flags_offset());
   13.45  
   13.46    // get parameter size (always needed)
   13.47 -  __ load_unsigned_word(rcx, size_of_parameters);
   13.48 +  __ load_unsigned_short(rcx, size_of_parameters);
   13.49  
   13.50    // rbx: methodOop
   13.51    // rcx: size of parameters
   13.52    // r13: sender_sp (could differ from sp+wordSize if we were called via c2i )
   13.53  
   13.54 -  __ load_unsigned_word(rdx, size_of_locals); // get size of locals in words
   13.55 +  __ load_unsigned_short(rdx, size_of_locals); // get size of locals in words
   13.56    __ subl(rdx, rcx); // rdx = no. of additional locals
   13.57  
   13.58    // YYY
   13.59 @@ -1583,7 +1583,7 @@
   13.60      // Compute size of arguments for saving when returning to
   13.61      // deoptimized caller
   13.62      __ get_method(rax);
   13.63 -    __ load_unsigned_word(rax, Address(rax, in_bytes(methodOopDesc::
   13.64 +    __ load_unsigned_short(rax, Address(rax, in_bytes(methodOopDesc::
   13.65                                                  size_of_parameters_offset())));
   13.66      __ shll(rax, Interpreter::logStackElementSize());
   13.67      __ restore_locals(); // XXX do we need this?
    14.1 --- a/src/cpu/x86/vm/templateTable_x86_32.cpp	Mon Mar 09 11:32:57 2009 -0400
    14.2 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp	Tue Mar 10 08:52:16 2009 -0700
    14.3 @@ -296,7 +296,7 @@
    14.4  
    14.5  void TemplateTable::sipush() {
    14.6    transition(vtos, itos);
    14.7 -  __ load_unsigned_word(rax, at_bcp(1));
    14.8 +  __ load_unsigned_short(rax, at_bcp(1));
    14.9    __ bswapl(rax);
   14.10    __ sarl(rax, 16);
   14.11  }
   14.12 @@ -662,7 +662,7 @@
   14.13    index_check(rdx, rax);  // kills rbx,
   14.14    // rax,: index
   14.15    // can do better code for P5 - may want to improve this at some point
   14.16 -  __ load_unsigned_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   14.17 +  __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   14.18    __ mov(rax, rbx);
   14.19  }
   14.20  
   14.21 @@ -677,7 +677,7 @@
   14.22    // rdx: array
   14.23    index_check(rdx, rax);
   14.24    // rax,: index
   14.25 -  __ load_unsigned_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   14.26 +  __ load_unsigned_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   14.27    __ mov(rax, rbx);
   14.28  }
   14.29  
   14.30 @@ -687,7 +687,7 @@
   14.31    index_check(rdx, rax);  // kills rbx,
   14.32    // rax,: index
   14.33    // can do better code for P5 - may want to improve this at some point
   14.34 -  __ load_signed_word(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT)));
   14.35 +  __ load_signed_short(rbx, Address(rdx, rax, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_SHORT)));
   14.36    __ mov(rax, rbx);
   14.37  }
   14.38  
   14.39 @@ -2310,7 +2310,7 @@
   14.40    __ cmpl(flags, ctos );
   14.41    __ jcc(Assembler::notEqual, notChar);
   14.42  
   14.43 -  __ load_unsigned_word(rax, lo );
   14.44 +  __ load_unsigned_short(rax, lo );
   14.45    __ push(ctos);
   14.46    if (!is_static) {
   14.47      patch_bytecode(Bytecodes::_fast_cgetfield, rcx, rbx);
   14.48 @@ -2322,7 +2322,7 @@
   14.49    __ cmpl(flags, stos );
   14.50    __ jcc(Assembler::notEqual, notShort);
   14.51  
   14.52 -  __ load_signed_word(rax, lo );
   14.53 +  __ load_signed_short(rax, lo );
   14.54    __ push(stos);
   14.55    if (!is_static) {
   14.56      patch_bytecode(Bytecodes::_fast_sgetfield, rcx, rbx);
   14.57 @@ -2830,8 +2830,8 @@
   14.58    // access field
   14.59    switch (bytecode()) {
   14.60      case Bytecodes::_fast_bgetfield: __ movsbl(rax, lo );                 break;
   14.61 -    case Bytecodes::_fast_sgetfield: __ load_signed_word(rax, lo );       break;
   14.62 -    case Bytecodes::_fast_cgetfield: __ load_unsigned_word(rax, lo );     break;
   14.63 +    case Bytecodes::_fast_sgetfield: __ load_signed_short(rax, lo );      break;
   14.64 +    case Bytecodes::_fast_cgetfield: __ load_unsigned_short(rax, lo );    break;
   14.65      case Bytecodes::_fast_igetfield: __ movl(rax, lo);                    break;
   14.66      case Bytecodes::_fast_lgetfield: __ stop("should not be rewritten");  break;
   14.67      case Bytecodes::_fast_fgetfield: __ fld_s(lo);                        break;
   14.68 @@ -3055,35 +3055,44 @@
   14.69    // profile this call
   14.70    __ profile_virtual_call(rdx, rsi, rdi);
   14.71  
   14.72 -  __ mov(rdi, rdx); // Save klassOop in rdi
   14.73 -
   14.74 -  // Compute start of first itableOffsetEntry (which is at the end of the vtable)
   14.75 -  const int base = instanceKlass::vtable_start_offset() * wordSize;
   14.76 -  assert(vtableEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below");
   14.77 -  __ movl(rsi, Address(rdx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable
   14.78 -  __ lea(rdx, Address(rdx, rsi, Address::times_4, base));
   14.79 -  if (HeapWordsPerLong > 1) {
   14.80 -    // Round up to align_object_offset boundary
   14.81 -    __ round_to(rdx, BytesPerLong);
   14.82 -  }
   14.83 -
   14.84 -  Label entry, search, interface_ok;
   14.85 -
   14.86 -  __ jmpb(entry);
   14.87 -  __ bind(search);
   14.88 -  __ addptr(rdx, itableOffsetEntry::size() * wordSize);
   14.89 -
   14.90 -  __ bind(entry);
   14.91 -
   14.92 -  // Check that the entry is non-null.  A null entry means that the receiver
   14.93 -  // class doesn't implement the interface, and wasn't the same as the
   14.94 -  // receiver class checked when the interface was resolved.
   14.95 -  __ push(rdx);
   14.96 -  __ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
   14.97 -  __ testptr(rdx, rdx);
   14.98 -  __ jcc(Assembler::notZero, interface_ok);
   14.99 +  Label no_such_interface, no_such_method;
  14.100 +
  14.101 +  __ lookup_interface_method(// inputs: rec. class, interface, itable index
  14.102 +                             rdx, rax, rbx,
  14.103 +                             // outputs: method, scan temp. reg
  14.104 +                             rbx, rsi,
  14.105 +                             no_such_interface);
  14.106 +
  14.107 +  // rbx,: methodOop to call
  14.108 +  // rcx: receiver
  14.109 +  // Check for abstract method error
  14.110 +  // Note: This should be done more efficiently via a throw_abstract_method_error
  14.111 +  //       interpreter entry point and a conditional jump to it in case of a null
  14.112 +  //       method.
  14.113 +  __ testptr(rbx, rbx);
  14.114 +  __ jcc(Assembler::zero, no_such_method);
  14.115 +
  14.116 +  // do the call
  14.117 +  // rcx: receiver
  14.118 +  // rbx,: methodOop
  14.119 +  __ jump_from_interpreted(rbx, rdx);
  14.120 +  __ should_not_reach_here();
  14.121 +
  14.122 +  // exception handling code follows...
  14.123 +  // note: must restore interpreter registers to canonical
  14.124 +  //       state for exception handling to work correctly!
  14.125 +
  14.126 +  __ bind(no_such_method);
  14.127    // throw exception
  14.128 -  __ pop(rdx);           // pop saved register first.
  14.129 +  __ pop(rbx);           // pop return address (pushed by prepare_invoke)
  14.130 +  __ restore_bcp();      // rsi must be correct for exception handler   (was destroyed)
  14.131 +  __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
  14.132 +  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
  14.133 +  // the call_VM checks for exception, so we should never return here.
  14.134 +  __ should_not_reach_here();
  14.135 +
  14.136 +  __ bind(no_such_interface);
  14.137 +  // throw exception
  14.138    __ pop(rbx);           // pop return address (pushed by prepare_invoke)
  14.139    __ restore_bcp();      // rsi must be correct for exception handler   (was destroyed)
  14.140    __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
  14.141 @@ -3091,42 +3100,6 @@
  14.142                     InterpreterRuntime::throw_IncompatibleClassChangeError));
  14.143    // the call_VM checks for exception, so we should never return here.
  14.144    __ should_not_reach_here();
  14.145 -  __ bind(interface_ok);
  14.146 -
  14.147 -    __ pop(rdx);
  14.148 -
  14.149 -    __ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
  14.150 -    __ jcc(Assembler::notEqual, search);
  14.151 -
  14.152 -    __ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes()));
  14.153 -    __ addptr(rdx, rdi); // Add offset to klassOop
  14.154 -    assert(itableMethodEntry::size() * wordSize == (1 << (int)Address::times_ptr), "adjust the scaling in the code below");
  14.155 -    __ movptr(rbx, Address(rdx, rbx, Address::times_ptr));
  14.156 -    // rbx,: methodOop to call
  14.157 -    // rcx: receiver
  14.158 -    // Check for abstract method error
  14.159 -    // Note: This should be done more efficiently via a throw_abstract_method_error
  14.160 -    //       interpreter entry point and a conditional jump to it in case of a null
  14.161 -    //       method.
  14.162 -    { Label L;
  14.163 -      __ testptr(rbx, rbx);
  14.164 -      __ jcc(Assembler::notZero, L);
  14.165 -      // throw exception
  14.166 -          // note: must restore interpreter registers to canonical
  14.167 -          //       state for exception handling to work correctly!
  14.168 -          __ pop(rbx);           // pop return address (pushed by prepare_invoke)
  14.169 -          __ restore_bcp();      // rsi must be correct for exception handler   (was destroyed)
  14.170 -          __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
  14.171 -      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
  14.172 -      // the call_VM checks for exception, so we should never return here.
  14.173 -      __ should_not_reach_here();
  14.174 -      __ bind(L);
  14.175 -    }
  14.176 -
  14.177 -  // do the call
  14.178 -  // rcx: receiver
  14.179 -  // rbx,: methodOop
  14.180 -  __ jump_from_interpreted(rbx, rdx);
  14.181  }
  14.182  
  14.183  //----------------------------------------------------------------------------------------------------
    15.1 --- a/src/cpu/x86/vm/templateTable_x86_64.cpp	Mon Mar 09 11:32:57 2009 -0400
    15.2 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp	Tue Mar 10 08:52:16 2009 -0700
    15.3 @@ -307,7 +307,7 @@
    15.4  
    15.5  void TemplateTable::sipush() {
    15.6    transition(vtos, itos);
    15.7 -  __ load_unsigned_word(rax, at_bcp(1));
    15.8 +  __ load_unsigned_short(rax, at_bcp(1));
    15.9    __ bswapl(rax);
   15.10    __ sarl(rax, 16);
   15.11  }
   15.12 @@ -645,10 +645,10 @@
   15.13    // eax: index
   15.14    // rdx: array
   15.15    index_check(rdx, rax); // kills rbx
   15.16 -  __ load_unsigned_word(rax,
   15.17 -                        Address(rdx, rax,
   15.18 -                                Address::times_2,
   15.19 -                                arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   15.20 +  __ load_unsigned_short(rax,
   15.21 +                         Address(rdx, rax,
   15.22 +                                 Address::times_2,
   15.23 +                                 arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   15.24  }
   15.25  
   15.26  // iload followed by caload frequent pair
   15.27 @@ -663,10 +663,10 @@
   15.28    // rdx: array
   15.29    __ pop_ptr(rdx);
   15.30    index_check(rdx, rax); // kills rbx
   15.31 -  __ load_unsigned_word(rax,
   15.32 -                        Address(rdx, rax,
   15.33 -                                Address::times_2,
   15.34 -                                arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   15.35 +  __ load_unsigned_short(rax,
   15.36 +                         Address(rdx, rax,
   15.37 +                                 Address::times_2,
   15.38 +                                 arrayOopDesc::base_offset_in_bytes(T_CHAR)));
   15.39  }
   15.40  
   15.41  void TemplateTable::saload() {
   15.42 @@ -675,10 +675,10 @@
   15.43    // eax: index
   15.44    // rdx: array
   15.45    index_check(rdx, rax); // kills rbx
   15.46 -  __ load_signed_word(rax,
   15.47 -                      Address(rdx, rax,
   15.48 -                              Address::times_2,
   15.49 -                              arrayOopDesc::base_offset_in_bytes(T_SHORT)));
   15.50 +  __ load_signed_short(rax,
   15.51 +                       Address(rdx, rax,
   15.52 +                               Address::times_2,
   15.53 +                               arrayOopDesc::base_offset_in_bytes(T_SHORT)));
   15.54  }
   15.55  
   15.56  void TemplateTable::iload(int n) {
   15.57 @@ -2276,7 +2276,7 @@
   15.58    __ cmpl(flags, ctos);
   15.59    __ jcc(Assembler::notEqual, notChar);
   15.60    // ctos
   15.61 -  __ load_unsigned_word(rax, field);
   15.62 +  __ load_unsigned_short(rax, field);
   15.63    __ push(ctos);
   15.64    // Rewrite bytecode to be faster
   15.65    if (!is_static) {
   15.66 @@ -2288,7 +2288,7 @@
   15.67    __ cmpl(flags, stos);
   15.68    __ jcc(Assembler::notEqual, notShort);
   15.69    // stos
   15.70 -  __ load_signed_word(rax, field);
   15.71 +  __ load_signed_short(rax, field);
   15.72    __ push(stos);
   15.73    // Rewrite bytecode to be faster
   15.74    if (!is_static) {
   15.75 @@ -2751,10 +2751,10 @@
   15.76      __ movsbl(rax, field);
   15.77      break;
   15.78    case Bytecodes::_fast_sgetfield:
   15.79 -    __ load_signed_word(rax, field);
   15.80 +    __ load_signed_short(rax, field);
   15.81      break;
   15.82    case Bytecodes::_fast_cgetfield:
   15.83 -    __ load_unsigned_word(rax, field);
   15.84 +    __ load_unsigned_short(rax, field);
   15.85      break;
   15.86    case Bytecodes::_fast_fgetfield:
   15.87      __ movflt(xmm0, field);
   15.88 @@ -3010,97 +3010,55 @@
   15.89    // profile this call
   15.90    __ profile_virtual_call(rdx, r13, r14);
   15.91  
   15.92 -  __ mov(r14, rdx); // Save klassOop in r14
   15.93 -
   15.94 -  // Compute start of first itableOffsetEntry (which is at the end of
   15.95 -  // the vtable)
   15.96 -  const int base = instanceKlass::vtable_start_offset() * wordSize;
   15.97 -  // Get length of vtable
   15.98 -  assert(vtableEntry::size() * wordSize == 8,
   15.99 -         "adjust the scaling in the code below");
  15.100 -  __ movl(r13, Address(rdx,
  15.101 -                       instanceKlass::vtable_length_offset() * wordSize));
  15.102 -  __ lea(rdx, Address(rdx, r13, Address::times_8, base));
  15.103 -
  15.104 -  if (HeapWordsPerLong > 1) {
  15.105 -    // Round up to align_object_offset boundary
  15.106 -    __ round_to(rdx, BytesPerLong);
  15.107 -  }
  15.108 -
  15.109 -  Label entry, search, interface_ok;
  15.110 -
  15.111 -  __ jmpb(entry);
  15.112 -  __ bind(search);
  15.113 -  __ addptr(rdx, itableOffsetEntry::size() * wordSize);
  15.114 -
  15.115 -  __ bind(entry);
  15.116 -
  15.117 -  // Check that the entry is non-null.  A null entry means that the
  15.118 -  // receiver class doesn't implement the interface, and wasn't the
  15.119 -  // same as the receiver class checked when the interface was
  15.120 -  // resolved.
  15.121 -  __ push(rdx);
  15.122 -  __ movptr(rdx, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
  15.123 -  __ testptr(rdx, rdx);
  15.124 -  __ jcc(Assembler::notZero, interface_ok);
  15.125 +  Label no_such_interface, no_such_method;
  15.126 +
  15.127 +  __ lookup_interface_method(// inputs: rec. class, interface, itable index
  15.128 +                             rdx, rax, rbx,
  15.129 +                             // outputs: method, scan temp. reg
  15.130 +                             rbx, r13,
  15.131 +                             no_such_interface);
  15.132 +
  15.133 +  // rbx,: methodOop to call
  15.134 +  // rcx: receiver
  15.135 +  // Check for abstract method error
  15.136 +  // Note: This should be done more efficiently via a throw_abstract_method_error
  15.137 +  //       interpreter entry point and a conditional jump to it in case of a null
  15.138 +  //       method.
  15.139 +  __ testptr(rbx, rbx);
  15.140 +  __ jcc(Assembler::zero, no_such_method);
  15.141 +
  15.142 +  // do the call
  15.143 +  // rcx: receiver
  15.144 +  // rbx,: methodOop
  15.145 +  __ jump_from_interpreted(rbx, rdx);
  15.146 +  __ should_not_reach_here();
  15.147 +
  15.148 +  // exception handling code follows...
  15.149 +  // note: must restore interpreter registers to canonical
  15.150 +  //       state for exception handling to work correctly!
  15.151 +
  15.152 +  __ bind(no_such_method);
  15.153    // throw exception
  15.154 -  __ pop(rdx); // pop saved register first.
  15.155 -  __ pop(rbx); // pop return address (pushed by prepare_invoke)
  15.156 -  __ restore_bcp(); // r13 must be correct for exception handler (was
  15.157 -                    // destroyed)
  15.158 -  __ restore_locals(); // make sure locals pointer is correct as well
  15.159 -                       // (was destroyed)
  15.160 +  __ pop(rbx);           // pop return address (pushed by prepare_invoke)
  15.161 +  __ restore_bcp();      // r13 must be correct for exception handler   (was destroyed)
  15.162 +  __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
  15.163 +  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
  15.164 +  // the call_VM checks for exception, so we should never return here.
  15.165 +  __ should_not_reach_here();
  15.166 +
  15.167 +  __ bind(no_such_interface);
  15.168 +  // throw exception
  15.169 +  __ pop(rbx);           // pop return address (pushed by prepare_invoke)
  15.170 +  __ restore_bcp();      // r13 must be correct for exception handler   (was destroyed)
  15.171 +  __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
  15.172    __ call_VM(noreg, CAST_FROM_FN_PTR(address,
  15.173                     InterpreterRuntime::throw_IncompatibleClassChangeError));
  15.174    // the call_VM checks for exception, so we should never return here.
  15.175    __ should_not_reach_here();
  15.176 -  __ bind(interface_ok);
  15.177 -
  15.178 -  __ pop(rdx);
  15.179 -
  15.180 -  __ cmpptr(rax, Address(rdx, itableOffsetEntry::interface_offset_in_bytes()));
  15.181 -  __ jcc(Assembler::notEqual, search);
  15.182 -
  15.183 -  __ movl(rdx, Address(rdx, itableOffsetEntry::offset_offset_in_bytes()));
  15.184 -
  15.185 -  __ addptr(rdx, r14); // Add offset to klassOop
  15.186 -  assert(itableMethodEntry::size() * wordSize == 8,
  15.187 -         "adjust the scaling in the code below");
  15.188 -  __ movptr(rbx, Address(rdx, rbx, Address::times_8));
  15.189 -  // rbx: methodOop to call
  15.190 -  // rcx: receiver
  15.191 -  // Check for abstract method error
  15.192 -  // Note: This should be done more efficiently via a
  15.193 -  // throw_abstract_method_error interpreter entry point and a
  15.194 -  // conditional jump to it in case of a null method.
  15.195 -  {
  15.196 -    Label L;
  15.197 -    __ testptr(rbx, rbx);
  15.198 -    __ jcc(Assembler::notZero, L);
  15.199 -    // throw exception
  15.200 -    // note: must restore interpreter registers to canonical
  15.201 -    //       state for exception handling to work correctly!
  15.202 -    __ pop(rbx);  // pop return address (pushed by prepare_invoke)
  15.203 -    __ restore_bcp(); // r13 must be correct for exception handler
  15.204 -                      // (was destroyed)
  15.205 -    __ restore_locals(); // make sure locals pointer is correct as
  15.206 -                         // well (was destroyed)
  15.207 -    __ call_VM(noreg,
  15.208 -               CAST_FROM_FN_PTR(address,
  15.209 -                             InterpreterRuntime::throw_AbstractMethodError));
  15.210 -    // the call_VM checks for exception, so we should never return here.
  15.211 -    __ should_not_reach_here();
  15.212 -    __ bind(L);
  15.213 -  }
  15.214 -
  15.215 -  __ movptr(rcx, Address(rbx, methodOopDesc::interpreter_entry_offset()));
  15.216 -
  15.217 -  // do the call
  15.218 -  // rcx: receiver
  15.219 -  // rbx: methodOop
  15.220 -  __ jump_from_interpreted(rbx, rdx);
  15.221 +  return;
  15.222  }
  15.223  
  15.224 +
  15.225  //-----------------------------------------------------------------------------
  15.226  // Allocation
  15.227  
    16.1 --- a/src/cpu/x86/vm/vtableStubs_x86_32.cpp	Mon Mar 09 11:32:57 2009 -0400
    16.2 +++ b/src/cpu/x86/vm/vtableStubs_x86_32.cpp	Tue Mar 10 08:52:16 2009 -0700
    16.3 @@ -34,10 +34,16 @@
    16.4  extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index);
    16.5  #endif
    16.6  
    16.7 -// used by compiler only; may use only caller saved registers rax, rbx, rcx.
    16.8 -// rdx holds first int arg, rsi, rdi, rbp are callee-save & must be preserved.
    16.9 -// Leave receiver in rcx; required behavior when +OptoArgsInRegisters
   16.10 -// is modifed to put first oop in rcx.
   16.11 +// These stubs are used by the compiler only.
   16.12 +// Argument registers, which must be preserved:
   16.13 +//   rcx - receiver (always first argument)
   16.14 +//   rdx - second argument (if any)
   16.15 +// Other registers that might be usable:
   16.16 +//   rax - inline cache register (is interface for itable stub)
   16.17 +//   rbx - method (used when calling out to interpreter)
   16.18 +// Available now, but may become callee-save at some point:
   16.19 +//   rsi, rdi
   16.20 +// Note that rax and rdx are also used for return values.
   16.21  //
   16.22  VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
   16.23    const int i486_code_length = VtableStub::pd_code_size_limit(true);
   16.24 @@ -94,16 +100,25 @@
   16.25    __ jmp( Address(method, methodOopDesc::from_compiled_offset()));
   16.26  
   16.27    masm->flush();
   16.28 +
   16.29 +  if (PrintMiscellaneous && (WizardMode || Verbose)) {
   16.30 +    tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d",
   16.31 +                  vtable_index, s->entry_point(),
   16.32 +                  (int)(s->code_end() - s->entry_point()),
   16.33 +                  (int)(s->code_end() - __ pc()));
   16.34 +  }
   16.35 +  guarantee(__ pc() <= s->code_end(), "overflowed buffer");
   16.36 +
   16.37    s->set_exception_points(npe_addr, ame_addr);
   16.38    return s;
   16.39  }
   16.40  
   16.41  
   16.42 -VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
   16.43 +VtableStub* VtableStubs::create_itable_stub(int itable_index) {
   16.44    // Note well: pd_code_size_limit is the absolute minimum we can get away with.  If you
   16.45    //            add code here, bump the code stub size returned by pd_code_size_limit!
   16.46    const int i486_code_length = VtableStub::pd_code_size_limit(false);
   16.47 -  VtableStub* s = new(i486_code_length) VtableStub(false, vtable_index);
   16.48 +  VtableStub* s = new(i486_code_length) VtableStub(false, itable_index);
   16.49    ResourceMark rm;
   16.50    CodeBuffer cb(s->entry_point(), i486_code_length);
   16.51    MacroAssembler* masm = new MacroAssembler(&cb);
   16.52 @@ -123,50 +138,19 @@
   16.53  
   16.54    // get receiver klass (also an implicit null-check)
   16.55    address npe_addr = __ pc();
   16.56 -  __ movptr(rbx, Address(rcx, oopDesc::klass_offset_in_bytes()));
   16.57 +  __ movptr(rsi, Address(rcx, oopDesc::klass_offset_in_bytes()));
   16.58  
   16.59 -  __ mov(rsi, rbx);   // Save klass in free register
   16.60 -  // Most registers are in use, so save a few
   16.61 -  __ push(rdx);
   16.62 -  // compute itable entry offset (in words)
   16.63 -  const int base = instanceKlass::vtable_start_offset() * wordSize;
   16.64 -  assert(vtableEntry::size() * wordSize == 4, "adjust the scaling in the code below");
   16.65 -  __ movl(rdx, Address(rbx, instanceKlass::vtable_length_offset() * wordSize)); // Get length of vtable
   16.66 -  __ lea(rbx, Address(rbx, rdx, Address::times_ptr, base));
   16.67 -  if (HeapWordsPerLong > 1) {
   16.68 -    // Round up to align_object_offset boundary
   16.69 -    __ round_to(rbx, BytesPerLong);
   16.70 -  }
   16.71 -
   16.72 -  Label hit, next, entry, throw_icce;
   16.73 -
   16.74 -  __ jmpb(entry);
   16.75 -
   16.76 -  __ bind(next);
   16.77 -  __ addptr(rbx, itableOffsetEntry::size() * wordSize);
   16.78 -
   16.79 -  __ bind(entry);
   16.80 -
   16.81 -  // If the entry is NULL then we've reached the end of the table
   16.82 -  // without finding the expected interface, so throw an exception
   16.83 -  __ movptr(rdx, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
   16.84 -  __ testptr(rdx, rdx);
   16.85 -  __ jcc(Assembler::zero, throw_icce);
   16.86 -  __ cmpptr(rax, rdx);
   16.87 -  __ jcc(Assembler::notEqual, next);
   16.88 -
   16.89 -  // We found a hit, move offset into rbx,
   16.90 -  __ movl(rdx, Address(rbx, itableOffsetEntry::offset_offset_in_bytes()));
   16.91 -
   16.92 -  // Compute itableMethodEntry.
   16.93 -  const int method_offset = (itableMethodEntry::size() * wordSize * vtable_index) + itableMethodEntry::method_offset_in_bytes();
   16.94 +  // Most registers are in use; we'll use rax, rbx, rsi, rdi
   16.95 +  // (If we need to make rsi, rdi callee-save, do a push/pop here.)
   16.96 +  const Register method = rbx;
   16.97 +  Label throw_icce;
   16.98  
   16.99    // Get methodOop and entrypoint for compiler
  16.100 -  const Register method = rbx;
  16.101 -  __ movptr(method, Address(rsi, rdx, Address::times_1, method_offset));
  16.102 -
  16.103 -  // Restore saved register, before possible trap.
  16.104 -  __ pop(rdx);
  16.105 +  __ lookup_interface_method(// inputs: rec. class, interface, itable index
  16.106 +                             rsi, rax, itable_index,
  16.107 +                             // outputs: method, scan temp. reg
  16.108 +                             method, rdi,
  16.109 +                             throw_icce);
  16.110  
  16.111    // method (rbx): methodOop
  16.112    // rcx: receiver
  16.113 @@ -187,12 +171,15 @@
  16.114    __ jmp(Address(method, methodOopDesc::from_compiled_offset()));
  16.115  
  16.116    __ bind(throw_icce);
  16.117 -  // Restore saved register
  16.118 -  __ pop(rdx);
  16.119    __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
  16.120 -
  16.121    masm->flush();
  16.122  
  16.123 +  if (PrintMiscellaneous && (WizardMode || Verbose)) {
  16.124 +    tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d",
  16.125 +                  itable_index, s->entry_point(),
  16.126 +                  (int)(s->code_end() - s->entry_point()),
  16.127 +                  (int)(s->code_end() - __ pc()));
  16.128 +  }
  16.129    guarantee(__ pc() <= s->code_end(), "overflowed buffer");
  16.130  
  16.131    s->set_exception_points(npe_addr, ame_addr);
  16.132 @@ -207,7 +194,7 @@
  16.133      return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0);
  16.134    } else {
  16.135      // Itable stub size
  16.136 -    return (DebugVtables ? 144 : 64) + (CountCompiledCalls ? 6 : 0);
  16.137 +    return (DebugVtables ? 256 : 66) + (CountCompiledCalls ? 6 : 0);
  16.138    }
  16.139  }
  16.140  
    17.1 --- a/src/cpu/x86/vm/vtableStubs_x86_64.cpp	Mon Mar 09 11:32:57 2009 -0400
    17.2 +++ b/src/cpu/x86/vm/vtableStubs_x86_64.cpp	Tue Mar 10 08:52:16 2009 -0700
    17.3 @@ -98,17 +98,26 @@
    17.4    __ jmp( Address(rbx, methodOopDesc::from_compiled_offset()));
    17.5  
    17.6    __ flush();
    17.7 +
    17.8 +  if (PrintMiscellaneous && (WizardMode || Verbose)) {
    17.9 +    tty->print_cr("vtable #%d at "PTR_FORMAT"[%d] left over: %d",
   17.10 +                  vtable_index, s->entry_point(),
   17.11 +                  (int)(s->code_end() - s->entry_point()),
   17.12 +                  (int)(s->code_end() - __ pc()));
   17.13 +  }
   17.14 +  guarantee(__ pc() <= s->code_end(), "overflowed buffer");
   17.15 +
   17.16    s->set_exception_points(npe_addr, ame_addr);
   17.17    return s;
   17.18  }
   17.19  
   17.20  
   17.21 -VtableStub* VtableStubs::create_itable_stub(int vtable_index) {
   17.22 +VtableStub* VtableStubs::create_itable_stub(int itable_index) {
   17.23    // Note well: pd_code_size_limit is the absolute minimum we can get
   17.24    // away with.  If you add code here, bump the code stub size
   17.25    // returned by pd_code_size_limit!
   17.26    const int amd64_code_length = VtableStub::pd_code_size_limit(false);
   17.27 -  VtableStub* s = new(amd64_code_length) VtableStub(false, vtable_index);
   17.28 +  VtableStub* s = new(amd64_code_length) VtableStub(false, itable_index);
   17.29    ResourceMark rm;
   17.30    CodeBuffer cb(s->entry_point(), amd64_code_length);
   17.31    MacroAssembler* masm = new MacroAssembler(&cb);
   17.32 @@ -131,68 +140,28 @@
   17.33    // get receiver klass (also an implicit null-check)
   17.34    address npe_addr = __ pc();
   17.35  
   17.36 -  __ load_klass(rbx, j_rarg0);
   17.37 +  // Most registers are in use; we'll use rax, rbx, r10, r11
   17.38 +  // (various calling sequences use r[cd]x, r[sd]i, r[89]; stay away from them)
   17.39 +  __ load_klass(r10, j_rarg0);
   17.40  
   17.41    // If we take a trap while this arg is on the stack we will not
   17.42    // be able to walk the stack properly. This is not an issue except
   17.43    // when there are mistakes in this assembly code that could generate
   17.44    // a spurious fault. Ask me how I know...
   17.45  
   17.46 -  __ push(j_rarg1);     // Most registers are in use, so save one
   17.47 -
   17.48 -  // compute itable entry offset (in words)
   17.49 -  const int base = instanceKlass::vtable_start_offset() * wordSize;
   17.50 -  assert(vtableEntry::size() * wordSize == 8,
   17.51 -         "adjust the scaling in the code below");
   17.52 -  // Get length of vtable
   17.53 -  __ movl(j_rarg1,
   17.54 -          Address(rbx, instanceKlass::vtable_length_offset() * wordSize));
   17.55 -  __ lea(rbx, Address(rbx, j_rarg1, Address::times_8, base));
   17.56 -
   17.57 -  if (HeapWordsPerLong > 1) {
   17.58 -    // Round up to align_object_offset boundary
   17.59 -    __ round_to(rbx, BytesPerLong);
   17.60 -  }
   17.61 -  Label hit, next, entry, throw_icce;
   17.62 -
   17.63 -  __ jmpb(entry);
   17.64 -
   17.65 -  __ bind(next);
   17.66 -  __ addptr(rbx, itableOffsetEntry::size() * wordSize);
   17.67 -
   17.68 -  __ bind(entry);
   17.69 -
   17.70 -  // If the entry is NULL then we've reached the end of the table
   17.71 -  // without finding the expected interface, so throw an exception
   17.72 -  __ movptr(j_rarg1, Address(rbx, itableOffsetEntry::interface_offset_in_bytes()));
   17.73 -  __ testptr(j_rarg1, j_rarg1);
   17.74 -  __ jcc(Assembler::zero, throw_icce);
   17.75 -  __ cmpptr(rax, j_rarg1);
   17.76 -  __ jccb(Assembler::notEqual, next);
   17.77 -
   17.78 -  // We found a hit, move offset into j_rarg1
   17.79 -  __ movl(j_rarg1, Address(rbx, itableOffsetEntry::offset_offset_in_bytes()));
   17.80 -
   17.81 -  // Compute itableMethodEntry
   17.82 -  const int method_offset =
   17.83 -    (itableMethodEntry::size() * wordSize * vtable_index) +
   17.84 -    itableMethodEntry::method_offset_in_bytes();
   17.85 +  const Register method = rbx;
   17.86 +  Label throw_icce;
   17.87  
   17.88    // Get methodOop and entrypoint for compiler
   17.89 -
   17.90 -  // Get klass pointer again
   17.91 -  __ load_klass(rax, j_rarg0);
   17.92 -
   17.93 -  const Register method = rbx;
   17.94 -  __ movptr(method, Address(rax, j_rarg1, Address::times_1, method_offset));
   17.95 -
   17.96 -  // Restore saved register, before possible trap.
   17.97 -  __ pop(j_rarg1);
   17.98 +  __ lookup_interface_method(// inputs: rec. class, interface, itable index
   17.99 +                             r10, rax, itable_index,
  17.100 +                             // outputs: method, scan temp. reg
  17.101 +                             method, r11,
  17.102 +                             throw_icce);
  17.103  
  17.104    // method (rbx): methodOop
  17.105    // j_rarg0: receiver
  17.106  
  17.107 -
  17.108  #ifdef ASSERT
  17.109    if (DebugVtables) {
  17.110      Label L2;
  17.111 @@ -211,12 +180,16 @@
  17.112    __ jmp(Address(method, methodOopDesc::from_compiled_offset()));
  17.113  
  17.114    __ bind(throw_icce);
  17.115 -  // Restore saved register
  17.116 -  __ pop(j_rarg1);
  17.117    __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
  17.118  
  17.119    __ flush();
  17.120  
  17.121 +  if (PrintMiscellaneous && (WizardMode || Verbose)) {
  17.122 +    tty->print_cr("itable #%d at "PTR_FORMAT"[%d] left over: %d",
  17.123 +                  itable_index, s->entry_point(),
  17.124 +                  (int)(s->code_end() - s->entry_point()),
  17.125 +                  (int)(s->code_end() - __ pc()));
  17.126 +  }
  17.127    guarantee(__ pc() <= s->code_end(), "overflowed buffer");
  17.128  
  17.129    s->set_exception_points(npe_addr, ame_addr);
  17.130 @@ -230,7 +203,7 @@
  17.131             (UseCompressedOops ? 16 : 0);  // 1 leaq can be 3 bytes + 1 long
  17.132    } else {
  17.133      // Itable stub size
  17.134 -    return (DebugVtables ? 636 : 72) + (CountCompiledCalls ? 13 : 0) +
  17.135 +    return (DebugVtables ? 512 : 72) + (CountCompiledCalls ? 13 : 0) +
  17.136             (UseCompressedOops ? 32 : 0);  // 2 leaqs
  17.137    }
  17.138  }
    18.1 --- a/src/cpu/x86/vm/x86_32.ad	Mon Mar 09 11:32:57 2009 -0400
    18.2 +++ b/src/cpu/x86/vm/x86_32.ad	Tue Mar 10 08:52:16 2009 -0700
    18.3 @@ -1,5 +1,5 @@
    18.4  //
    18.5 -// Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
    18.6 +// Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
    18.7  // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    18.8  //
    18.9  // This code is free software; you can redistribute it and/or modify it
   18.10 @@ -3126,14 +3126,12 @@
   18.11  
   18.12    enc_class movq_ld(regXD dst, memory mem) %{
   18.13      MacroAssembler _masm(&cbuf);
   18.14 -    Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
   18.15 -    __ movq(as_XMMRegister($dst$$reg), madr);
   18.16 +    __ movq($dst$$XMMRegister, $mem$$Address);
   18.17    %}
   18.18  
   18.19    enc_class movq_st(memory mem, regXD src) %{
   18.20      MacroAssembler _masm(&cbuf);
   18.21 -    Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
   18.22 -    __ movq(madr, as_XMMRegister($src$$reg));
   18.23 +    __ movq($mem$$Address, $src$$XMMRegister);
   18.24    %}
   18.25  
   18.26    enc_class pshufd_8x8(regX dst, regX src) %{
   18.27 @@ -3751,8 +3749,8 @@
   18.28      masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
   18.29  
   18.30      // Load first characters
   18.31 -    masm.load_unsigned_word(rcx, Address(rbx, 0));
   18.32 -    masm.load_unsigned_word(rdi, Address(rax, 0));
   18.33 +    masm.load_unsigned_short(rcx, Address(rbx, 0));
   18.34 +    masm.load_unsigned_short(rdi, Address(rax, 0));
   18.35  
   18.36      // Compare first characters
   18.37      masm.subl(rcx, rdi);
   18.38 @@ -3782,8 +3780,8 @@
   18.39  
   18.40      // Compare the rest of the characters
   18.41      masm.bind(WHILE_HEAD_LABEL);
   18.42 -    masm.load_unsigned_word(rcx, Address(rbx, rsi, Address::times_2, 0));
   18.43 -    masm.load_unsigned_word(rdi, Address(rax, rsi, Address::times_2, 0));
   18.44 +    masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0));
   18.45 +    masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0));
   18.46      masm.subl(rcx, rdi);
   18.47      masm.jcc(Assembler::notZero, POP_LABEL);
   18.48      masm.incrementl(rsi);
   18.49 @@ -3840,8 +3838,8 @@
   18.50      masm.jcc(Assembler::zero, COMPARE_LOOP_HDR);
   18.51  
   18.52      // Compare 2-byte "tail" at end of arrays
   18.53 -    masm.load_unsigned_word(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
   18.54 -    masm.load_unsigned_word(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
   18.55 +    masm.load_unsigned_short(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
   18.56 +    masm.load_unsigned_short(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
   18.57      masm.cmpl(tmp1Reg, tmp2Reg);
   18.58      masm.jcc(Assembler::notEqual, FALSE_LABEL);
   18.59      masm.testl(resultReg, resultReg);
   18.60 @@ -6396,21 +6394,94 @@
   18.61    match(Set dst (LoadB mem));
   18.62  
   18.63    ins_cost(125);
   18.64 -  format %{ "MOVSX8 $dst,$mem" %}
   18.65 -  opcode(0xBE, 0x0F);
   18.66 -  ins_encode( OpcS, OpcP, RegMem(dst,mem));
   18.67 -  ins_pipe( ialu_reg_mem );
   18.68 -%}
   18.69 -
   18.70 -// Load Byte (8bit UNsigned)
   18.71 -instruct loadUB(xRegI dst, memory mem, immI_255 bytemask) %{
   18.72 -  match(Set dst (AndI (LoadB mem) bytemask));
   18.73 +  format %{ "MOVSX8 $dst,$mem\t# byte" %}
   18.74 +
   18.75 +  ins_encode %{
   18.76 +    __ movsbl($dst$$Register, $mem$$Address);
   18.77 +  %}
   18.78 +
   18.79 +  ins_pipe(ialu_reg_mem);
   18.80 +%}
   18.81 +
   18.82 +// Load Byte (8bit signed) into Long Register
   18.83 +instruct loadB2L(eRegL dst, memory mem) %{
   18.84 +  match(Set dst (ConvI2L (LoadB mem)));
   18.85 +
   18.86 +  ins_cost(375);
   18.87 +  format %{ "MOVSX8 $dst.lo,$mem\t# byte -> long\n\t"
   18.88 +            "MOV    $dst.hi,$dst.lo\n\t"
   18.89 +            "SAR    $dst.hi,7" %}
   18.90 +
   18.91 +  ins_encode %{
   18.92 +    __ movsbl($dst$$Register, $mem$$Address);
   18.93 +    __ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register.
   18.94 +    __ sarl(HIGH_FROM_LOW($dst$$Register), 7); // 24+1 MSB are already signed extended.
   18.95 +  %}
   18.96 +
   18.97 +  ins_pipe(ialu_reg_mem);
   18.98 +%}
   18.99 +
  18.100 +// Load Unsigned Byte (8bit UNsigned)
  18.101 +instruct loadUB(xRegI dst, memory mem) %{
  18.102 +  match(Set dst (LoadUB mem));
  18.103  
  18.104    ins_cost(125);
  18.105 -  format %{ "MOVZX8 $dst,$mem" %}
  18.106 -  opcode(0xB6, 0x0F);
  18.107 -  ins_encode( OpcS, OpcP, RegMem(dst,mem));
  18.108 -  ins_pipe( ialu_reg_mem );
  18.109 +  format %{ "MOVZX8 $dst,$mem\t# ubyte -> int" %}
  18.110 +
  18.111 +  ins_encode %{
  18.112 +    __ movzbl($dst$$Register, $mem$$Address);
  18.113 +  %}
  18.114 +
  18.115 +  ins_pipe(ialu_reg_mem);
  18.116 +%}
  18.117 +
  18.118 +// Load Unsigned Byte (8 bit UNsigned) into Long Register
  18.119 +instruct loadUB2L(eRegL dst, memory mem)
  18.120 +%{
  18.121 +  match(Set dst (ConvI2L (LoadUB mem)));
  18.122 +
  18.123 +  ins_cost(250);
  18.124 +  format %{ "MOVZX8 $dst.lo,$mem\t# ubyte -> long\n\t"
  18.125 +            "XOR    $dst.hi,$dst.hi" %}
  18.126 +
  18.127 +  ins_encode %{
  18.128 +    __ movzbl($dst$$Register, $mem$$Address);
  18.129 +    __ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register));
  18.130 +  %}
  18.131 +
  18.132 +  ins_pipe(ialu_reg_mem);
  18.133 +%}
  18.134 +
  18.135 +// Load Short (16bit signed)
  18.136 +instruct loadS(eRegI dst, memory mem) %{
  18.137 +  match(Set dst (LoadS mem));
  18.138 +
  18.139 +  ins_cost(125);
  18.140 +  format %{ "MOVSX  $dst,$mem\t# short" %}
  18.141 +
  18.142 +  ins_encode %{
  18.143 +    __ movswl($dst$$Register, $mem$$Address);
  18.144 +  %}
  18.145 +
  18.146 +  ins_pipe(ialu_reg_mem);
  18.147 +%}
  18.148 +
  18.149 +// Load Short (16bit signed) into Long Register
  18.150 +instruct loadS2L(eRegL dst, memory mem) %{
  18.151 +  match(Set dst (ConvI2L (LoadS mem)));
  18.152 +
  18.153 +  ins_cost(375);
  18.154 +  format %{ "MOVSX  $dst.lo,$mem\t# short -> long\n\t"
  18.155 +            "MOV    $dst.hi,$dst.lo\n\t"
  18.156 +            "SAR    $dst.hi,15" %}
  18.157 +
  18.158 +  ins_encode %{
  18.159 +    __ movswl($dst$$Register, $mem$$Address);
  18.160 +    __ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register.
  18.161 +    __ sarl(HIGH_FROM_LOW($dst$$Register), 15); // 16+1 MSB are already signed extended.
  18.162 +  %}
  18.163 +
  18.164 +  ins_pipe(ialu_reg_mem);
  18.165  %}
  18.166  
  18.167  // Load Unsigned Short/Char (16bit unsigned)
  18.168 @@ -6418,10 +6489,30 @@
  18.169    match(Set dst (LoadUS mem));
  18.170  
  18.171    ins_cost(125);
  18.172 -  format %{ "MOVZX  $dst,$mem" %}
  18.173 -  opcode(0xB7, 0x0F);
  18.174 -  ins_encode( OpcS, OpcP, RegMem(dst,mem));
  18.175 -  ins_pipe( ialu_reg_mem );
  18.176 +  format %{ "MOVZX  $dst,$mem\t# ushort/char -> int" %}
  18.177 +
  18.178 +  ins_encode %{
  18.179 +    __ movzwl($dst$$Register, $mem$$Address);
  18.180 +  %}
  18.181 +
  18.182 +  ins_pipe(ialu_reg_mem);
  18.183 +%}
  18.184 +
  18.185 +// Load Unsigned Short/Char (16 bit UNsigned) into Long Register
  18.186 +instruct loadUS2L(eRegL dst, memory mem)
  18.187 +%{
  18.188 +  match(Set dst (ConvI2L (LoadUS mem)));
  18.189 +
  18.190 +  ins_cost(250);
  18.191 +  format %{ "MOVZX  $dst.lo,$mem\t# ushort/char -> long\n\t"
  18.192 +            "XOR    $dst.hi,$dst.hi" %}
  18.193 +
  18.194 +  ins_encode %{
  18.195 +    __ movzwl($dst$$Register, $mem$$Address);
  18.196 +    __ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register));
  18.197 +  %}
  18.198 +
  18.199 +  ins_pipe(ialu_reg_mem);
  18.200  %}
  18.201  
  18.202  // Load Integer
  18.203 @@ -6429,10 +6520,47 @@
  18.204    match(Set dst (LoadI mem));
  18.205  
  18.206    ins_cost(125);
  18.207 -  format %{ "MOV    $dst,$mem" %}
  18.208 -  opcode(0x8B);
  18.209 -  ins_encode( OpcP, RegMem(dst,mem));
  18.210 -  ins_pipe( ialu_reg_mem );
  18.211 +  format %{ "MOV    $dst,$mem\t# int" %}
  18.212 +
  18.213 +  ins_encode %{
  18.214 +    __ movl($dst$$Register, $mem$$Address);
  18.215 +  %}
  18.216 +
  18.217 +  ins_pipe(ialu_reg_mem);
  18.218 +%}
  18.219 +
  18.220 +// Load Integer into Long Register
  18.221 +instruct loadI2L(eRegL dst, memory mem) %{
  18.222 +  match(Set dst (ConvI2L (LoadI mem)));
  18.223 +
  18.224 +  ins_cost(375);
  18.225 +  format %{ "MOV    $dst.lo,$mem\t# int -> long\n\t"
  18.226 +            "MOV    $dst.hi,$dst.lo\n\t"
  18.227 +            "SAR    $dst.hi,31" %}
  18.228 +
  18.229 +  ins_encode %{
  18.230 +    __ movl($dst$$Register, $mem$$Address);
  18.231 +    __ movl(HIGH_FROM_LOW($dst$$Register), $dst$$Register); // This is always a different register.
  18.232 +    __ sarl(HIGH_FROM_LOW($dst$$Register), 31);
  18.233 +  %}
  18.234 +
  18.235 +  ins_pipe(ialu_reg_mem);
  18.236 +%}
  18.237 +
  18.238 +// Load Unsigned Integer into Long Register
  18.239 +instruct loadUI2L(eRegL dst, memory mem) %{
  18.240 +  match(Set dst (LoadUI2L mem));
  18.241 +
  18.242 +  ins_cost(250);
  18.243 +  format %{ "MOV    $dst.lo,$mem\t# uint -> long\n\t"
  18.244 +            "XOR    $dst.hi,$dst.hi" %}
  18.245 +
  18.246 +  ins_encode %{
  18.247 +    __ movl($dst$$Register, $mem$$Address);
  18.248 +    __ xorl(HIGH_FROM_LOW($dst$$Register), HIGH_FROM_LOW($dst$$Register));
  18.249 +  %}
  18.250 +
  18.251 +  ins_pipe(ialu_reg_mem);
  18.252  %}
  18.253  
  18.254  // Load Long.  Cannot clobber address while loading, so restrict address
  18.255 @@ -6442,11 +6570,17 @@
  18.256    match(Set dst (LoadL mem));
  18.257  
  18.258    ins_cost(250);
  18.259 -  format %{ "MOV    $dst.lo,$mem\n\t"
  18.260 +  format %{ "MOV    $dst.lo,$mem\t# long\n\t"
  18.261              "MOV    $dst.hi,$mem+4" %}
  18.262 -  opcode(0x8B, 0x8B);
  18.263 -  ins_encode( OpcP, RegMem(dst,mem), OpcS, RegMem_Hi(dst,mem));
  18.264 -  ins_pipe( ialu_reg_long_mem );
  18.265 +
  18.266 +  ins_encode %{
  18.267 +    Address Amemlo = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp, false);
  18.268 +    Address Amemhi = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp + 4, false);
  18.269 +    __ movl($dst$$Register, Amemlo);
  18.270 +    __ movl(HIGH_FROM_LOW($dst$$Register), Amemhi);
  18.271 +  %}
  18.272 +
  18.273 +  ins_pipe(ialu_reg_long_mem);
  18.274  %}
  18.275  
  18.276  // Volatile Load Long.  Must be atomic, so do 64-bit FILD
  18.277 @@ -6521,17 +6655,6 @@
  18.278    ins_pipe( ialu_reg_mem );
  18.279  %}
  18.280  
  18.281 -// Load Short (16bit signed)
  18.282 -instruct loadS(eRegI dst, memory mem) %{
  18.283 -  match(Set dst (LoadS mem));
  18.284 -
  18.285 -  ins_cost(125);
  18.286 -  format %{ "MOVSX  $dst,$mem" %}
  18.287 -  opcode(0xBF, 0x0F);
  18.288 -  ins_encode( OpcS, OpcP, RegMem(dst,mem));
  18.289 -  ins_pipe( ialu_reg_mem );
  18.290 -%}
  18.291 -
  18.292  // Load Double
  18.293  instruct loadD(regD dst, memory mem) %{
  18.294    predicate(UseSSE<=1);
  18.295 @@ -7957,7 +8080,7 @@
  18.296      __ xchgl(as_Register(EBX_enc), as_Register(ECX_enc));
  18.297      if( os::is_MP() )
  18.298        __ lock();
  18.299 -    __ cmpxchg8(Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp));
  18.300 +    __ cmpxchg8($mem$$Address);
  18.301      __ xchgl(as_Register(EBX_enc), as_Register(ECX_enc));
  18.302    %}
  18.303    ins_pipe( pipe_cmpxchg );
  18.304 @@ -11467,6 +11590,7 @@
  18.305  instruct convI2L_reg( eRegL dst, eRegI src, eFlagsReg cr) %{
  18.306    match(Set dst (ConvI2L src));
  18.307    effect(KILL cr);
  18.308 +  ins_cost(375);
  18.309    format %{ "MOV    $dst.lo,$src\n\t"
  18.310              "MOV    $dst.hi,$src\n\t"
  18.311              "SAR    $dst.hi,31" %}
  18.312 @@ -11478,6 +11602,7 @@
  18.313  instruct convI2L_reg_zex(eRegL dst, eRegI src, immL_32bits mask, eFlagsReg flags ) %{
  18.314    match(Set dst (AndL (ConvI2L src) mask) );
  18.315    effect( KILL flags );
  18.316 +  ins_cost(250);
  18.317    format %{ "MOV    $dst.lo,$src\n\t"
  18.318              "XOR    $dst.hi,$dst.hi" %}
  18.319    opcode(0x33); // XOR
  18.320 @@ -11489,6 +11614,7 @@
  18.321  instruct zerox_long(eRegL dst, eRegL src, immL_32bits mask, eFlagsReg flags ) %{
  18.322    match(Set dst (AndL src mask) );
  18.323    effect( KILL flags );
  18.324 +  ins_cost(250);
  18.325    format %{ "MOV    $dst.lo,$src.lo\n\t"
  18.326              "XOR    $dst.hi,$dst.hi\n\t" %}
  18.327    opcode(0x33); // XOR
    19.1 --- a/src/cpu/x86/vm/x86_64.ad	Mon Mar 09 11:32:57 2009 -0400
    19.2 +++ b/src/cpu/x86/vm/x86_64.ad	Tue Mar 10 08:52:16 2009 -0700
    19.3 @@ -1,5 +1,5 @@
    19.4  //
    19.5 -// Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
    19.6 +// Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
    19.7  // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    19.8  //
    19.9  // This code is free software; you can redistribute it and/or modify it
   19.10 @@ -3462,14 +3462,12 @@
   19.11  
   19.12    enc_class movq_ld(regD dst, memory mem) %{
   19.13      MacroAssembler _masm(&cbuf);
   19.14 -    Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
   19.15 -    __ movq(as_XMMRegister($dst$$reg), madr);
   19.16 +    __ movq($dst$$XMMRegister, $mem$$Address);
   19.17    %}
   19.18  
   19.19    enc_class movq_st(memory mem, regD src) %{
   19.20      MacroAssembler _masm(&cbuf);
   19.21 -    Address madr = Address::make_raw($mem$$base, $mem$$index, $mem$$scale, $mem$$disp);
   19.22 -    __ movq(madr, as_XMMRegister($src$$reg));
   19.23 +    __ movq($mem$$Address, $src$$XMMRegister);
   19.24    %}
   19.25  
   19.26    enc_class pshufd_8x8(regF dst, regF src) %{
   19.27 @@ -3765,8 +3763,8 @@
   19.28      masm.jcc(Assembler::zero, LENGTH_DIFF_LABEL);
   19.29  
   19.30      // Load first characters
   19.31 -    masm.load_unsigned_word(rcx, Address(rbx, 0));
   19.32 -    masm.load_unsigned_word(rdi, Address(rax, 0));
   19.33 +    masm.load_unsigned_short(rcx, Address(rbx, 0));
   19.34 +    masm.load_unsigned_short(rdi, Address(rax, 0));
   19.35  
   19.36      // Compare first characters
   19.37      masm.subl(rcx, rdi);
   19.38 @@ -3796,8 +3794,8 @@
   19.39  
   19.40      // Compare the rest of the characters
   19.41      masm.bind(WHILE_HEAD_LABEL);
   19.42 -    masm.load_unsigned_word(rcx, Address(rbx, rsi, Address::times_2, 0));
   19.43 -    masm.load_unsigned_word(rdi, Address(rax, rsi, Address::times_2, 0));
   19.44 +    masm.load_unsigned_short(rcx, Address(rbx, rsi, Address::times_2, 0));
   19.45 +    masm.load_unsigned_short(rdi, Address(rax, rsi, Address::times_2, 0));
   19.46      masm.subl(rcx, rdi);
   19.47      masm.jcc(Assembler::notZero, POP_LABEL);
   19.48      masm.increment(rsi);
   19.49 @@ -3854,8 +3852,8 @@
   19.50      masm.jcc(Assembler::zero, COMPARE_LOOP_HDR);
   19.51  
   19.52      // Compare 2-byte "tail" at end of arrays
   19.53 -    masm.load_unsigned_word(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
   19.54 -    masm.load_unsigned_word(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
   19.55 +    masm.load_unsigned_short(tmp1Reg, Address(ary1Reg, resultReg, Address::times_4, base_offset));
   19.56 +    masm.load_unsigned_short(tmp2Reg, Address(ary2Reg, resultReg, Address::times_4, base_offset));
   19.57      masm.cmpl(tmp1Reg, tmp2Reg);
   19.58      masm.jcc(Assembler::notEqual, FALSE_LABEL);
   19.59      masm.testl(resultReg, resultReg);
   19.60 @@ -6031,70 +6029,88 @@
   19.61  
   19.62    ins_cost(125);
   19.63    format %{ "movsbl  $dst, $mem\t# byte" %}
   19.64 -  opcode(0x0F, 0xBE);
   19.65 -  ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
   19.66 +
   19.67 +  ins_encode %{
   19.68 +    __ movsbl($dst$$Register, $mem$$Address);
   19.69 +  %}
   19.70 +
   19.71    ins_pipe(ialu_reg_mem);
   19.72  %}
   19.73  
   19.74 -// Load Byte (8 bit signed) into long
   19.75 -// instruct loadB2L(rRegL dst, memory mem)
   19.76 -// %{
   19.77 -//   match(Set dst (ConvI2L (LoadB mem)));
   19.78 -
   19.79 -//   ins_cost(125);
   19.80 -//   format %{ "movsbq  $dst, $mem\t# byte -> long" %}
   19.81 -//   opcode(0x0F, 0xBE);
   19.82 -//   ins_encode(REX_reg_mem_wide(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
   19.83 -//   ins_pipe(ialu_reg_mem);
   19.84 -// %}
   19.85 -
   19.86 -// Load Byte (8 bit UNsigned)
   19.87 -instruct loadUB(rRegI dst, memory mem, immI_255 bytemask)
   19.88 -%{
   19.89 -  match(Set dst (AndI (LoadB mem) bytemask));
   19.90 +// Load Byte (8 bit signed) into Long Register
   19.91 +instruct loadB2L(rRegL dst, memory mem)
   19.92 +%{
   19.93 +  match(Set dst (ConvI2L (LoadB mem)));
   19.94 +
   19.95 +  ins_cost(125);
   19.96 +  format %{ "movsbq  $dst, $mem\t# byte -> long" %}
   19.97 +
   19.98 +  ins_encode %{
   19.99 +    __ movsbq($dst$$Register, $mem$$Address);
  19.100 +  %}
  19.101 +
  19.102 +  ins_pipe(ialu_reg_mem);
  19.103 +%}
  19.104 +
  19.105 +// Load Unsigned Byte (8 bit UNsigned)
  19.106 +instruct loadUB(rRegI dst, memory mem)
  19.107 +%{
  19.108 +  match(Set dst (LoadUB mem));
  19.109  
  19.110    ins_cost(125);
  19.111    format %{ "movzbl  $dst, $mem\t# ubyte" %}
  19.112 -  opcode(0x0F, 0xB6);
  19.113 -  ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
  19.114 +
  19.115 +  ins_encode %{
  19.116 +    __ movzbl($dst$$Register, $mem$$Address);
  19.117 +  %}
  19.118 +
  19.119    ins_pipe(ialu_reg_mem);
  19.120  %}
  19.121  
  19.122 -// Load Byte (8 bit UNsigned) into long
  19.123 -// instruct loadUB2L(rRegL dst, memory mem, immI_255 bytemask)
  19.124 -// %{
  19.125 -//   match(Set dst (ConvI2L (AndI (LoadB mem) bytemask)));
  19.126 -
  19.127 -//   ins_cost(125);
  19.128 -//   format %{ "movzbl  $dst, $mem\t# ubyte -> long" %}
  19.129 -//   opcode(0x0F, 0xB6);
  19.130 -//   ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
  19.131 -//   ins_pipe(ialu_reg_mem);
  19.132 -// %}
  19.133 +// Load Unsigned Byte (8 bit UNsigned) into Long Register
  19.134 +instruct loadUB2L(rRegL dst, memory mem)
  19.135 +%{
  19.136 +  match(Set dst (ConvI2L (LoadUB mem)));
  19.137 +
  19.138 +  ins_cost(125);
  19.139 +  format %{ "movzbq  $dst, $mem\t# ubyte -> long" %}
  19.140 +
  19.141 +  ins_encode %{
  19.142 +    __ movzbq($dst$$Register, $mem$$Address);
  19.143 +  %}
  19.144 +
  19.145 +  ins_pipe(ialu_reg_mem);
  19.146 +%}
  19.147  
  19.148  // Load Short (16 bit signed)
  19.149  instruct loadS(rRegI dst, memory mem)
  19.150  %{
  19.151    match(Set dst (LoadS mem));
  19.152  
  19.153 -  ins_cost(125); // XXX
  19.154 +  ins_cost(125);
  19.155    format %{ "movswl $dst, $mem\t# short" %}
  19.156 -  opcode(0x0F, 0xBF);
  19.157 -  ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
  19.158 +
  19.159 +  ins_encode %{
  19.160 +    __ movswl($dst$$Register, $mem$$Address);
  19.161 +  %}
  19.162 +
  19.163    ins_pipe(ialu_reg_mem);
  19.164  %}
  19.165  
  19.166 -// Load Short (16 bit signed) into long
  19.167 -// instruct loadS2L(rRegL dst, memory mem)
  19.168 -// %{
  19.169 -//   match(Set dst (ConvI2L (LoadS mem)));
  19.170 -
  19.171 -//   ins_cost(125); // XXX
  19.172 -//   format %{ "movswq $dst, $mem\t# short -> long" %}
  19.173 -//   opcode(0x0F, 0xBF);
  19.174 -//   ins_encode(REX_reg_mem_wide(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
  19.175 -//   ins_pipe(ialu_reg_mem);
  19.176 -// %}
  19.177 +// Load Short (16 bit signed) into Long Register
  19.178 +instruct loadS2L(rRegL dst, memory mem)
  19.179 +%{
  19.180 +  match(Set dst (ConvI2L (LoadS mem)));
  19.181 +
  19.182 +  ins_cost(125);
  19.183 +  format %{ "movswq $dst, $mem\t# short -> long" %}
  19.184 +
  19.185 +  ins_encode %{
  19.186 +    __ movswq($dst$$Register, $mem$$Address);
  19.187 +  %}
  19.188 +
  19.189 +  ins_pipe(ialu_reg_mem);
  19.190 +%}
  19.191  
  19.192  // Load Unsigned Short/Char (16 bit UNsigned)
  19.193  instruct loadUS(rRegI dst, memory mem)
  19.194 @@ -6103,32 +6119,71 @@
  19.195  
  19.196    ins_cost(125);
  19.197    format %{ "movzwl  $dst, $mem\t# ushort/char" %}
  19.198 -  opcode(0x0F, 0xB7);
  19.199 -  ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
  19.200 +
  19.201 +  ins_encode %{
  19.202 +    __ movzwl($dst$$Register, $mem$$Address);
  19.203 +  %}
  19.204 +
  19.205    ins_pipe(ialu_reg_mem);
  19.206  %}
  19.207  
  19.208 -// Load Unsigned Short/Char (16 bit UNsigned) into long
  19.209 -// instruct loadUS2L(rRegL dst, memory mem)
  19.210 -// %{
  19.211 -//   match(Set dst (ConvI2L (LoadUS mem)));
  19.212 -
  19.213 -//   ins_cost(125);
  19.214 -//   format %{ "movzwl  $dst, $mem\t# ushort/char -> long" %}
  19.215 -//   opcode(0x0F, 0xB7);
  19.216 -//   ins_encode(REX_reg_mem(dst, mem), OpcP, OpcS, reg_mem(dst, mem));
  19.217 -//   ins_pipe(ialu_reg_mem);
  19.218 -// %}
  19.219 +// Load Unsigned Short/Char (16 bit UNsigned) into Long Register
  19.220 +instruct loadUS2L(rRegL dst, memory mem)
  19.221 +%{
  19.222 +  match(Set dst (ConvI2L (LoadUS mem)));
  19.223 +
  19.224 +  ins_cost(125);
  19.225 +  format %{ "movzwq  $dst, $mem\t# ushort/char -> long" %}
  19.226 +
  19.227 +  ins_encode %{
  19.228 +    __ movzwq($dst$$Register, $mem$$Address);
  19.229 +  %}
  19.230 +
  19.231 +  ins_pipe(ialu_reg_mem);
  19.232 +%}
  19.233  
  19.234  // Load Integer
  19.235  instruct loadI(rRegI dst, memory mem)
  19.236  %{
  19.237    match(Set dst (LoadI mem));
  19.238  
  19.239 -  ins_cost(125); // XXX
  19.240 +  ins_cost(125);
  19.241    format %{ "movl    $dst, $mem\t# int" %}
  19.242 -  opcode(0x8B);
  19.243 -  ins_encode(REX_reg_mem(dst, mem), OpcP, reg_mem(dst, mem));
  19.244 +
  19.245 +  ins_encode %{
  19.246 +    __ movl($dst$$Register, $mem$$Address);
  19.247 +  %}
  19.248 +
  19.249 +  ins_pipe(ialu_reg_mem);
  19.250 +%}
  19.251 +
  19.252 +// Load Integer into Long Register
  19.253 +instruct loadI2L(rRegL dst, memory mem)
  19.254 +%{
  19.255 +  match(Set dst (ConvI2L (LoadI mem)));
  19.256 +
  19.257 +  ins_cost(125);
  19.258 +  format %{ "movslq  $dst, $mem\t# int -> long" %}
  19.259 +
  19.260 +  ins_encode %{
  19.261 +    __ movslq($dst$$Register, $mem$$Address);
  19.262 +  %}
  19.263 +
  19.264 +  ins_pipe(ialu_reg_mem);
  19.265 +%}
  19.266 +
  19.267 +// Load Unsigned Integer into Long Register
  19.268 +instruct loadUI2L(rRegL dst, memory mem)
  19.269 +%{
  19.270 +  match(Set dst (LoadUI2L mem));
  19.271 +
  19.272 +  ins_cost(125);
  19.273 +  format %{ "movl    $dst, $mem\t# uint -> long" %}
  19.274 +
  19.275 +  ins_encode %{
  19.276 +    __ movl($dst$$Register, $mem$$Address);
  19.277 +  %}
  19.278 +
  19.279    ins_pipe(ialu_reg_mem);
  19.280  %}
  19.281  
  19.282 @@ -6137,10 +6192,13 @@
  19.283  %{
  19.284    match(Set dst (LoadL mem));
  19.285  
  19.286 -  ins_cost(125); // XXX
  19.287 +  ins_cost(125);
  19.288    format %{ "movq    $dst, $mem\t# long" %}
  19.289 -  opcode(0x8B);
  19.290 -  ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem));
  19.291 +
  19.292 +  ins_encode %{
  19.293 +    __ movq($dst$$Register, $mem$$Address);
  19.294 +  %}
  19.295 +
  19.296    ins_pipe(ialu_reg_mem); // XXX
  19.297  %}
  19.298  
  19.299 @@ -10804,16 +10862,6 @@
  19.300  //   ins_pipe(ialu_reg_reg);
  19.301  // %}
  19.302  
  19.303 -instruct convI2L_reg_mem(rRegL dst, memory src)
  19.304 -%{
  19.305 -  match(Set dst (ConvI2L (LoadI src)));
  19.306 -
  19.307 -  format %{ "movslq  $dst, $src\t# i2l" %}
  19.308 -  opcode(0x63); // needs REX.W
  19.309 -  ins_encode(REX_reg_mem_wide(dst, src), OpcP, reg_mem(dst,src));
  19.310 -  ins_pipe(ialu_reg_mem);
  19.311 -%}
  19.312 -
  19.313  // Zero-extend convert int to long
  19.314  instruct convI2L_reg_reg_zex(rRegL dst, rRegI src, immL_32bits mask)
  19.315  %{
    20.1 --- a/src/share/vm/adlc/forms.cpp	Mon Mar 09 11:32:57 2009 -0400
    20.2 +++ b/src/share/vm/adlc/forms.cpp	Tue Mar 10 08:52:16 2009 -0700
    20.3 @@ -70,6 +70,7 @@
    20.4    else return (_iter <_cur-1 ? _names[++_iter] : NULL);
    20.5  }
    20.6  const char  *NameList::current() { return (_iter < _cur ? _names[_iter] : NULL); }
    20.7 +const char  *NameList::peek(int skip) { return (_iter + skip < _cur ? _names[_iter + skip] : NULL); }
    20.8  
    20.9  // Return 'true' if current entry is signal
   20.10  bool  NameList::current_is_signal() {
   20.11 @@ -248,11 +249,13 @@
   20.12  // True if 'opType', an ideal name, loads or stores.
   20.13  Form::DataType Form::is_load_from_memory(const char *opType) const {
   20.14    if( strcmp(opType,"LoadB")==0 )  return Form::idealB;
   20.15 +  if( strcmp(opType,"LoadUB")==0 )  return Form::idealB;
   20.16    if( strcmp(opType,"LoadUS")==0 )  return Form::idealC;
   20.17    if( strcmp(opType,"LoadD")==0 )  return Form::idealD;
   20.18    if( strcmp(opType,"LoadD_unaligned")==0 )  return Form::idealD;
   20.19    if( strcmp(opType,"LoadF")==0 )  return Form::idealF;
   20.20    if( strcmp(opType,"LoadI")==0 )  return Form::idealI;
   20.21 +  if( strcmp(opType,"LoadUI2L")==0 )  return Form::idealI;
   20.22    if( strcmp(opType,"LoadKlass")==0 )  return Form::idealP;
   20.23    if( strcmp(opType,"LoadNKlass")==0 ) return Form::idealN;
   20.24    if( strcmp(opType,"LoadL")==0 )  return Form::idealL;
    21.1 --- a/src/share/vm/adlc/forms.hpp	Mon Mar 09 11:32:57 2009 -0400
    21.2 +++ b/src/share/vm/adlc/forms.hpp	Tue Mar 10 08:52:16 2009 -0700
    21.3 @@ -342,6 +342,7 @@
    21.4    void  reset();                   // Reset iteration
    21.5    const char *iter();              // after reset(), first element : else next
    21.6    const char *current();           // return current element in iteration.
    21.7 +  const char *peek(int skip = 1);  // returns element + skip in iteration if there is one
    21.8  
    21.9    bool  current_is_signal();       // Return 'true' if current entry is signal
   21.10    bool  is_signal(const char *entry); // Return true if entry is a signal
    22.1 --- a/src/share/vm/adlc/formssel.cpp	Mon Mar 09 11:32:57 2009 -0400
    22.2 +++ b/src/share/vm/adlc/formssel.cpp	Tue Mar 10 08:52:16 2009 -0700
    22.3 @@ -3310,8 +3310,8 @@
    22.4    static const char *needs_ideal_memory_list[] = {
    22.5      "StoreI","StoreL","StoreP","StoreN","StoreD","StoreF" ,
    22.6      "StoreB","StoreC","Store" ,"StoreFP",
    22.7 -    "LoadI" ,"LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF"  ,
    22.8 -    "LoadB" ,"LoadUS" ,"LoadS" ,"Load"   ,
    22.9 +    "LoadI", "LoadUI2L", "LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF"  ,
   22.10 +    "LoadB" , "LoadUB", "LoadUS" ,"LoadS" ,"Load"   ,
   22.11      "Store4I","Store2I","Store2L","Store2D","Store4F","Store2F","Store16B",
   22.12      "Store8B","Store4B","Store8C","Store4C","Store2C",
   22.13      "Load4I" ,"Load2I" ,"Load2L" ,"Load2D" ,"Load4F" ,"Load2F" ,"Load16B" ,
   22.14 @@ -3431,10 +3431,16 @@
   22.15      const InstructForm *form2_inst = form2 ? form2->is_instruction() : NULL;
   22.16      const char *name_left  = mRule2->_lChild ? mRule2->_lChild->_opType : NULL;
   22.17      const char *name_right = mRule2->_rChild ? mRule2->_rChild->_opType : NULL;
   22.18 +    DataType data_type = Form::none;
   22.19 +    if (form->is_operand()) {
   22.20 +      // Make sure the loadX matches the type of the reg
   22.21 +      data_type = form->ideal_to_Reg_type(form->is_operand()->ideal_type(globals));
   22.22 +    }
   22.23      // Detect reg vs (loadX memory)
   22.24      if( form->is_cisc_reg(globals)
   22.25          && form2_inst
   22.26 -        && (is_load_from_memory(mRule2->_opType) != Form::none) // reg vs. (load memory)
   22.27 +        && data_type != Form::none
   22.28 +        && (is_load_from_memory(mRule2->_opType) == data_type) // reg vs. (load memory)
   22.29          && (name_left != NULL)       // NOT (load)
   22.30          && (name_right == NULL) ) {  // NOT (load memory foo)
   22.31        const Form *form2_left = name_left ? globals[name_left] : NULL;
    23.1 --- a/src/share/vm/adlc/output_c.cpp	Mon Mar 09 11:32:57 2009 -0400
    23.2 +++ b/src/share/vm/adlc/output_c.cpp	Tue Mar 10 08:52:16 2009 -0700
    23.3 @@ -2139,8 +2139,59 @@
    23.4          // A subfield variable, '$$' prefix
    23.5          emit_field( rep_var );
    23.6        } else {
    23.7 -        // A replacement variable, '$' prefix
    23.8 -        emit_rep_var( rep_var );
    23.9 +        if (_strings_to_emit.peek() != NULL &&
   23.10 +            strcmp(_strings_to_emit.peek(), "$Address") == 0) {
   23.11 +          fprintf(_fp, "Address::make_raw(");
   23.12 +
   23.13 +          emit_rep_var( rep_var );
   23.14 +          fprintf(_fp,"->base(ra_,this,idx%d), ", _operand_idx);
   23.15 +
   23.16 +          _reg_status = LITERAL_ACCESSED;
   23.17 +          emit_rep_var( rep_var );
   23.18 +          fprintf(_fp,"->index(ra_,this,idx%d), ", _operand_idx);
   23.19 +
   23.20 +          _reg_status = LITERAL_ACCESSED;
   23.21 +          emit_rep_var( rep_var );
   23.22 +          fprintf(_fp,"->scale(), ");
   23.23 +
   23.24 +          _reg_status = LITERAL_ACCESSED;
   23.25 +          emit_rep_var( rep_var );
   23.26 +          Form::DataType stack_type = _operand ? _operand->is_user_name_for_sReg() : Form::none;
   23.27 +          if( _operand  && _operand_idx==0 && stack_type != Form::none ) {
   23.28 +            fprintf(_fp,"->disp(ra_,this,0), ");
   23.29 +          } else {
   23.30 +            fprintf(_fp,"->disp(ra_,this,idx%d), ", _operand_idx);
   23.31 +          }
   23.32 +
   23.33 +          _reg_status = LITERAL_ACCESSED;
   23.34 +          emit_rep_var( rep_var );
   23.35 +          fprintf(_fp,"->disp_is_oop())");
   23.36 +
   23.37 +          // skip trailing $Address
   23.38 +          _strings_to_emit.iter();
   23.39 +        } else {
   23.40 +          // A replacement variable, '$' prefix
   23.41 +          const char* next = _strings_to_emit.peek();
   23.42 +          const char* next2 = _strings_to_emit.peek(2);
   23.43 +          if (next != NULL && next2 != NULL && strcmp(next2, "$Register") == 0 &&
   23.44 +              (strcmp(next, "$base") == 0 || strcmp(next, "$index") == 0)) {
   23.45 +            // handle $rev_var$$base$$Register and $rev_var$$index$$Register by
   23.46 +            // producing as_Register(opnd_array(#)->base(ra_,this,idx1)).
   23.47 +            fprintf(_fp, "as_Register(");
   23.48 +            // emit the operand reference
   23.49 +            emit_rep_var( rep_var );
   23.50 +            rep_var = _strings_to_emit.iter();
   23.51 +            assert(strcmp(rep_var, "$base") == 0 || strcmp(rep_var, "$index") == 0, "bad pattern");
   23.52 +            // handle base or index
   23.53 +            emit_field(rep_var);
   23.54 +            rep_var = _strings_to_emit.iter();
   23.55 +            assert(strcmp(rep_var, "$Register") == 0, "bad pattern");
   23.56 +            // close up the parens
   23.57 +            fprintf(_fp, ")");
   23.58 +          } else {
   23.59 +            emit_rep_var( rep_var );
   23.60 +          }
   23.61 +        }
   23.62        } // end replacement and/or subfield
   23.63      }
   23.64    }
    24.1 --- a/src/share/vm/asm/assembler.cpp	Mon Mar 09 11:32:57 2009 -0400
    24.2 +++ b/src/share/vm/asm/assembler.cpp	Tue Mar 10 08:52:16 2009 -0700
    24.3 @@ -239,6 +239,78 @@
    24.4    }
    24.5  }
    24.6  
    24.7 +struct DelayedConstant {
    24.8 +  typedef void (*value_fn_t)();
    24.9 +  BasicType type;
   24.10 +  intptr_t value;
   24.11 +  value_fn_t value_fn;
   24.12 +  // This limit of 20 is generous for initial uses.
   24.13 +  // The limit needs to be large enough to store the field offsets
   24.14 +  // into classes which do not have statically fixed layouts.
   24.15 +  // (Initial use is for method handle object offsets.)
   24.16 +  // Look for uses of "delayed_value" in the source code
   24.17 +  // and make sure this number is generous enough to handle all of them.
   24.18 +  enum { DC_LIMIT = 20 };
   24.19 +  static DelayedConstant delayed_constants[DC_LIMIT];
   24.20 +  static DelayedConstant* add(BasicType type, value_fn_t value_fn);
   24.21 +  bool match(BasicType t, value_fn_t cfn) {
   24.22 +    return type == t && value_fn == cfn;
   24.23 +  }
   24.24 +  static void update_all();
   24.25 +};
   24.26 +
   24.27 +DelayedConstant DelayedConstant::delayed_constants[DC_LIMIT];
   24.28 +// Default C structure initialization rules have the following effect here:
   24.29 +// = { { (BasicType)0, (intptr_t)NULL }, ... };
   24.30 +
   24.31 +DelayedConstant* DelayedConstant::add(BasicType type,
   24.32 +                                      DelayedConstant::value_fn_t cfn) {
   24.33 +  for (int i = 0; i < DC_LIMIT; i++) {
   24.34 +    DelayedConstant* dcon = &delayed_constants[i];
   24.35 +    if (dcon->match(type, cfn))
   24.36 +      return dcon;
   24.37 +    if (dcon->value_fn == NULL) {
   24.38 +      // (cmpxchg not because this is multi-threaded but because I'm paranoid)
   24.39 +      if (Atomic::cmpxchg_ptr(CAST_FROM_FN_PTR(void*, cfn), &dcon->value_fn, NULL) == NULL) {
   24.40 +        dcon->type = type;
   24.41 +        return dcon;
   24.42 +      }
   24.43 +    }
   24.44 +  }
   24.45 +  // If this assert is hit (in pre-integration testing!) then re-evaluate
   24.46 +  // the comment on the definition of DC_LIMIT.
   24.47 +  guarantee(false, "too many delayed constants");
   24.48 +  return NULL;
   24.49 +}
   24.50 +
   24.51 +void DelayedConstant::update_all() {
   24.52 +  for (int i = 0; i < DC_LIMIT; i++) {
   24.53 +    DelayedConstant* dcon = &delayed_constants[i];
   24.54 +    if (dcon->value_fn != NULL && dcon->value == 0) {
   24.55 +      typedef int     (*int_fn_t)();
   24.56 +      typedef address (*address_fn_t)();
   24.57 +      switch (dcon->type) {
   24.58 +      case T_INT:     dcon->value = (intptr_t) ((int_fn_t)    dcon->value_fn)(); break;
   24.59 +      case T_ADDRESS: dcon->value = (intptr_t) ((address_fn_t)dcon->value_fn)(); break;
   24.60 +      }
   24.61 +    }
   24.62 +  }
   24.63 +}
   24.64 +
   24.65 +intptr_t* AbstractAssembler::delayed_value_addr(int(*value_fn)()) {
   24.66 +  DelayedConstant* dcon = DelayedConstant::add(T_INT, (DelayedConstant::value_fn_t) value_fn);
   24.67 +  return &dcon->value;
   24.68 +}
   24.69 +intptr_t* AbstractAssembler::delayed_value_addr(address(*value_fn)()) {
   24.70 +  DelayedConstant* dcon = DelayedConstant::add(T_ADDRESS, (DelayedConstant::value_fn_t) value_fn);
   24.71 +  return &dcon->value;
   24.72 +}
   24.73 +void AbstractAssembler::update_delayed_values() {
   24.74 +  DelayedConstant::update_all();
   24.75 +}
   24.76 +
   24.77 +
   24.78 +
   24.79  
   24.80  void AbstractAssembler::block_comment(const char* comment) {
   24.81    if (sect() == CodeBuffer::SECT_INSTS) {
    25.1 --- a/src/share/vm/asm/assembler.hpp	Mon Mar 09 11:32:57 2009 -0400
    25.2 +++ b/src/share/vm/asm/assembler.hpp	Tue Mar 10 08:52:16 2009 -0700
    25.3 @@ -140,6 +140,28 @@
    25.4    }
    25.5  };
    25.6  
    25.7 +// A union type for code which has to assemble both constant and
    25.8 +// non-constant operands, when the distinction cannot be made
    25.9 +// statically.
   25.10 +class RegisterConstant VALUE_OBJ_CLASS_SPEC {
   25.11 + private:
   25.12 +  Register _r;
   25.13 +  intptr_t _c;
   25.14 +
   25.15 + public:
   25.16 +  RegisterConstant(): _r(noreg), _c(0) {}
   25.17 +  RegisterConstant(Register r): _r(r), _c(0) {}
   25.18 +  RegisterConstant(intptr_t c): _r(noreg), _c(c) {}
   25.19 +
   25.20 +  Register as_register() const { assert(is_register(),""); return _r; }
   25.21 +  intptr_t as_constant() const { assert(is_constant(),""); return _c; }
   25.22 +
   25.23 +  Register register_or_noreg() const { return _r; }
   25.24 +  intptr_t constant_or_zero() const  { return _c; }
   25.25 +
   25.26 +  bool is_register() const { return _r != noreg; }
   25.27 +  bool is_constant() const { return _r == noreg; }
   25.28 +};
   25.29  
   25.30  // The Abstract Assembler: Pure assembler doing NO optimizations on the
   25.31  // instruction level; i.e., what you write is what you get.
   25.32 @@ -280,6 +302,26 @@
   25.33    inline address address_constant(Label& L);
   25.34    inline address address_table_constant(GrowableArray<Label*> label);
   25.35  
   25.36 +  // Bootstrapping aid to cope with delayed determination of constants.
   25.37 +  // Returns a static address which will eventually contain the constant.
   25.38 +  // The value zero (NULL) stands instead of a constant which is still uncomputed.
   25.39 +  // Thus, the eventual value of the constant must not be zero.
   25.40 +  // This is fine, since this is designed for embedding object field
   25.41 +  // offsets in code which must be generated before the object class is loaded.
   25.42 +  // Field offsets are never zero, since an object's header (mark word)
   25.43 +  // is located at offset zero.
   25.44 +  RegisterConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0) {
   25.45 +    return delayed_value(delayed_value_addr(value_fn), tmp, offset);
   25.46 +  }
   25.47 +  RegisterConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0) {
   25.48 +    return delayed_value(delayed_value_addr(value_fn), tmp, offset);
   25.49 +  }
   25.50 +  virtual RegisterConstant delayed_value(intptr_t* delayed_value_addr, Register tmp, int offset) = 0;
   25.51 +  // Last overloading is platform-dependent; look in assembler_<arch>.cpp.
   25.52 +  static intptr_t* delayed_value_addr(int(*constant_fn)());
   25.53 +  static intptr_t* delayed_value_addr(address(*constant_fn)());
   25.54 +  static void update_delayed_values();
   25.55 +
   25.56    // Bang stack to trigger StackOverflowError at a safe location
   25.57    // implementation delegates to machine-specific bang_stack_with_offset
   25.58    void generate_stack_overflow_check( int frame_size_in_bytes );
    26.1 --- a/src/share/vm/opto/classes.hpp	Mon Mar 09 11:32:57 2009 -0400
    26.2 +++ b/src/share/vm/opto/classes.hpp	Tue Mar 10 08:52:16 2009 -0700
    26.3 @@ -1,5 +1,5 @@
    26.4  /*
    26.5 - * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
    26.6 + * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
    26.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    26.8   *
    26.9   * This code is free software; you can redistribute it and/or modify it
   26.10 @@ -129,11 +129,13 @@
   26.11  macro(LShiftI)
   26.12  macro(LShiftL)
   26.13  macro(LoadB)
   26.14 +macro(LoadUB)
   26.15  macro(LoadUS)
   26.16  macro(LoadD)
   26.17  macro(LoadD_unaligned)
   26.18  macro(LoadF)
   26.19  macro(LoadI)
   26.20 +macro(LoadUI2L)
   26.21  macro(LoadKlass)
   26.22  macro(LoadNKlass)
   26.23  macro(LoadL)
    27.1 --- a/src/share/vm/opto/compile.cpp	Mon Mar 09 11:32:57 2009 -0400
    27.2 +++ b/src/share/vm/opto/compile.cpp	Tue Mar 10 08:52:16 2009 -0700
    27.3 @@ -1,5 +1,5 @@
    27.4  /*
    27.5 - * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
    27.6 + * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
    27.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    27.8   *
    27.9   * This code is free software; you can redistribute it and/or modify it
   27.10 @@ -2005,8 +2005,10 @@
   27.11    case Op_StoreP:
   27.12    case Op_StoreN:
   27.13    case Op_LoadB:
   27.14 +  case Op_LoadUB:
   27.15    case Op_LoadUS:
   27.16    case Op_LoadI:
   27.17 +  case Op_LoadUI2L:
   27.18    case Op_LoadKlass:
   27.19    case Op_LoadNKlass:
   27.20    case Op_LoadL:
    28.1 --- a/src/share/vm/opto/gcm.cpp	Mon Mar 09 11:32:57 2009 -0400
    28.2 +++ b/src/share/vm/opto/gcm.cpp	Tue Mar 10 08:52:16 2009 -0700
    28.3 @@ -1901,7 +1901,8 @@
    28.4    for (int i = 0; i < _members.length(); i++) {
    28.5      CFGElement* s = _members.at(i);
    28.6      float block_freq = s->_freq * loop_freq;
    28.7 -    if (block_freq < MIN_BLOCK_FREQUENCY) block_freq = MIN_BLOCK_FREQUENCY;
    28.8 +    if (g_isnan(block_freq) || block_freq < MIN_BLOCK_FREQUENCY)
    28.9 +      block_freq = MIN_BLOCK_FREQUENCY;
   28.10      s->_freq = block_freq;
   28.11    }
   28.12    CFGLoop* ch = _child;
    29.1 --- a/src/share/vm/opto/memnode.cpp	Mon Mar 09 11:32:57 2009 -0400
    29.2 +++ b/src/share/vm/opto/memnode.cpp	Tue Mar 10 08:52:16 2009 -0700
    29.3 @@ -1,5 +1,5 @@
    29.4  /*
    29.5 - * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
    29.6 + * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
    29.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    29.8   *
    29.9   * This code is free software; you can redistribute it and/or modify it
   29.10 @@ -778,7 +778,7 @@
   29.11             adr_type->offset() == arrayOopDesc::length_offset_in_bytes()),
   29.12           "use LoadRangeNode instead");
   29.13    switch (bt) {
   29.14 -  case T_BOOLEAN:
   29.15 +  case T_BOOLEAN: return new (C, 3) LoadUBNode(ctl, mem, adr, adr_type, rt->is_int()    );
   29.16    case T_BYTE:    return new (C, 3) LoadBNode (ctl, mem, adr, adr_type, rt->is_int()    );
   29.17    case T_INT:     return new (C, 3) LoadINode (ctl, mem, adr, adr_type, rt->is_int()    );
   29.18    case T_CHAR:    return new (C, 3) LoadUSNode(ctl, mem, adr, adr_type, rt->is_int()    );
   29.19 @@ -1616,6 +1616,22 @@
   29.20    return LoadNode::Ideal(phase, can_reshape);
   29.21  }
   29.22  
   29.23 +//--------------------------LoadUBNode::Ideal-------------------------------------
   29.24 +//
   29.25 +//  If the previous store is to the same address as this load,
   29.26 +//  and the value stored was larger than a byte, replace this load
   29.27 +//  with the value stored truncated to a byte.  If no truncation is
   29.28 +//  needed, the replacement is done in LoadNode::Identity().
   29.29 +//
   29.30 +Node* LoadUBNode::Ideal(PhaseGVN* phase, bool can_reshape) {
   29.31 +  Node* mem = in(MemNode::Memory);
   29.32 +  Node* value = can_see_stored_value(mem, phase);
   29.33 +  if (value && !phase->type(value)->higher_equal(_type))
   29.34 +    return new (phase->C, 3) AndINode(value, phase->intcon(0xFF));
   29.35 +  // Identity call will handle the case where truncation is not needed.
   29.36 +  return LoadNode::Ideal(phase, can_reshape);
   29.37 +}
   29.38 +
   29.39  //--------------------------LoadUSNode::Ideal-------------------------------------
   29.40  //
   29.41  //  If the previous store is to the same address as this load,
    30.1 --- a/src/share/vm/opto/memnode.hpp	Mon Mar 09 11:32:57 2009 -0400
    30.2 +++ b/src/share/vm/opto/memnode.hpp	Tue Mar 10 08:52:16 2009 -0700
    30.3 @@ -1,5 +1,5 @@
    30.4  /*
    30.5 - * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
    30.6 + * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
    30.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    30.8   *
    30.9   * This code is free software; you can redistribute it and/or modify it
   30.10 @@ -207,6 +207,19 @@
   30.11    virtual BasicType memory_type() const { return T_BYTE; }
   30.12  };
   30.13  
   30.14 +//------------------------------LoadUBNode-------------------------------------
   30.15 +// Load a unsigned byte (8bits unsigned) from memory
   30.16 +class LoadUBNode : public LoadNode {
   30.17 +public:
   30.18 +  LoadUBNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeInt* ti = TypeInt::UBYTE )
   30.19 +    : LoadNode(c, mem, adr, at, ti) {}
   30.20 +  virtual int Opcode() const;
   30.21 +  virtual uint ideal_reg() const { return Op_RegI; }
   30.22 +  virtual Node* Ideal(PhaseGVN *phase, bool can_reshape);
   30.23 +  virtual int store_Opcode() const { return Op_StoreB; }
   30.24 +  virtual BasicType memory_type() const { return T_BYTE; }
   30.25 +};
   30.26 +
   30.27  //------------------------------LoadUSNode-------------------------------------
   30.28  // Load an unsigned short/char (16bits unsigned) from memory
   30.29  class LoadUSNode : public LoadNode {
   30.30 @@ -232,6 +245,18 @@
   30.31    virtual BasicType memory_type() const { return T_INT; }
   30.32  };
   30.33  
   30.34 +//------------------------------LoadUI2LNode-----------------------------------
   30.35 +// Load an unsigned integer into long from memory
   30.36 +class LoadUI2LNode : public LoadNode {
   30.37 +public:
   30.38 +  LoadUI2LNode(Node* c, Node* mem, Node* adr, const TypePtr* at, const TypeLong* t = TypeLong::UINT)
   30.39 +    : LoadNode(c, mem, adr, at, t) {}
   30.40 +  virtual int Opcode() const;
   30.41 +  virtual uint ideal_reg() const { return Op_RegL; }
   30.42 +  virtual int store_Opcode() const { return Op_StoreL; }
   30.43 +  virtual BasicType memory_type() const { return T_LONG; }
   30.44 +};
   30.45 +
   30.46  //------------------------------LoadRangeNode----------------------------------
   30.47  // Load an array length from the array
   30.48  class LoadRangeNode : public LoadINode {
    31.1 --- a/src/share/vm/opto/mulnode.cpp	Mon Mar 09 11:32:57 2009 -0400
    31.2 +++ b/src/share/vm/opto/mulnode.cpp	Tue Mar 10 08:52:16 2009 -0700
    31.3 @@ -486,20 +486,23 @@
    31.4      return new (phase->C, 3) AndINode(ldus, phase->intcon(mask&0xFFFF));
    31.5    }
    31.6  
    31.7 -  // Masking sign bits off of a Byte?  Let the matcher use an unsigned load
    31.8 -  if( lop == Op_LoadB &&
    31.9 -      (!in(0) && load->in(0)) &&
   31.10 -      (mask == 0x000000FF) ) {
   31.11 -    // Associate this node with the LoadB, so the matcher can see them together.
   31.12 -    // If we don't do this, it is common for the LoadB to have one control
   31.13 -    // edge, and the store or call containing this AndI to have a different
   31.14 -    // control edge.  This will cause Label_Root to group the AndI with
   31.15 -    // the encoding store or call, so the matcher has no chance to match
   31.16 -    // this AndI together with the LoadB.  Setting the control edge here
   31.17 -    // prevents Label_Root from grouping the AndI with the store or call,
   31.18 -    // if it has a control edge that is inconsistent with the LoadB.
   31.19 -    set_req(0, load->in(0));
   31.20 -    return this;
   31.21 +  // Masking sign bits off of a Byte?  Do an unsigned byte load.
   31.22 +  if (lop == Op_LoadB && mask == 0x000000FF) {
   31.23 +    return new (phase->C, 3) LoadUBNode(load->in(MemNode::Control),
   31.24 +                                        load->in(MemNode::Memory),
   31.25 +                                        load->in(MemNode::Address),
   31.26 +                                        load->adr_type());
   31.27 +  }
   31.28 +
   31.29 +  // Masking sign bits off of a Byte plus additional lower bits?  Do
   31.30 +  // an unsigned byte load plus an and.
   31.31 +  if (lop == Op_LoadB && (mask & 0xFFFFFF00) == 0) {
   31.32 +    Node* ldub = new (phase->C, 3) LoadUBNode(load->in(MemNode::Control),
   31.33 +                                              load->in(MemNode::Memory),
   31.34 +                                              load->in(MemNode::Address),
   31.35 +                                              load->adr_type());
   31.36 +    ldub = phase->transform(ldub);
   31.37 +    return new (phase->C, 3) AndINode(ldub, phase->intcon(mask));
   31.38    }
   31.39  
   31.40    // Masking off sign bits?  Dont make them!
   31.41 @@ -599,12 +602,21 @@
   31.42    if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape);
   31.43    const jlong mask = t2->get_con();
   31.44  
   31.45 -  Node *rsh = in(1);
   31.46 -  uint rop = rsh->Opcode();
   31.47 +  Node* in1 = in(1);
   31.48 +  uint op = in1->Opcode();
   31.49 +
   31.50 +  // Masking sign bits off of an integer?  Do an unsigned integer to long load.
   31.51 +  if (op == Op_ConvI2L && in1->in(1)->Opcode() == Op_LoadI && mask == 0x00000000FFFFFFFFL) {
   31.52 +    Node* load = in1->in(1);
   31.53 +    return new (phase->C, 3) LoadUI2LNode(load->in(MemNode::Control),
   31.54 +                                          load->in(MemNode::Memory),
   31.55 +                                          load->in(MemNode::Address),
   31.56 +                                          load->adr_type());
   31.57 +  }
   31.58  
   31.59    // Masking off sign bits?  Dont make them!
   31.60 -  if( rop == Op_RShiftL ) {
   31.61 -    const TypeInt *t12 = phase->type(rsh->in(2))->isa_int();
   31.62 +  if (op == Op_RShiftL) {
   31.63 +    const TypeInt *t12 = phase->type(in1->in(2))->isa_int();
   31.64      if( t12 && t12->is_con() ) { // Shift is by a constant
   31.65        int shift = t12->get_con();
   31.66        shift &= BitsPerJavaLong - 1;  // semantics of Java shifts
   31.67 @@ -613,7 +625,7 @@
   31.68        // bits survive.  NO sign-extension bits survive the maskings.
   31.69        if( (sign_bits_mask & mask) == 0 ) {
   31.70          // Use zero-fill shift instead
   31.71 -        Node *zshift = phase->transform(new (phase->C, 3) URShiftLNode(rsh->in(1),rsh->in(2)));
   31.72 +        Node *zshift = phase->transform(new (phase->C, 3) URShiftLNode(in1->in(1), in1->in(2)));
   31.73          return new (phase->C, 3) AndLNode( zshift, in(2) );
   31.74        }
   31.75      }
    32.1 --- a/src/share/vm/opto/type.cpp	Mon Mar 09 11:32:57 2009 -0400
    32.2 +++ b/src/share/vm/opto/type.cpp	Tue Mar 10 08:52:16 2009 -0700
    32.3 @@ -1,5 +1,5 @@
    32.4  /*
    32.5 - * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
    32.6 + * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
    32.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    32.8   *
    32.9   * This code is free software; you can redistribute it and/or modify it
   32.10 @@ -226,6 +226,7 @@
   32.11    TypeInt::CC_LE   = TypeInt::make(-1, 0, WidenMin);
   32.12    TypeInt::CC_GE   = TypeInt::make( 0, 1, WidenMin);  // == TypeInt::BOOL
   32.13    TypeInt::BYTE    = TypeInt::make(-128,127,     WidenMin); // Bytes
   32.14 +  TypeInt::UBYTE   = TypeInt::make(0, 255,       WidenMin); // Unsigned Bytes
   32.15    TypeInt::CHAR    = TypeInt::make(0,65535,      WidenMin); // Java chars
   32.16    TypeInt::SHORT   = TypeInt::make(-32768,32767, WidenMin); // Java shorts
   32.17    TypeInt::POS     = TypeInt::make(0,max_jint,   WidenMin); // Non-neg values
   32.18 @@ -1022,6 +1023,7 @@
   32.19  const TypeInt *TypeInt::CC_LE;  // [-1,0]
   32.20  const TypeInt *TypeInt::CC_GE;  // [0,1] == BOOL (!)
   32.21  const TypeInt *TypeInt::BYTE;   // Bytes, -128 to 127
   32.22 +const TypeInt *TypeInt::UBYTE;  // Unsigned Bytes, 0 to 255
   32.23  const TypeInt *TypeInt::CHAR;   // Java chars, 0-65535
   32.24  const TypeInt *TypeInt::SHORT;  // Java shorts, -32768-32767
   32.25  const TypeInt *TypeInt::POS;    // Positive 32-bit integers or zero
    33.1 --- a/src/share/vm/opto/type.hpp	Mon Mar 09 11:32:57 2009 -0400
    33.2 +++ b/src/share/vm/opto/type.hpp	Tue Mar 10 08:52:16 2009 -0700
    33.3 @@ -1,5 +1,5 @@
    33.4  /*
    33.5 - * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
    33.6 + * Copyright 1997-2009 Sun Microsystems, Inc.  All Rights Reserved.
    33.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    33.8   *
    33.9   * This code is free software; you can redistribute it and/or modify it
   33.10 @@ -415,6 +415,7 @@
   33.11    static const TypeInt *CC_LE;  // [-1,0]
   33.12    static const TypeInt *CC_GE;  // [0,1] == BOOL (!)
   33.13    static const TypeInt *BYTE;
   33.14 +  static const TypeInt *UBYTE;
   33.15    static const TypeInt *CHAR;
   33.16    static const TypeInt *SHORT;
   33.17    static const TypeInt *POS;
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/test/compiler/6797305/Test6797305.java	Tue Mar 10 08:52:16 2009 -0700
    34.3 @@ -0,0 +1,114 @@
    34.4 +/*
    34.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    34.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    34.7 + *
    34.8 + * This code is free software; you can redistribute it and/or modify it
    34.9 + * under the terms of the GNU General Public License version 2 only, as
   34.10 + * published by the Free Software Foundation.
   34.11 + *
   34.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
   34.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   34.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   34.15 + * version 2 for more details (a copy is included in the LICENSE file that
   34.16 + * accompanied this code).
   34.17 + *
   34.18 + * You should have received a copy of the GNU General Public License version
   34.19 + * 2 along with this work; if not, write to the Free Software Foundation,
   34.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   34.21 + *
   34.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   34.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
   34.24 + * have any questions.
   34.25 + */
   34.26 +
   34.27 +/**
   34.28 + * @test
   34.29 + * @bug 6797305
   34.30 + * @summary Add LoadUB and LoadUI opcode class
   34.31 + *
   34.32 + * @run main/othervm -Xcomp -XX:CompileOnly=Test6797305.loadB,Test6797305.loadB2L,Test6797305.loadUB,Test6797305.loadUBmask,Test6797305.loadUB2L,Test6797305.loadS,Test6797305.loadS2L,Test6797305.loadUS,Test6797305.loadUSmask,Test6797305.loadUS2L,Test6797305.loadI,Test6797305.loadI2L,Test6797305.loadUI2L,Test6797305.loadL Test6797305
   34.33 + */
   34.34 +
   34.35 +public class Test6797305 {
   34.36 +    static final byte[]  ba = new byte[]  { -1 };
   34.37 +    static final short[] sa = new short[] { -1 };
   34.38 +    static final int[]   ia = new int[]   { -1 };
   34.39 +    static final long[]  la = new long[]  { -1 };
   34.40 +
   34.41 +    public static void main(String[] args)
   34.42 +    {
   34.43 +        long b = loadB(ba);
   34.44 +        if (b != -1)
   34.45 +            throw new InternalError("loadB failed: " + b + " != " + -1);
   34.46 +
   34.47 +        long b2l = loadB2L(ba);
   34.48 +        if (b2l != -1L)
   34.49 +            throw new InternalError("loadB2L failed: " + b2l + " != " + -1L);
   34.50 +
   34.51 +        int ub = loadUB(ba);
   34.52 +        if (ub != 0xFF)
   34.53 +            throw new InternalError("loadUB failed: " + ub + " != " + 0xFF);
   34.54 +
   34.55 +        int ubmask = loadUBmask(ba);
   34.56 +        if (ubmask != 0xFE)
   34.57 +            throw new InternalError("loadUBmask failed: " + ubmask + " != " + 0xFE);
   34.58 +
   34.59 +        long ub2l = loadUB2L(ba);
   34.60 +        if (ub2l != 0xFFL)
   34.61 +            throw new InternalError("loadUB2L failed: " + ub2l + " != " + 0xFFL);
   34.62 +
   34.63 +        int s = loadS(sa);
   34.64 +        if (s != -1)
   34.65 +            throw new InternalError("loadS failed: " + s + " != " + -1);
   34.66 +
   34.67 +        long s2l = loadS2L(sa);
   34.68 +        if (s2l != -1L)
   34.69 +            throw new InternalError("loadS2L failed: " + s2l + " != " + -1L);
   34.70 +
   34.71 +        int us = loadUS(sa);
   34.72 +        if (us != 0xFFFF)
   34.73 +            throw new InternalError("loadUS failed: " + us + " != " + 0xFFFF);
   34.74 +
   34.75 +        int usmask = loadUSmask(sa);
   34.76 +        if (usmask != 0xFFFE)
   34.77 +            throw new InternalError("loadUBmask failed: " + ubmask + " != " + 0xFFFE);
   34.78 +
   34.79 +        long us2l = loadUS2L(sa);
   34.80 +        if (us2l != 0xFFFFL)
   34.81 +            throw new InternalError("loadUS2L failed: " + us2l + " != " + 0xFFFFL);
   34.82 +
   34.83 +        int i = loadI(ia);
   34.84 +        if (i != -1)
   34.85 +            throw new InternalError("loadI failed: " + i + " != " + -1);
   34.86 +
   34.87 +        long i2l = loadI2L(ia);
   34.88 +        if (i2l != -1L)
   34.89 +            throw new InternalError("loadI2L failed: " + i2l + " != " + -1L);
   34.90 +
   34.91 +        long ui2l = loadUI2L(ia);
   34.92 +        if (ui2l != 0xFFFFFFFFL)
   34.93 +            throw new InternalError("loadUI2L failed: " + ui2l + " != " + 0xFFFFFFFFL);
   34.94 +
   34.95 +        long l = loadL(la);
   34.96 +        if (l != -1L)
   34.97 +            throw new InternalError("loadL failed: " + l + " != " + -1L);
   34.98 +    }
   34.99 +
  34.100 +    static int  loadB     (byte[] ba)  { return ba[0];               }
  34.101 +    static long loadB2L   (byte[] ba)  { return ba[0];               }
  34.102 +    static int  loadUB    (byte[] ba)  { return ba[0] & 0xFF;        }
  34.103 +    static int  loadUBmask(byte[] ba)  { return ba[0] & 0xFE;        }
  34.104 +    static long loadUB2L  (byte[] ba)  { return ba[0] & 0xFF;        }
  34.105 +
  34.106 +    static int  loadS     (short[] sa) { return sa[0];               }
  34.107 +    static long loadS2L   (short[] sa) { return sa[0];               }
  34.108 +    static int  loadUS    (short[] sa) { return sa[0] & 0xFFFF;      }
  34.109 +    static int  loadUSmask(short[] sa) { return sa[0] & 0xFFFE;      }
  34.110 +    static long loadUS2L  (short[] sa) { return sa[0] & 0xFFFF;      }
  34.111 +
  34.112 +    static int  loadI     (int[] ia)   { return ia[0];               }
  34.113 +    static long loadI2L   (int[] ia)   { return ia[0];               }
  34.114 +    static long loadUI2L  (int[] ia)   { return ia[0] & 0xFFFFFFFFL; }
  34.115 +
  34.116 +    static long loadL     (long[] la)  { return la[0];               }
  34.117 +}

mercurial