RFR: 8133646: Internal Error: x86/vm/macroAssembler_x86.cpp:886 DEBUG MESSAGE: StubRoutines::call_stub: threads must correspond
David Holmes
david.holmes at oracle.com
Wed Aug 26 22:56:57 UTC 2015
On 26/08/2015 11:04 PM, Daniel D. Daugherty wrote:
>
> On 8/25/15 8:17 PM, David Holmes wrote:
>> Hi Coleen,
>>
>> Thanks for the review.
>>
>> On 26/08/2015 2:28 AM, Coleen Phillimore wrote:
>>>
>>> David,
>>> Can you add this duplicate code into a verify_thread() function? This
>>> would help if we are ever able to combine common code in
>>> stubRoutines_x86_32/64.cpp
>>
>> I'm so grateful you posed that as a question not a request. :) Answer:
>> no.
>>
>> The duplicated structure is pre-existing, and the error messages
>> differ so the context would have to be passed in. I'm totally
>> unfamiliar with playing in the macroassembler so would be unsure how
>> to factor this out into a separate function without messing up
>> register usage, or using the correct "variables" from the "calling
>> context".
>>
>> Also note that for some reason these sanity checks don't exist on
>> x86_32, nor sparc (only aarch64 also has it presumably based on the
>> x86_64 version). I think the time to factor this out would be if/when
>> we do the code combining.
>
> We do have a similar check on x86_32:
>
> src/cpu/x86/vm/stubGenerator_x86_32.cpp:
>
> 343 address generate_catch_exception() {
> <snip>
> 351 #ifdef ASSERT
> 352 // verify that threads correspond
> 353 { Label L;
> 354 __ get_thread(rbx);
> 355 __ cmpptr(rbx, rcx);
> 356 __ jcc(Assembler::equal, L);
> 357 __ stop("StubRoutines::catch_exception: threads must
> correspond");
> 358 __ bind(L);
> 359 }
> 360 #endif
>
> The check is much simpler because we don't have enough registers
> on x86_32 to set aside one for the thread.
Thanks Dan. Yes I misspoke. I had seen this but as it only has one check
there was no need for any additional diagnostics.
> On SPARC we have this:
>
> src/cpu/sparc/vm/stubGenerator_sparc.cpp:
>
> 322 address generate_catch_exception() {
> <snip>
> 326 // verify that thread corresponds
> 327 __ verify_thread();
>
> There are lots of other calls to verify_thread() sprinkled
> through the SPARC code...
>
> src/cpu/sparc/vm/macroAssembler_sparc.cpp:
>
> 398 void MacroAssembler::verify_thread() {
> 399 if (VerifyThread) {
> 400 // NOTE: this chops off the heads of the 64-bit O registers.
> 401 #ifdef CC_INTERP
> 402 save_frame(0);
> 403 #else
> 404 // make sure G2_thread contains the right value
> 405 save_frame_and_mov(0, Lmethod, Lmethod); // to avoid
> clobbering O0
> (and propagate Lmethod for -Xprof)
> 406 mov(G1, L1); // avoid clobbering G1
> 407 // G2 saved below
> 408 mov(G3, L3); // avoid clobbering G3
> 409 mov(G4, L4); // avoid clobbering G4
> 410 mov(G5_method, L5); // avoid clobbering G5_method
> 411 #endif /* CC_INTERP */
> 412 #if defined(COMPILER2) && !defined(_LP64)
> 413 // Save & restore possible 64-bit Long arguments in G-regs
> 414 srlx(G1,32,L0);
> 415 srlx(G4,32,L6);
> 416 #endif
> 417 call(CAST_FROM_FN_PTR(address,verify_thread_subroutine),
> relocInfo::
> runtime_call_type);
> 418 delayed()->mov(G2_thread, O0);
> 419
> 420 mov(L1, G1); // Restore G1
> 421 // G2 restored below
> 422 mov(L3, G3); // restore G3
> 423 mov(L4, G4); // restore G4
> 424 mov(L5, G5_method); // restore G5_method
> 425 #if defined(COMPILER2) && !defined(_LP64)
> 426 // Save & restore possible 64-bit Long arguments in G-regs
> 427 sllx(L0,32,G2); // Move old high G1 bits high
> in G2
> 428 srl(G1, 0,G1); // Clear current high G1 bits
> 429 or3 (G1,G2,G1); // Recover 64-bit G1
> 430 sllx(L6,32,G2); // Move old high G4 bits high
> in G2
> 431 srl(G4, 0,G4); // Clear current high G4 bits
> 432 or3 (G4,G2,G4); // Recover 64-bit G4
> 433 #endif
> 434 restore(O0, 0, G2_thread);
> 435 }
> 436 }
>
> Does anyone else have a headache after reading verify_thread()? :-)
I hadn't caught this - so thanks very much. Despite the apparent
complexity the crux of the above is the call to:
static Thread* verify_thread_subroutine(Thread* gthread_value) {
Thread* correct_value = ThreadLocalStorage::thread();
guarantee(gthread_value == correct_value, "G2_thread value must be
the thread");
return correct_value;
}
which only does the same single-check that the x32 version does.
So bottom line: I'll push the x64 additions.
Thanks again,
David
> Dan
>
>
>>
>> Thanks,
>> David
>>
>>> Thanks,
>>> Coleen
>>>
>>> On 8/25/15 2:07 AM, David Holmes wrote:
>>>> Bug: https://bugs.openjdk.java.net/browse/JDK-8133646
>>>>
>>>> webrev: http://cr.openjdk.java.net/~dholmes/8133646/webrev/
>>>>
>>>> The error raised in this bug was not reproducible - it was only seen
>>>> on one machine which was subsequently re-imaged to run Windows. A
>>>> similar Solaris system did not reproduce the bug.
>>>>
>>>> Rather than just close this as not-reproducible I want to push the
>>>> enhanced diagnostics that Vladimir provided here:
>>>>
>>>> http://mail.openjdk.java.net/pipermail/hotspot-dev/2015-August/019667.html
>>>>
>>>>
>>>>
>>>> which I've added to the two chunks of code that perform this thread
>>>> sanity check.
>>>>
>>>> Thanks,
>>>> David
>>>
>
More information about the hotspot-dev
mailing list