src/cpu/sparc/vm/assembler_sparc.cpp

changeset 1079
c517646eef23
parent 1077
660978a2a31a
child 1100
c89f86385056
child 1112
96b229c54d1e
     1.1 --- a/src/cpu/sparc/vm/assembler_sparc.cpp	Fri Mar 13 11:35:17 2009 -0700
     1.2 +++ b/src/cpu/sparc/vm/assembler_sparc.cpp	Fri Mar 13 18:39:22 2009 -0700
     1.3 @@ -2767,6 +2767,268 @@
     1.4  }
     1.5  
     1.6  
     1.7 +void MacroAssembler::check_klass_subtype(Register sub_klass,
     1.8 +                                         Register super_klass,
     1.9 +                                         Register temp_reg,
    1.10 +                                         Register temp2_reg,
    1.11 +                                         Label& L_success) {
    1.12 +  Label L_failure, L_pop_to_failure;
    1.13 +  check_klass_subtype_fast_path(sub_klass, super_klass,
    1.14 +                                temp_reg, temp2_reg,
    1.15 +                                &L_success, &L_failure, NULL);
    1.16 +  Register sub_2 = sub_klass;
    1.17 +  Register sup_2 = super_klass;
    1.18 +  if (!sub_2->is_global())  sub_2 = L0;
    1.19 +  if (!sup_2->is_global())  sup_2 = L1;
    1.20 +
    1.21 +  save_frame_and_mov(0, sub_klass, sub_2, super_klass, sup_2);
    1.22 +  check_klass_subtype_slow_path(sub_2, sup_2,
    1.23 +                                L2, L3, L4, L5,
    1.24 +                                NULL, &L_pop_to_failure);
    1.25 +
    1.26 +  // on success:
    1.27 +  restore();
    1.28 +  ba(false, L_success);
    1.29 +  delayed()->nop();
    1.30 +
    1.31 +  // on failure:
    1.32 +  bind(L_pop_to_failure);
    1.33 +  restore();
    1.34 +  bind(L_failure);
    1.35 +}
    1.36 +
    1.37 +
    1.38 +void MacroAssembler::check_klass_subtype_fast_path(Register sub_klass,
    1.39 +                                                   Register super_klass,
    1.40 +                                                   Register temp_reg,
    1.41 +                                                   Register temp2_reg,
    1.42 +                                                   Label* L_success,
    1.43 +                                                   Label* L_failure,
    1.44 +                                                   Label* L_slow_path,
    1.45 +                                        RegisterConstant super_check_offset,
    1.46 +                                        Register instanceof_hack) {
    1.47 +  int sc_offset = (klassOopDesc::header_size() * HeapWordSize +
    1.48 +                   Klass::secondary_super_cache_offset_in_bytes());
    1.49 +  int sco_offset = (klassOopDesc::header_size() * HeapWordSize +
    1.50 +                    Klass::super_check_offset_offset_in_bytes());
    1.51 +
    1.52 +  bool must_load_sco  = (super_check_offset.constant_or_zero() == -1);
    1.53 +  bool need_slow_path = (must_load_sco ||
    1.54 +                         super_check_offset.constant_or_zero() == sco_offset);
    1.55 +
    1.56 +  assert_different_registers(sub_klass, super_klass, temp_reg);
    1.57 +  if (super_check_offset.is_register()) {
    1.58 +    assert_different_registers(sub_klass, super_klass,
    1.59 +                               super_check_offset.as_register());
    1.60 +  } else if (must_load_sco) {
    1.61 +    assert(temp2_reg != noreg, "supply either a temp or a register offset");
    1.62 +  }
    1.63 +
    1.64 +  Label L_fallthrough;
    1.65 +  int label_nulls = 0;
    1.66 +  if (L_success == NULL)   { L_success   = &L_fallthrough; label_nulls++; }
    1.67 +  if (L_failure == NULL)   { L_failure   = &L_fallthrough; label_nulls++; }
    1.68 +  if (L_slow_path == NULL) { L_slow_path = &L_fallthrough; label_nulls++; }
    1.69 +  assert(label_nulls <= 1 || instanceof_hack != noreg ||
    1.70 +         (L_slow_path == &L_fallthrough && label_nulls <= 2 && !need_slow_path),
    1.71 +         "at most one NULL in the batch, usually");
    1.72 +
    1.73 +  // Support for the instanceof hack, which uses delay slots to
    1.74 +  // set a destination register to zero or one.
    1.75 +  bool do_bool_sets = (instanceof_hack != noreg);
    1.76 +#define BOOL_SET(bool_value)                            \
    1.77 +  if (do_bool_sets && bool_value >= 0)                  \
    1.78 +    set(bool_value, instanceof_hack)
    1.79 +#define DELAYED_BOOL_SET(bool_value)                    \
    1.80 +  if (do_bool_sets && bool_value >= 0)                  \
    1.81 +    delayed()->set(bool_value, instanceof_hack);        \
    1.82 +  else delayed()->nop()
    1.83 +  // Hacked ba(), which may only be used just before L_fallthrough.
    1.84 +#define FINAL_JUMP(label, bool_value)                   \
    1.85 +  if (&(label) == &L_fallthrough) {                     \
    1.86 +    BOOL_SET(bool_value);                               \
    1.87 +  } else {                                              \
    1.88 +    ba((do_bool_sets && bool_value >= 0), label);       \
    1.89 +    DELAYED_BOOL_SET(bool_value);                       \
    1.90 +  }
    1.91 +
    1.92 +  // If the pointers are equal, we are done (e.g., String[] elements).
    1.93 +  // This self-check enables sharing of secondary supertype arrays among
    1.94 +  // non-primary types such as array-of-interface.  Otherwise, each such
    1.95 +  // type would need its own customized SSA.
    1.96 +  // We move this check to the front of the fast path because many
    1.97 +  // type checks are in fact trivially successful in this manner,
    1.98 +  // so we get a nicely predicted branch right at the start of the check.
    1.99 +  cmp(super_klass, sub_klass);
   1.100 +  brx(Assembler::equal, do_bool_sets, Assembler::pn, *L_success);
   1.101 +  DELAYED_BOOL_SET(1);
   1.102 +
   1.103 +  // Check the supertype display:
   1.104 +  if (must_load_sco) {
   1.105 +    // The super check offset is always positive...
   1.106 +    lduw(super_klass, sco_offset, temp2_reg);
   1.107 +    super_check_offset = RegisterConstant(temp2_reg);
   1.108 +  }
   1.109 +  ld_ptr(sub_klass, super_check_offset, temp_reg);
   1.110 +  cmp(super_klass, temp_reg);
   1.111 +
   1.112 +  // This check has worked decisively for primary supers.
   1.113 +  // Secondary supers are sought in the super_cache ('super_cache_addr').
   1.114 +  // (Secondary supers are interfaces and very deeply nested subtypes.)
   1.115 +  // This works in the same check above because of a tricky aliasing
   1.116 +  // between the super_cache and the primary super display elements.
   1.117 +  // (The 'super_check_addr' can address either, as the case requires.)
   1.118 +  // Note that the cache is updated below if it does not help us find
   1.119 +  // what we need immediately.
   1.120 +  // So if it was a primary super, we can just fail immediately.
   1.121 +  // Otherwise, it's the slow path for us (no success at this point).
   1.122 +
   1.123 +  if (super_check_offset.is_register()) {
   1.124 +    brx(Assembler::equal, do_bool_sets, Assembler::pn, *L_success);
   1.125 +    delayed(); if (do_bool_sets)  BOOL_SET(1);
   1.126 +    // if !do_bool_sets, sneak the next cmp into the delay slot:
   1.127 +    cmp(super_check_offset.as_register(), sc_offset);
   1.128 +
   1.129 +    if (L_failure == &L_fallthrough) {
   1.130 +      brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_slow_path);
   1.131 +      delayed()->nop();
   1.132 +      BOOL_SET(0);  // fallthrough on failure
   1.133 +    } else {
   1.134 +      brx(Assembler::notEqual, do_bool_sets, Assembler::pn, *L_failure);
   1.135 +      DELAYED_BOOL_SET(0);
   1.136 +      FINAL_JUMP(*L_slow_path, -1);  // -1 => vanilla delay slot
   1.137 +    }
   1.138 +  } else if (super_check_offset.as_constant() == sc_offset) {
   1.139 +    // Need a slow path; fast failure is impossible.
   1.140 +    if (L_slow_path == &L_fallthrough) {
   1.141 +      brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_success);
   1.142 +      DELAYED_BOOL_SET(1);
   1.143 +    } else {
   1.144 +      brx(Assembler::notEqual, false, Assembler::pn, *L_slow_path);
   1.145 +      delayed()->nop();
   1.146 +      FINAL_JUMP(*L_success, 1);
   1.147 +    }
   1.148 +  } else {
   1.149 +    // No slow path; it's a fast decision.
   1.150 +    if (L_failure == &L_fallthrough) {
   1.151 +      brx(Assembler::equal, do_bool_sets, Assembler::pt, *L_success);
   1.152 +      DELAYED_BOOL_SET(1);
   1.153 +      BOOL_SET(0);
   1.154 +    } else {
   1.155 +      brx(Assembler::notEqual, do_bool_sets, Assembler::pn, *L_failure);
   1.156 +      DELAYED_BOOL_SET(0);
   1.157 +      FINAL_JUMP(*L_success, 1);
   1.158 +    }
   1.159 +  }
   1.160 +
   1.161 +  bind(L_fallthrough);
   1.162 +
   1.163 +#undef final_jump
   1.164 +#undef bool_set
   1.165 +#undef DELAYED_BOOL_SET
   1.166 +#undef final_jump
   1.167 +}
   1.168 +
   1.169 +
   1.170 +void MacroAssembler::check_klass_subtype_slow_path(Register sub_klass,
   1.171 +                                                   Register super_klass,
   1.172 +                                                   Register count_temp,
   1.173 +                                                   Register scan_temp,
   1.174 +                                                   Register scratch_reg,
   1.175 +                                                   Register coop_reg,
   1.176 +                                                   Label* L_success,
   1.177 +                                                   Label* L_failure) {
   1.178 +  assert_different_registers(sub_klass, super_klass,
   1.179 +                             count_temp, scan_temp, scratch_reg, coop_reg);
   1.180 +
   1.181 +  Label L_fallthrough, L_loop;
   1.182 +  int label_nulls = 0;
   1.183 +  if (L_success == NULL)   { L_success   = &L_fallthrough; label_nulls++; }
   1.184 +  if (L_failure == NULL)   { L_failure   = &L_fallthrough; label_nulls++; }
   1.185 +  assert(label_nulls <= 1, "at most one NULL in the batch");
   1.186 +
   1.187 +  // a couple of useful fields in sub_klass:
   1.188 +  int ss_offset = (klassOopDesc::header_size() * HeapWordSize +
   1.189 +                   Klass::secondary_supers_offset_in_bytes());
   1.190 +  int sc_offset = (klassOopDesc::header_size() * HeapWordSize +
   1.191 +                   Klass::secondary_super_cache_offset_in_bytes());
   1.192 +
   1.193 +  // Do a linear scan of the secondary super-klass chain.
   1.194 +  // This code is rarely used, so simplicity is a virtue here.
   1.195 +
   1.196 +#ifndef PRODUCT
   1.197 +  int* pst_counter = &SharedRuntime::_partial_subtype_ctr;
   1.198 +  inc_counter((address) pst_counter, count_temp, scan_temp);
   1.199 +#endif
   1.200 +
   1.201 +  // We will consult the secondary-super array.
   1.202 +  ld_ptr(sub_klass, ss_offset, scan_temp);
   1.203 +
   1.204 +  // Compress superclass if necessary.
   1.205 +  Register search_key = super_klass;
   1.206 +  bool decode_super_klass = false;
   1.207 +  if (UseCompressedOops) {
   1.208 +    if (coop_reg != noreg) {
   1.209 +      encode_heap_oop_not_null(super_klass, coop_reg);
   1.210 +      search_key = coop_reg;
   1.211 +    } else {
   1.212 +      encode_heap_oop_not_null(super_klass);
   1.213 +      decode_super_klass = true; // scarce temps!
   1.214 +    }
   1.215 +    // The superclass is never null; it would be a basic system error if a null
   1.216 +    // pointer were to sneak in here.  Note that we have already loaded the
   1.217 +    // Klass::super_check_offset from the super_klass in the fast path,
   1.218 +    // so if there is a null in that register, we are already in the afterlife.
   1.219 +  }
   1.220 +
   1.221 +  // Load the array length.  (Positive movl does right thing on LP64.)
   1.222 +  lduw(scan_temp, arrayOopDesc::length_offset_in_bytes(), count_temp);
   1.223 +
   1.224 +  // Check for empty secondary super list
   1.225 +  tst(count_temp);
   1.226 +
   1.227 +  // Top of search loop
   1.228 +  bind(L_loop);
   1.229 +  br(Assembler::equal, false, Assembler::pn, *L_failure);
   1.230 +  delayed()->add(scan_temp, heapOopSize, scan_temp);
   1.231 +  assert(heapOopSize != 0, "heapOopSize should be initialized");
   1.232 +
   1.233 +  // Skip the array header in all array accesses.
   1.234 +  int elem_offset = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
   1.235 +  elem_offset -= heapOopSize;   // the scan pointer was pre-incremented also
   1.236 +
   1.237 +  // Load next super to check
   1.238 +  if (UseCompressedOops) {
   1.239 +    // Don't use load_heap_oop; we don't want to decode the element.
   1.240 +    lduw(   scan_temp, elem_offset, scratch_reg );
   1.241 +  } else {
   1.242 +    ld_ptr( scan_temp, elem_offset, scratch_reg );
   1.243 +  }
   1.244 +
   1.245 +  // Look for Rsuper_klass on Rsub_klass's secondary super-class-overflow list
   1.246 +  cmp(scratch_reg, search_key);
   1.247 +
   1.248 +  // A miss means we are NOT a subtype and need to keep looping
   1.249 +  brx(Assembler::notEqual, false, Assembler::pn, L_loop);
   1.250 +  delayed()->deccc(count_temp); // decrement trip counter in delay slot
   1.251 +
   1.252 +  // Falling out the bottom means we found a hit; we ARE a subtype
   1.253 +  if (decode_super_klass) decode_heap_oop(super_klass);
   1.254 +
   1.255 +  // Success.  Cache the super we found and proceed in triumph.
   1.256 +  st_ptr(super_klass, sub_klass, sc_offset);
   1.257 +
   1.258 +  if (L_success != &L_fallthrough) {
   1.259 +    ba(false, *L_success);
   1.260 +    delayed()->nop();
   1.261 +  }
   1.262 +
   1.263 +  bind(L_fallthrough);
   1.264 +}
   1.265 +
   1.266 +
   1.267 +
   1.268 +
   1.269  void MacroAssembler::biased_locking_enter(Register obj_reg, Register mark_reg,
   1.270                                            Register temp_reg,
   1.271                                            Label& done, Label* slow_case,

mercurial