Print this page
rev 4534 : 8010927: Kitchensink crashed with SIGSEGV, Problematic frame: v ~StubRoutines::checkcast_arraycopy
Summary: Changed gen_write_ref_array_post_barrier() code on x64 to pass start address and number of copied oop elements. In generate_checkcast_copy() skip post barrier code if no elements are copied.
Reviewed-by: roland

Split Split Close
Expand all
Collapse all
          --- old/src/cpu/x86/vm/stubGenerator_x86_64.cpp
          +++ new/src/cpu/x86/vm/stubGenerator_x86_64.cpp
↓ open down ↓ 1237 lines elided ↑ open up ↑
1238 1238          ShouldNotReachHere();
1239 1239  
1240 1240      }
1241 1241    }
1242 1242  
1243 1243    //
1244 1244    // Generate code for an array write post barrier
1245 1245    //
1246 1246    //  Input:
1247 1247    //     start    - register containing starting address of destination array
1248      -  //     end      - register containing ending address of destination array
     1248 +  //     count    - elements count
1249 1249    //     scratch  - scratch register
1250 1250    //
1251 1251    //  The input registers are overwritten.
1252      -  //  The ending address is inclusive.
1253      -  void  gen_write_ref_array_post_barrier(Register start, Register end, Register scratch) {
1254      -    assert_different_registers(start, end, scratch);
     1252 +  //
     1253 +  void  gen_write_ref_array_post_barrier(Register start, Register count, Register scratch) {
     1254 +    assert_different_registers(start, count, scratch);
1255 1255      BarrierSet* bs = Universe::heap()->barrier_set();
1256 1256      switch (bs->kind()) {
1257 1257        case BarrierSet::G1SATBCT:
1258 1258        case BarrierSet::G1SATBCTLogging:
1259      -
1260 1259          {
1261      -          __ pusha();                      // push registers (overkill)
1262      -          // must compute element count unless barrier set interface is changed (other platforms supply count)
1263      -          assert_different_registers(start, end, scratch);
1264      -          __ lea(scratch, Address(end, BytesPerHeapOop));
1265      -          __ subptr(scratch, start);               // subtract start to get #bytes
1266      -          __ shrptr(scratch, LogBytesPerHeapOop);  // convert to element count
1267      -          __ mov(c_rarg0, start);
1268      -          __ mov(c_rarg1, scratch);
     1260 +          __ pusha();             // push registers (overkill)
     1261 +          if (c_rarg0 == count) { // On win64 c_rarg0 == rcx
     1262 +            assert_different_registers(c_rarg1, start);
     1263 +            __ mov(c_rarg1, count);
     1264 +            __ mov(c_rarg0, start);
     1265 +          } else {
     1266 +            assert_different_registers(c_rarg0, count);
     1267 +            __ mov(c_rarg0, start);
     1268 +            __ mov(c_rarg1, count);
     1269 +          }
1269 1270            __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2);
1270 1271            __ popa();
1271 1272          }
1272 1273          break;
1273 1274        case BarrierSet::CardTableModRef:
1274 1275        case BarrierSet::CardTableExtension:
1275 1276          {
1276 1277            CardTableModRefBS* ct = (CardTableModRefBS*)bs;
1277 1278            assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
1278 1279  
1279 1280            Label L_loop;
     1281 +          const Register end = count;
1280 1282  
1281      -           __ shrptr(start, CardTableModRefBS::card_shift);
1282      -           __ addptr(end, BytesPerHeapOop);
1283      -           __ shrptr(end, CardTableModRefBS::card_shift);
1284      -           __ subptr(end, start); // number of bytes to copy
     1283 +          __ leaq(end, Address(start, count, TIMES_OOP, 0));  // end == start+count*oop_size
     1284 +          __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive
     1285 +          __ shrptr(start, CardTableModRefBS::card_shift);
     1286 +          __ shrptr(end,   CardTableModRefBS::card_shift);
     1287 +          __ subptr(end, start); // end --> cards count
1285 1288  
1286      -          intptr_t disp = (intptr_t) ct->byte_map_base;
1287      -          if (Assembler::is_simm32(disp)) {
1288      -            Address cardtable(noreg, noreg, Address::no_scale, disp);
1289      -            __ lea(scratch, cardtable);
1290      -          } else {
1291      -            ExternalAddress cardtable((address)disp);
1292      -            __ lea(scratch, cardtable);
1293      -          }
1294      -
1295      -          const Register count = end; // 'end' register contains bytes count now
     1289 +          int64_t disp = (int64_t) ct->byte_map_base;
     1290 +          __ mov64(scratch, disp);
1296 1291            __ addptr(start, scratch);
1297 1292          __ BIND(L_loop);
1298 1293            __ movb(Address(start, count, Address::times_1), 0);
1299 1294            __ decrement(count);
1300 1295            __ jcc(Assembler::greaterEqual, L_loop);
1301 1296          }
1302 1297          break;
1303 1298        default:
1304 1299          ShouldNotReachHere();
1305 1300  
↓ open down ↓ 631 lines elided ↑ open up ↑
1937 1932  
1938 1933      // Check for and copy trailing dword
1939 1934    __ BIND(L_copy_4_bytes);
1940 1935      __ testl(dword_count, 1); // Only byte test since the value is 0 or 1
1941 1936      __ jccb(Assembler::zero, L_exit);
1942 1937      __ movl(rax, Address(end_from, 8));
1943 1938      __ movl(Address(end_to, 8), rax);
1944 1939  
1945 1940    __ BIND(L_exit);
1946 1941      if (is_oop) {
1947      -      __ leaq(end_to, Address(saved_to, dword_count, Address::times_4, -4));
1948      -      gen_write_ref_array_post_barrier(saved_to, end_to, rax);
     1942 +      gen_write_ref_array_post_barrier(saved_to, dword_count, rax);
1949 1943      }
1950 1944      restore_arg_regs();
1951 1945      inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free
1952 1946      __ xorptr(rax, rax); // return 0
1953 1947      __ leave(); // required for proper stackwalking of RuntimeStub frame
1954 1948      __ ret(0);
1955 1949  
1956 1950      // Copy in multi-bytes chunks
1957 1951      copy_bytes_forward(end_from, end_to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
1958 1952      __ jmp(L_copy_4_bytes);
↓ open down ↓ 74 lines elided ↑ open up ↑
2033 2027      }
2034 2028      restore_arg_regs();
2035 2029      inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free
2036 2030      __ xorptr(rax, rax); // return 0
2037 2031      __ leave(); // required for proper stackwalking of RuntimeStub frame
2038 2032      __ ret(0);
2039 2033  
2040 2034      // Copy in multi-bytes chunks
2041 2035      copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
2042 2036  
2043      -   __ bind(L_exit);
2044      -     if (is_oop) {
2045      -       Register end_to = rdx;
2046      -       __ leaq(end_to, Address(to, dword_count, Address::times_4, -4));
2047      -       gen_write_ref_array_post_barrier(to, end_to, rax);
2048      -     }
     2037 +  __ BIND(L_exit);
     2038 +    if (is_oop) {
     2039 +      gen_write_ref_array_post_barrier(to, dword_count, rax);
     2040 +    }
2049 2041      restore_arg_regs();
2050 2042      inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free
2051 2043      __ xorptr(rax, rax); // return 0
2052 2044      __ leave(); // required for proper stackwalking of RuntimeStub frame
2053 2045      __ ret(0);
2054 2046  
2055 2047      return start;
2056 2048    }
2057 2049  
2058 2050    // Arguments:
↓ open down ↓ 17 lines elided ↑ open up ↑
2076 2068      StubCodeMark mark(this, "StubRoutines", name);
2077 2069      address start = __ pc();
2078 2070  
2079 2071      Label L_copy_bytes, L_copy_8_bytes, L_exit;
2080 2072      const Register from        = rdi;  // source array address
2081 2073      const Register to          = rsi;  // destination array address
2082 2074      const Register qword_count = rdx;  // elements count
2083 2075      const Register end_from    = from; // source array end address
2084 2076      const Register end_to      = rcx;  // destination array end address
2085 2077      const Register saved_to    = to;
     2078 +    const Register saved_count = r11;
2086 2079      // End pointers are inclusive, and if count is not zero they point
2087 2080      // to the last unit copied:  end_to[0] := end_from[0]
2088 2081  
2089 2082      __ enter(); // required for proper stackwalking of RuntimeStub frame
2090 2083      // Save no-overlap entry point for generate_conjoint_long_oop_copy()
2091 2084      assert_clean_int(c_rarg2, rax);    // Make sure 'count' is clean int.
2092 2085  
2093 2086      if (entry != NULL) {
2094 2087        *entry = __ pc();
2095 2088        // caller can pass a 64-bit byte count here (from Unsafe.copyMemory)
2096 2089        BLOCK_COMMENT("Entry:");
2097 2090      }
2098 2091  
2099 2092      setup_arg_regs(); // from => rdi, to => rsi, count => rdx
2100 2093                        // r9 and r10 may be used to save non-volatile registers
2101 2094      // 'from', 'to' and 'qword_count' are now valid
2102 2095      if (is_oop) {
     2096 +      // Save to and count for store barrier
     2097 +      __ movptr(saved_count, qword_count);
2103 2098        // no registers are destroyed by this call
2104 2099        gen_write_ref_array_pre_barrier(to, qword_count, dest_uninitialized);
2105 2100      }
2106 2101  
2107 2102      // Copy from low to high addresses.  Use 'to' as scratch.
2108 2103      __ lea(end_from, Address(from, qword_count, Address::times_8, -8));
2109 2104      __ lea(end_to,   Address(to,   qword_count, Address::times_8, -8));
2110 2105      __ negptr(qword_count);
2111 2106      __ jmp(L_copy_bytes);
2112 2107  
↓ open down ↓ 12 lines elided ↑ open up ↑
2125 2120        __ xorptr(rax, rax); // return 0
2126 2121        __ leave(); // required for proper stackwalking of RuntimeStub frame
2127 2122        __ ret(0);
2128 2123      }
2129 2124  
2130 2125      // Copy in multi-bytes chunks
2131 2126      copy_bytes_forward(end_from, end_to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
2132 2127  
2133 2128      if (is_oop) {
2134 2129      __ BIND(L_exit);
2135      -      gen_write_ref_array_post_barrier(saved_to, end_to, rax);
     2130 +      gen_write_ref_array_post_barrier(saved_to, saved_count, rax);
2136 2131      }
2137 2132      restore_arg_regs();
2138 2133      if (is_oop) {
2139 2134        inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free
2140 2135      } else {
2141 2136        inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free
2142 2137      }
2143 2138      __ xorptr(rax, rax); // return 0
2144 2139      __ leave(); // required for proper stackwalking of RuntimeStub frame
2145 2140      __ ret(0);
↓ open down ↓ 62 lines elided ↑ open up ↑
2208 2203        __ xorptr(rax, rax); // return 0
2209 2204        __ leave(); // required for proper stackwalking of RuntimeStub frame
2210 2205        __ ret(0);
2211 2206      }
2212 2207  
2213 2208      // Copy in multi-bytes chunks
2214 2209      copy_bytes_backward(from, to, qword_count, rax, L_copy_bytes, L_copy_8_bytes);
2215 2210  
2216 2211      if (is_oop) {
2217 2212      __ BIND(L_exit);
2218      -      __ lea(rcx, Address(to, saved_count, Address::times_8, -8));
2219      -      gen_write_ref_array_post_barrier(to, rcx, rax);
     2213 +      gen_write_ref_array_post_barrier(to, saved_count, rax);
2220 2214      }
2221 2215      restore_arg_regs();
2222 2216      if (is_oop) {
2223 2217        inc_counter_np(SharedRuntime::_oop_array_copy_ctr); // Update counter after rscratch1 is free
2224 2218      } else {
2225 2219        inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free
2226 2220      }
2227 2221      __ xorptr(rax, rax); // return 0
2228 2222      __ leave(); // required for proper stackwalking of RuntimeStub frame
2229 2223      __ ret(0);
↓ open down ↓ 166 lines elided ↑ open up ↑
2396 2390      __ jcc(Assembler::zero, L_store_element);
2397 2391  
2398 2392      __ load_klass(r11_klass, rax_oop);// query the object klass
2399 2393      generate_type_check(r11_klass, ckoff, ckval, L_store_element);
2400 2394      // ======== end loop ========
2401 2395  
2402 2396      // It was a real error; we must depend on the caller to finish the job.
2403 2397      // Register rdx = -1 * number of *remaining* oops, r14 = *total* oops.
2404 2398      // Emit GC store barriers for the oops we have copied (r14 + rdx),
2405 2399      // and report their number to the caller.
2406      -    assert_different_registers(rax, r14_length, count, to, end_to, rcx);
2407      -    __ lea(end_to, to_element_addr);
2408      -    __ addptr(end_to, -heapOopSize);      // make an inclusive end pointer
2409      -    gen_write_ref_array_post_barrier(to, end_to, rscratch1);
2410      -    __ movptr(rax, r14_length);           // original oops
2411      -    __ addptr(rax, count);                // K = (original - remaining) oops
2412      -    __ notptr(rax);                       // report (-1^K) to caller
2413      -    __ jmp(L_done);
     2400 +    assert_different_registers(rax, r14_length, count, to, end_to, rcx, rscratch1);
     2401 +    Label L_post_barrier;
     2402 +    __ addptr(r14_length, count);     // K = (original - remaining) oops
     2403 +    __ movptr(rax, r14_length);       // save the value
     2404 +    __ notptr(rax);                   // report (-1^K) to caller (does not affect flags)
     2405 +    __ jccb(Assembler::notZero, L_post_barrier);
     2406 +    __ jmp(L_done); // K == 0, nothing was copied, skip post barrier
2414 2407  
2415 2408      // Come here on success only.
2416 2409      __ BIND(L_do_card_marks);
2417      -    __ addptr(end_to, -heapOopSize);         // make an inclusive end pointer
2418      -    gen_write_ref_array_post_barrier(to, end_to, rscratch1);
2419      -    __ xorptr(rax, rax);                  // return 0 on success
     2410 +    __ xorptr(rax, rax);              // return 0 on success
2420 2411  
     2412 +    __ BIND(L_post_barrier);
     2413 +    gen_write_ref_array_post_barrier(to, r14_length, rscratch1);
     2414 +
2421 2415      // Common exit point (success or failure).
2422 2416      __ BIND(L_done);
2423 2417      __ movptr(r13, Address(rsp, saved_r13_offset * wordSize));
2424 2418      __ movptr(r14, Address(rsp, saved_r14_offset * wordSize));
2425 2419      restore_arg_regs();
2426 2420      inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr); // Update counter after rscratch1 is free
2427 2421      __ leave(); // required for proper stackwalking of RuntimeStub frame
2428 2422      __ ret(0);
2429 2423  
2430 2424      return start;
↓ open down ↓ 1411 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX