/* * Copyright (c) 2018, 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. *
*/
// First we test whether marking is in progress.
BasicType flag_type; bool patch = (decorators & C1_NEEDS_PATCHING) != 0; bool do_load = pre_val == LIR_OprFact::illegalOpr; if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
flag_type = T_INT;
} else {
guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption"); // Use unsigned type T_BOOLEAN here rather than signed T_BYTE since some platforms, eg. ARM, // need to use unsigned instructions to use the large offset to load the satb_mark_queue.
flag_type = T_BOOLEAN;
}
LIR_Opr thrd = gen->getThreadPointer();
LIR_Address* mark_active_flag_addr = new LIR_Address(thrd,
in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()),
flag_type); // Read the marking-in-progress flag. // Note: When loading pre_val requires patching, i.e. do_load == true && // patch == true, a safepoint can occur while patching. This makes the // pre-barrier non-atomic and invalidates the marking-in-progress check. // Therefore, in the presence of patching, we must repeat the same // marking-in-progress checking before calling into the Runtime. For // simplicity, we do this check unconditionally (regardless of the presence // of patching) in the runtime stub // (G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub).
LIR_Opr flag_val = gen->new_register(T_INT);
__ load(mark_active_flag_addr, flag_val);
__ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
// If the "new_val" is a constant NULL, no barrier is necessary. if (new_val->is_constant() &&
new_val->as_constant_ptr()->as_jobject() == NULL) return;
if (!new_val->is_register()) {
LIR_Opr new_val_reg = gen->new_register(T_OBJECT); if (new_val->is_constant()) {
__ move(new_val, new_val_reg);
} else {
__ leal(new_val, new_val_reg);
}
new_val = new_val_reg;
}
assert(new_val->is_register(), "must be a register at this point");
if (addr->is_address()) {
LIR_Address* address = addr->as_address_ptr();
LIR_Opr ptr = gen->new_pointer_register(); if (!address->index()->is_valid() && address->disp() == 0) {
__ move(address->base(), ptr);
} else {
assert(address->disp() != max_jint, "lea doesn't support patched addresses!");
__ leal(addr, ptr);
}
addr = ptr;
}
assert(addr->is_register(), "must be a register at this point");
if (access.is_oop() && (is_weak || is_phantom || is_anonymous)) { // Register the value in the referent field with the pre-barrier
LabelObj *Lcont_anonymous; if (is_anonymous) {
Lcont_anonymous = new LabelObj();
generate_referent_check(access, Lcont_anonymous);
}
pre_barrier(access, LIR_OprFact::illegalOpr /* addr_opr */,
result /* pre_val */, access.patch_emit_info() /* info */); if (is_anonymous) {
__ branch_destination(Lcont_anonymous->label());
}
}
}
class C1G1PreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure { virtual OopMapSet* generate_code(StubAssembler* sasm) {
G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
bs->generate_c1_pre_barrier_runtime_stub(sasm); return NULL;
}
};
class C1G1PostBarrierCodeGenClosure : public StubAssemblerCodeGenClosure { virtual OopMapSet* generate_code(StubAssembler* sasm) {
G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
bs->generate_c1_post_barrier_runtime_stub(sasm); return NULL;
}
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.