src/cpu/sparc/vm/assembler_sparc.cpp

changeset 1058
9adddb8c0fc8
parent 1057
56aae7be60d4
child 1077
660978a2a31a
     1.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp	Wed Mar 04 09:58:39 2009 -0800
     1.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp	Fri Mar 06 21:36:50 2009 -0800
     1.3 @@ -2638,6 +2638,135 @@
     1.4  }
     1.5  
     1.6  
     1.7 +void MacroAssembler::regcon_inc_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) {
     1.8 +  assert(dest.register_or_noreg() != G0, "lost side effect");
     1.9 +  if ((src.is_constant() && src.as_constant() == 0) ||
    1.10 +      (src.is_register() && src.as_register() == G0)) {
    1.11 +    // do nothing
    1.12 +  } else if (dest.is_register()) {
    1.13 +    add(dest.as_register(), ensure_rs2(src, temp), dest.as_register());
    1.14 +  } else if (src.is_constant()) {
    1.15 +    intptr_t res = dest.as_constant() + src.as_constant();
    1.16 +    dest = RegisterConstant(res); // side effect seen by caller
    1.17 +  } else {
    1.18 +    assert(temp != noreg, "cannot handle constant += register");
    1.19 +    add(src.as_register(), ensure_rs2(dest, temp), temp);
    1.20 +    dest = RegisterConstant(temp); // side effect seen by caller
    1.21 +  }
    1.22 +}
    1.23 +
    1.24 +void MacroAssembler::regcon_sll_ptr( RegisterConstant& dest, RegisterConstant src, Register temp ) {
    1.25 +  assert(dest.register_or_noreg() != G0, "lost side effect");
    1.26 +  if (!is_simm13(src.constant_or_zero()))
    1.27 +    src = (src.as_constant() & 0xFF);
    1.28 +  if ((src.is_constant() && src.as_constant() == 0) ||
    1.29 +      (src.is_register() && src.as_register() == G0)) {
    1.30 +    // do nothing
    1.31 +  } else if (dest.is_register()) {
    1.32 +    sll_ptr(dest.as_register(), src, dest.as_register());
    1.33 +  } else if (src.is_constant()) {
    1.34 +    intptr_t res = dest.as_constant() << src.as_constant();
    1.35 +    dest = RegisterConstant(res); // side effect seen by caller
    1.36 +  } else {
    1.37 +    assert(temp != noreg, "cannot handle constant <<= register");
    1.38 +    set(dest.as_constant(), temp);
    1.39 +    sll_ptr(temp, src, temp);
    1.40 +    dest = RegisterConstant(temp); // side effect seen by caller
    1.41 +  }
    1.42 +}
    1.43 +
    1.44 +
    1.45 +// Look up the method for a megamorphic invokeinterface call.
    1.46 +// The target method is determined by <intf_klass, itable_index>.
    1.47 +// The receiver klass is in recv_klass.
    1.48 +// On success, the result will be in method_result, and execution falls through.
    1.49 +// On failure, execution transfers to the given label.
    1.50 +void MacroAssembler::lookup_interface_method(Register recv_klass,
    1.51 +                                             Register intf_klass,
    1.52 +                                             RegisterConstant itable_index,
    1.53 +                                             Register method_result,
    1.54 +                                             Register scan_temp,
    1.55 +                                             Register sethi_temp,
    1.56 +                                             Label& L_no_such_interface) {
    1.57 +  assert_different_registers(recv_klass, intf_klass, method_result, scan_temp);
    1.58 +  assert(itable_index.is_constant() || itable_index.as_register() == method_result,
    1.59 +         "caller must use same register for non-constant itable index as for method");
    1.60 +
    1.61 +  // Compute start of first itableOffsetEntry (which is at the end of the vtable)
    1.62 +  int vtable_base = instanceKlass::vtable_start_offset() * wordSize;
    1.63 +  int scan_step   = itableOffsetEntry::size() * wordSize;
    1.64 +  int vte_size    = vtableEntry::size() * wordSize;
    1.65 +
    1.66 +  lduw(recv_klass, instanceKlass::vtable_length_offset() * wordSize, scan_temp);
    1.67 +  // %%% We should store the aligned, prescaled offset in the klassoop.
    1.68 +  // Then the next several instructions would fold away.
    1.69 +
    1.70 +  int round_to_unit = ((HeapWordsPerLong > 1) ? BytesPerLong : 0);
    1.71 +  int itb_offset = vtable_base;
    1.72 +  if (round_to_unit != 0) {
    1.73 +    // hoist first instruction of round_to(scan_temp, BytesPerLong):
    1.74 +    itb_offset += round_to_unit - wordSize;
    1.75 +  }
    1.76 +  int itb_scale = exact_log2(vtableEntry::size() * wordSize);
    1.77 +  sll(scan_temp, itb_scale,  scan_temp);
    1.78 +  add(scan_temp, itb_offset, scan_temp);
    1.79 +  if (round_to_unit != 0) {
    1.80 +    // Round up to align_object_offset boundary
    1.81 +    // see code for instanceKlass::start_of_itable!
    1.82 +    // Was: round_to(scan_temp, BytesPerLong);
    1.83 +    // Hoisted: add(scan_temp, BytesPerLong-1, scan_temp);
    1.84 +    and3(scan_temp, -round_to_unit, scan_temp);
    1.85 +  }
    1.86 +  add(recv_klass, scan_temp, scan_temp);
    1.87 +
    1.88 +  // Adjust recv_klass by scaled itable_index, so we can free itable_index.
    1.89 +  RegisterConstant itable_offset = itable_index;
    1.90 +  regcon_sll_ptr(itable_offset, exact_log2(itableMethodEntry::size() * wordSize));
    1.91 +  regcon_inc_ptr(itable_offset, itableMethodEntry::method_offset_in_bytes());
    1.92 +  add(recv_klass, ensure_rs2(itable_offset, sethi_temp), recv_klass);
    1.93 +
    1.94 +  // for (scan = klass->itable(); scan->interface() != NULL; scan += scan_step) {
    1.95 +  //   if (scan->interface() == intf) {
    1.96 +  //     result = (klass + scan->offset() + itable_index);
    1.97 +  //   }
    1.98 +  // }
    1.99 +  Label search, found_method;
   1.100 +
   1.101 +  for (int peel = 1; peel >= 0; peel--) {
   1.102 +    // %%%% Could load both offset and interface in one ldx, if they were
   1.103 +    // in the opposite order.  This would save a load.
   1.104 +    ld_ptr(scan_temp, itableOffsetEntry::interface_offset_in_bytes(), method_result);
   1.105 +
   1.106 +    // Check that this entry is non-null.  A null entry means that
   1.107 +    // the receiver class doesn't implement the interface, and wasn't the
   1.108 +    // same as when the caller was compiled.
   1.109 +    bpr(Assembler::rc_z, false, Assembler::pn, method_result, L_no_such_interface);
   1.110 +    delayed()->cmp(method_result, intf_klass);
   1.111 +
   1.112 +    if (peel) {
   1.113 +      brx(Assembler::equal,    false, Assembler::pt, found_method);
   1.114 +    } else {
   1.115 +      brx(Assembler::notEqual, false, Assembler::pn, search);
   1.116 +      // (invert the test to fall through to found_method...)
   1.117 +    }
   1.118 +    delayed()->add(scan_temp, scan_step, scan_temp);
   1.119 +
   1.120 +    if (!peel)  break;
   1.121 +
   1.122 +    bind(search);
   1.123 +  }
   1.124 +
   1.125 +  bind(found_method);
   1.126 +
   1.127 +  // Got a hit.
   1.128 +  int ito_offset = itableOffsetEntry::offset_offset_in_bytes();
   1.129 +  // scan_temp[-scan_step] points to the vtable offset we need
   1.130 +  ito_offset -= scan_step;
   1.131 +  lduw(scan_temp, ito_offset, scan_temp);
   1.132 +  ld_ptr(recv_klass, scan_temp, method_result);
   1.133 +}
   1.134 +
   1.135 +
   1.136  void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
   1.137                                            Register temp_reg,
   1.138                                            Label& done, Label* slow_case,

mercurial