# HG changeset patch # User sgoldman # Date 1207919924 25200 # Node ID deadee49286e6003a2385bd4efb3da63730179b5 # Parent 9f4457a14b586f37f55903271122afcf2b1cf54e 6644928: Internal Error (src/share/vm/code/relocInfo.hpp:1089) Summary: Cardtable base can be zero, ExternalAddress can't take a NULL. diff -r 9f4457a14b58 -r deadee49286e src/cpu/x86/vm/assembler_x86_32.cpp --- a/src/cpu/x86/vm/assembler_x86_32.cpp Wed Apr 09 15:10:22 2008 -0700 +++ b/src/cpu/x86/vm/assembler_x86_32.cpp Fri Apr 11 06:18:44 2008 -0700 @@ -3405,10 +3405,16 @@ assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); CardTableModRefBS* ct = (CardTableModRefBS*)bs; assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); - ExternalAddress cardtable((address)ct->byte_map_base); - Address index(noreg, obj, Address::times_1); - - movb(as_Address(ArrayAddress(cardtable, index)), 0); + + // The calculation for byte_map_base is as follows: + // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); + // So this essentially converts an address to a displacement and + // it will never need to be relocated. On 64bit however the value may be too + // large for a 32bit displacement + + intptr_t disp = (intptr_t) ct->byte_map_base; + Address cardtable(noreg, obj, Address::times_1, disp); + movb(cardtable, 0); } diff -r 9f4457a14b58 -r deadee49286e src/cpu/x86/vm/assembler_x86_64.cpp --- a/src/cpu/x86/vm/assembler_x86_64.cpp Wed Apr 09 15:10:22 2008 -0700 +++ b/src/cpu/x86/vm/assembler_x86_64.cpp Fri Apr 11 06:18:44 2008 -0700 @@ -4427,9 +4427,32 @@ assert(bs->kind() == BarrierSet::CardTableModRef, "Wrong barrier set kind"); CardTableModRefBS* ct = (CardTableModRefBS*)bs; assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code"); - ExternalAddress cardtable((address)ct->byte_map_base); - Address index(noreg, obj, Address::times_1); - movb(as_Address(ArrayAddress(cardtable, index)), 0); + + // The calculation for byte_map_base is as follows: + // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift); + // So this essentially converts an address to a displacement and + // it will never need to be relocated. On 64bit however the value may be too + // large for a 32bit displacement + + intptr_t disp = (intptr_t) ct->byte_map_base; + if (is_simm32(disp)) { + Address cardtable(noreg, obj, Address::times_1, disp); + movb(cardtable, 0); + } else { + // By doing it as an ExternalAddress disp could be converted to a rip-relative + // displacement and done in a single instruction given favorable mapping and + // a smarter version of as_Address. Worst case it is two instructions which + // is no worse off then loading disp into a register and doing as a simple + // Address() as above. + // We can't do as ExternalAddress as the only style since if disp == 0 we'll + // assert since NULL isn't acceptable in a reloci (see 6644928). In any case + // in some cases we'll get a single instruction version. + + ExternalAddress cardtable((address)disp); + Address index(noreg, obj, Address::times_1); + movb(as_Address(ArrayAddress(cardtable, index)), 0); + } + } void MacroAssembler::c2bool(Register x) {