/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.baseline.ppc;
import static org.jikesrvm.ppc.BaselineConstants.F0;
import static org.jikesrvm.ppc.BaselineConstants.S0;
import static org.jikesrvm.ppc.BaselineConstants.T0;
import static org.jikesrvm.ppc.BaselineConstants.T1;
import static org.jikesrvm.ppc.BaselineConstants.T2;
import static org.jikesrvm.ppc.BaselineConstants.T3;
import static org.jikesrvm.ppc.BaselineConstants.T4;
import org.jikesrvm.VM;
import org.jikesrvm.classloader.MethodReference;
import org.jikesrvm.classloader.NormalMethod;
import org.jikesrvm.compilers.common.assembler.ppc.Assembler;
import org.jikesrvm.runtime.Entrypoints;
import org.vmmagic.unboxed.Offset;
/**
* Class called from baseline compiler to generate architecture specific
* write barrier for generational garbage collectors. For baseline
* compiled methods, the write barrier calls methods of WriteBarrier.
*/
class Barriers {
// on entry java stack contains ...|array_ref|index|value|
static void compileArrayStoreBarrier(BaselineCompilerImpl comp) {
comp.emit_resolved_invokestatic((MethodReference)Entrypoints.aastoreMethod.getMemberRef());
}
// on entry java stack contains ...|array_ref|index|value|
static void compileArrayStoreBarrierByte(BaselineCompilerImpl comp) {
comp.emit_resolved_invokestatic((MethodReference) Entrypoints.byteArrayWriteBarrierMethod.getMemberRef());
}
// on entry java stack contains ...|array_ref|index|value|
static void compileArrayStoreBarrierChar(BaselineCompilerImpl comp) {
comp.emit_resolved_invokestatic((MethodReference) Entrypoints.charArrayWriteBarrierMethod.getMemberRef());
}
// on entry java stack contains ...|array_ref|index|value|
static void compileArrayStoreBarrierDouble(BaselineCompilerImpl comp) {
comp.emit_resolved_invokestatic((MethodReference) Entrypoints.doubleArrayWriteBarrierMethod.getMemberRef());
}
// on entry java stack contains ...|array_ref|index|value|
static void compileArrayStoreBarrierFloat(BaselineCompilerImpl comp) {
comp.emit_resolved_invokestatic((MethodReference) Entrypoints.floatArrayWriteBarrierMethod.getMemberRef());
}
// on entry java stack contains ...|array_ref|index|value|
static void compileArrayStoreBarrierInt(BaselineCompilerImpl comp) {
comp.emit_resolved_invokestatic((MethodReference) Entrypoints.intArrayWriteBarrierMethod.getMemberRef());
}
// on entry java stack contains ...|array_ref|index|value|
static void compileArrayStoreBarrierLong(BaselineCompilerImpl comp) {
comp.emit_resolved_invokestatic((MethodReference) Entrypoints.longArrayWriteBarrierMethod.getMemberRef());
}
// on entry java stack contains ...|array_ref|index|value|
static void compileArrayStoreBarrierShort(BaselineCompilerImpl comp) {
comp.emit_resolved_invokestatic((MethodReference) Entrypoints.shortArrayWriteBarrierMethod.getMemberRef());
}
// on entry java stack contains ...|target_ref|ref_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrier(BaselineCompilerImpl comp, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.objectFieldWriteBarrierMethod.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 1); // object base
asm.emitNullCheck(T0);
comp.peekAddr(T1, 0); // value to store
asm.emitLVAL(T3, locationMetadata);
asm.emitBCCTRL(); // MemoryManager.putfieldWriteBarrier(T0,T1,T2,T3)
}
// on entry java stack contains ...|target_ref|ref_to_store|
static void compilePutfieldBarrierImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.objectFieldWriteBarrierMethod.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 1); // object base
asm.emitNullCheck(T0);
asm.emitLVALAddr(T2, fieldOffset); // offset
comp.peekAddr(T1, 0); // value to store
asm.emitLVAL(T3, locationMetadata);
asm.emitBCCTRL(); // MemoryManager.putfieldWriteBarrier(T0,T1,T2,T3)
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
private static void putfieldStoreBarrierHelper(BaselineCompilerImpl comp, int locationMetadata, NormalMethod barrier) {
// value_to_store is an Int or smaller and takes up 1 stack slot
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, barrier.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 1); // store target_ref in T0
asm.emitNullCheck(T0);
comp.peekInt(T1, 0); // store value_to_store in T1
asm.emitLVAL(T3, locationMetadata); // store locationMetaData in T3
asm.emitBCCTRL(); // call barrier with parameters in (T0,T1,T2,T3)
comp.discardSlots(2); // clean up stack
}
// on entry java stack contains ...|target_ref|value_to_store|
private static void putfieldStoreBarrierHelper(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata,
NormalMethod barrier) {
// value_to_store is an Int or smaller and takes up 1 stack slot
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, barrier.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 1); // store target_ref in T0
asm.emitNullCheck(T0);
comp.peekInt(T1, 0); // store value_to_store in T1
asm.emitLVAL(T3, locationMetadata); // store locationMetaData in T3
asm.emitLVALAddr(T2, fieldOffset); // store offset in T2
asm.emitBCCTRL(); // call barrier with parameters in (T0,T1,T2,T3)
comp.discardSlots(2); // clean up stack
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierBoolean(BaselineCompilerImpl comp, int locationMetadata) {
putfieldStoreBarrierHelper(comp, locationMetadata, Entrypoints.booleanFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierBooleanImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
putfieldStoreBarrierHelper(comp, fieldOffset, locationMetadata, Entrypoints.booleanFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierByte(BaselineCompilerImpl comp, int locationMetadata) {
putfieldStoreBarrierHelper(comp, locationMetadata, Entrypoints.byteFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierByteImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
putfieldStoreBarrierHelper(comp, fieldOffset, locationMetadata, Entrypoints.byteFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierChar(BaselineCompilerImpl comp, int locationMetadata) {
putfieldStoreBarrierHelper(comp, locationMetadata, Entrypoints.charFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierCharImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
putfieldStoreBarrierHelper(comp, fieldOffset, locationMetadata, Entrypoints.charFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierDouble(BaselineCompilerImpl comp, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.doubleFieldWriteBarrierMethod.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 2); // store target_ref in T0
asm.emitNullCheck(T0);
comp.peekDouble(F0, 0); // store value_to_store in F0
asm.emitMR(T1, T2); // move offset in T2 to T1
asm.emitLVAL(T2, locationMetadata); // store locationMetaData in T2
asm.emitBCCTRL(); // call barrier with parameters in (T0,F0,T1,T2)
comp.discardSlots(3); // clean up stack
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierDoubleImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.doubleFieldWriteBarrierMethod.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 2); // store target_ref in T0
asm.emitNullCheck(T0);
comp.peekDouble(F0, 0); // store value_to_store in F0
asm.emitLVALAddr(T1, fieldOffset); // store offset in T1
asm.emitLVAL(T2, locationMetadata); // store locationMetaData in T2
asm.emitBCCTRL(); // call barrier with parameters in (T0,F0,T1,T2)
comp.discardSlots(3); // clean up stack
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierFloat(BaselineCompilerImpl comp, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.floatFieldWriteBarrierMethod.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 1); // store target_ref in T0
asm.emitNullCheck(T0);
comp.peekFloat(F0, 0); // store value_to_store in F0
asm.emitMR(T1, T2); // copy offset in T2 to T1
asm.emitLVAL(T2, locationMetadata); // store locationMetaData in T2
asm.emitBCCTRL(); // call barrier with parameters in (T0,F0,T1,T2)
comp.discardSlots(2); // clean up stack
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierFloatImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.floatFieldWriteBarrierMethod.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 1); // store target_ref in T0
asm.emitNullCheck(T0);
comp.peekFloat(F0, 0); // store value_to_store in F0
asm.emitLVALAddr(T1, fieldOffset); // store offset in T1
asm.emitLVAL(T2, locationMetadata); // store locationMetaData in T2
asm.emitBCCTRL(); // call barrier with parameters in (T0,F0,T1,T2)
comp.discardSlots(2); // clean up stack
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierInt(BaselineCompilerImpl comp, int locationMetadata) {
putfieldStoreBarrierHelper(comp, locationMetadata, Entrypoints.intFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierIntImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
putfieldStoreBarrierHelper(comp, fieldOffset, locationMetadata, Entrypoints.intFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierLong(BaselineCompilerImpl comp, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.longFieldWriteBarrierMethod.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 2); // store target_ref in T0
asm.emitNullCheck(T0);
if (VM.BuildFor64Addr) {
comp.peekLong(T1, T1, 0); // 64 bit store of value into T1
// offset is fine in T2
asm.emitLVAL(T3, locationMetadata); // store locationMetaData in T3
asm.emitBCCTRL(); // call barrier with parameters in (T0,T1,T2,T3)
} else {
// GPR's are only 32 bits wide
asm.emitMR(T3, T2); // copy offset into T3
comp.peekLong(T1, T2, 0); // peek Long into T1 and T2
asm.emitLVAL(T4, locationMetadata); // store locationMetaData in T4
asm.emitBCCTRL(); // call barrier with parameters in (T0,{T1,T2},T3,T4)
}
comp.discardSlots(3); // clean up stack
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierLongImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.longFieldWriteBarrierMethod.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 2); // store target_ref in T0
asm.emitNullCheck(T0);
if (VM.BuildFor64Addr) {
comp.peekLong(T1, T1, 0); // 64 bit store of value into T1
asm.emitLVALAddr(T2, fieldOffset); // store offset in T2
asm.emitLVAL(T3, locationMetadata); // store locationMetaData in T3
asm.emitBCCTRL(); // call barrier with parameters in (T0,T1,T2,T3)
} else {
// GPR's are only 32 bits wide
comp.peekLong(T1, T2, 0); // peek Long into T1 and T2
asm.emitLVALAddr(T3, fieldOffset); // store offset in T3
asm.emitLVAL(T4, locationMetadata); // store locationMetaData in T4
asm.emitBCCTRL(); // call barrier with parameters in (T0,{T1,T2},T3,T4)
}
comp.discardSlots(3); // clean up stack
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierShort(BaselineCompilerImpl comp, int locationMetadata) {
putfieldStoreBarrierHelper(comp, locationMetadata, Entrypoints.shortFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierShortImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
putfieldStoreBarrierHelper(comp, fieldOffset, locationMetadata, Entrypoints.shortFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierWord(BaselineCompilerImpl comp, int locationMetadata) {
putfieldUnboxedStoreBarrierHelper(comp, locationMetadata, Entrypoints.wordFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierWordImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
putfieldUnboxedStoreBarrierHelper(comp, fieldOffset, locationMetadata, Entrypoints.wordFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierAddress(BaselineCompilerImpl comp, int locationMetadata) {
putfieldUnboxedStoreBarrierHelper(comp, locationMetadata, Entrypoints.addressFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierAddressImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
putfieldUnboxedStoreBarrierHelper(comp, fieldOffset, locationMetadata, Entrypoints.addressFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierOffset(BaselineCompilerImpl comp, int locationMetadata) {
putfieldUnboxedStoreBarrierHelper(comp, locationMetadata, Entrypoints.offsetFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierOffsetImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
putfieldUnboxedStoreBarrierHelper(comp, fieldOffset, locationMetadata, Entrypoints.offsetFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
static void compilePutfieldBarrierExtent(BaselineCompilerImpl comp, int locationMetadata) {
putfieldUnboxedStoreBarrierHelper(comp, locationMetadata, Entrypoints.extentFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
static void compilePutfieldBarrierExtentImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
putfieldUnboxedStoreBarrierHelper(comp, fieldOffset, locationMetadata, Entrypoints.extentFieldWriteBarrierMethod);
}
// on entry java stack contains ...|target_ref|value_to_store|
// T2 already contains the offset of the field on entry
private static void putfieldUnboxedStoreBarrierHelper(BaselineCompilerImpl comp, int locationMetadata, NormalMethod barrier) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, barrier.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 1); // store target_ref in T0
asm.emitNullCheck(T0);
comp.peekUnboxed(T1, 0); // value to store
asm.emitLVAL(T3, locationMetadata);
asm.emitBCCTRL(); // call barrier with parameters in (T0,T1,T2,T3)
comp.discardSlots(2);
}
// on entry java stack contains ...|target_ref|value_to_store|
private static void putfieldUnboxedStoreBarrierHelper(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata,
NormalMethod barrier) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, barrier.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 1); // store target_ref in T0
asm.emitNullCheck(T0);
asm.emitLVALAddr(T2, fieldOffset); // offset
comp.peekUnboxed(T1, 0); // value to store
asm.emitLVAL(T3, locationMetadata);
asm.emitBCCTRL();
comp.discardSlots(2); // clean up stack
}
// on entry java stack contains ...|ref_to_store|
// T1 already contains the offset of the field on entry
static void compilePutstaticBarrier(BaselineCompilerImpl comp, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.objectStaticWriteBarrierMethod.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 0); // value to store
asm.emitLVAL(T2, locationMetadata);
asm.emitBCCTRL(); // MemoryManager.putstaticWriteBarrier(T0,T1,T2)
}
// on entry java stack contains ...|ref_to_store|
static void compilePutstaticBarrierImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.objectStaticWriteBarrierMethod.getOffset());
asm.emitMTCTR(S0);
asm.emitLVALAddr(T1, fieldOffset); // offset
comp.peekAddr(T0, 0); // value to store
asm.emitLVAL(T2, locationMetadata);
asm.emitBCCTRL(); // MemoryManager.putstaticWriteBarrier(T0,T1,T2)
}
// on entry T0, T1 already contain the appropriate values
static void compileArrayLoadBarrier(BaselineCompilerImpl comp) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.objectArrayReadBarrierMethod.getOffset());
asm.emitMTCTR(S0);
asm.emitBCCTRL(); // MemoryManager.arrayLoadReadBarrier(T0,T1)
}
// on entry java stack contains ...|source_ref|
// T1 already contains the offset of the field on entry
static void compileGetfieldBarrier(BaselineCompilerImpl comp, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.objectFieldReadBarrierMethod.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 0); // object base
asm.emitNullCheck(T0);
asm.emitLVAL(T2, locationMetadata);
asm.emitBCCTRL(); // MemoryManager.getfieldReadBarrier(T0,T1,T2)
}
// on entry java stack contains ...|source_ref|
static void compileGetfieldBarrierImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.objectFieldReadBarrierMethod.getOffset());
asm.emitMTCTR(S0);
comp.peekAddr(T0, 0); // object base
asm.emitNullCheck(T0);
asm.emitLVALAddr(T1, fieldOffset); // offset
asm.emitLVAL(T2, locationMetadata);
asm.emitBCCTRL(); // MemoryManager.getfieldReadBarrier(T0,T1,T2)
}
// on entry java stack contains ...|
// T0 already contains the offset of the field on entry
static void compileGetstaticBarrier(BaselineCompilerImpl comp, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.objectStaticReadBarrierMethod.getOffset());
asm.emitMTCTR(S0);
asm.emitLVAL(T1, locationMetadata);
asm.emitBCCTRL(); // MemoryManager.getstaticReadBarrier(T0,T1)
}
// on entry java stack contains ...|
static void compileGetstaticBarrierImm(BaselineCompilerImpl comp, Offset fieldOffset, int locationMetadata) {
Assembler asm = comp.asm;
asm.emitLAddrToc(S0, Entrypoints.objectStaticReadBarrierMethod.getOffset());
asm.emitMTCTR(S0);
asm.emitLVALAddr(T0, fieldOffset); // offset
asm.emitLVAL(T1, locationMetadata);
asm.emitBCCTRL(); // MemoryManager.getstaticReadBarrier(T0,T1)
}
}