--- /dev/null 2017-03-07 11:44:12.271151064 +0100 +++ new/src/cpu/x86/vm/gc/shared/cardTableModRefBSCodeGen_x86.cpp 2017-04-25 16:46:08.243171945 +0200 @@ -0,0 +1,132 @@ + +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "asm/macroAssembler.inline.hpp" +#include "gc/shared/barrierSet.hpp" +#include "gc/shared/cardTable.hpp" +#include "gc/shared/cardTableModRefBS.hpp" +#include "gc/shared/cardTableModRefBSCodeGen.hpp" +#include "gc/shared/collectedHeap.hpp" +#include "interpreter/interp_masm.hpp" + +#define __ masm-> + +#ifdef PRODUCT +#define BLOCK_COMMENT(str) /* nothing */ +#else +#define BLOCK_COMMENT(str) __ block_comment(str) +#endif + +#define BIND(label) bind(label); BLOCK_COMMENT(#label ":") + +#define TIMES_OOP (UseCompressedOops ? Address::times_4 : Address::times_8) + +void CardTableModRefBSCodeGen::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp) { + BarrierSet *bs = Universe::heap()->barrier_set(); + CardTableModRefBS* ct = barrier_set_cast(bs); + assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code"); + + Label L_loop; + const Register end = count; + + __ leaq(end, Address(addr, count, TIMES_OOP, 0)); // end == addr+count*oop_size + __ subptr(end, BytesPerHeapOop); // end - 1 to make inclusive + __ shrptr(addr, CardTable::card_shift); + __ shrptr(end, CardTable::card_shift); + __ subptr(end, addr); // end --> cards count + + int64_t disp = (int64_t) ct->card_table()->byte_map_base(); + __ mov64(tmp, disp); + __ addptr(addr, tmp); +__ BIND(L_loop); + __ movb(Address(addr, count, Address::times_1), 0); + __ decrement(count); + __ jcc(Assembler::greaterEqual, L_loop); +} + +void CardTableModRefBSCodeGen::store_check(MacroAssembler* masm, Register obj, Address dst) { + // Does a store check for the oop in register obj. The content of + // register obj is destroyed afterwards. + BarrierSet* bs = Universe::heap()->barrier_set(); + + CardTableModRefBS* ct = barrier_set_cast(bs); + assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code"); + + __ shrptr(obj, CardTable::card_shift); + + Address card_addr; + + // 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->card_table()->byte_map_base(); + if (__ is_simm32(disp)) { + card_addr = Address(noreg, obj, Address::times_1, disp); + } 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. However, 'ExternalAddress' generates a relocation + // entry and that entry is not properly handled by the relocation code. + AddressLiteral cardtable((address)ct->card_table()->byte_map_base(), relocInfo::none); + Address index(noreg, obj, Address::times_1); + card_addr = __ as_Address(ArrayAddress(cardtable, index)); + } + + int dirty = CardTable::dirty_card_val(); + if (UseCondCardMark) { + Label L_already_dirty; + if (UseConcMarkSweepGC) { + __ membar(Assembler::StoreLoad); + } + __ cmpb(card_addr, dirty); + __ jcc(Assembler::equal, L_already_dirty); + __ movb(card_addr, dirty); + __ bind(L_already_dirty); + } else { + __ movb(card_addr, dirty); + } +} + +void CardTableModRefBSCodeGen::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type, + Address dst, Register val, Register tmp1, Register tmp2) { + bool on_array = (decorators & ACCESS_ON_ARRAY) != 0; + bool on_anonymous = (decorators & ACCESS_ON_ANONYMOUS) != 0; + bool precise = on_array || on_anonymous; + if (val == noreg) { + __ store_heap_oop_null(dst); + } else { + __ store_heap_oop(dst, val); + // flatten object address if needed + if (!precise || (dst.index() == noreg && dst.disp() == 0)) { + store_check(masm, dst.base(), dst); + } else { + __ lea(tmp1, dst); + store_check(masm, tmp1, dst); + } + } +}