/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Common Public License (CPL);
* 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/cpl1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.baseline.ia32;
import org.jikesrvm.VM_Configuration;
import org.jikesrvm.ArchitectureSpecific.VM_Assembler;
import org.jikesrvm.ia32.VM_BaselineConstants;
import org.jikesrvm.objectmodel.VM_ObjectModel;
import org.jikesrvm.runtime.VM_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 VM_WriteBarrier.
*/
class VM_Barriers implements VM_BaselineConstants {
static void compileArrayStoreBarrier(VM_Assembler asm) {
// on entry java stack contains ...|target_array_ref|array_index|ref_to_store|
// SP -> ref_to_store, SP+8 -> target_ref
Offset of8 = Offset.fromIntSignExtend(8);
asm.emitPUSH_RegDisp(SP, of8);
asm.emitPUSH_RegDisp(SP, of8); // Push what was originally (SP, 4)
asm.emitPUSH_RegDisp(SP, of8); // Push what was originally (SP, 0)
genParameterRegisterLoad(asm, 3);
asm.emitCALL_RegDisp(JTOC, VM_Entrypoints.arrayStoreWriteBarrierMethod.getOffset());
}
static void compilePutfieldBarrier(VM_Assembler asm, byte reg, int locationMetadata) {
// on entry java stack contains ...|target_ref|ref_to_store|
// SP -> ref_to_store, SP+4 -> target_ref
Offset of4 = Offset.fromIntSignExtend(4);
Offset of8 = Offset.fromIntSignExtend(8);
genNullCheck(asm, 4);
asm.emitPUSH_RegDisp(SP, of4);
asm.emitPUSH_Reg(reg);
asm.emitPUSH_RegDisp(SP, of8); // Push what was originally (SP, 0)
asm.emitPUSH_Imm(locationMetadata);
genParameterRegisterLoad(asm, 4);
asm.emitCALL_RegDisp(JTOC, VM_Entrypoints.putfieldWriteBarrierMethod.getOffset());
}
static void compilePutfieldBarrierImm(VM_Assembler asm, Offset fieldOffset, int locationMetadata) {
// on entry java stack contains ...|target_ref|ref_to_store|
// SP -> ref_to_store, SP+4 -> target_ref
Offset of4 = Offset.fromIntSignExtend(4);
Offset of8 = Offset.fromIntSignExtend(8);
genNullCheck(asm, 4);
asm.emitPUSH_RegDisp(SP, of4);
asm.emitPUSH_Imm(fieldOffset.toInt());
asm.emitPUSH_RegDisp(SP, of8); // Push what was originally (SP, 0)
asm.emitPUSH_Imm(locationMetadata);
genParameterRegisterLoad(asm, 4);
asm.emitCALL_RegDisp(JTOC, VM_Entrypoints.putfieldWriteBarrierMethod.getOffset());
}
static void compilePutstaticBarrier(VM_Assembler asm, byte reg, int locationMetadata) {
// on entry java stack contains ...|ref_to_store|
// SP -> ref_to_store
Offset of4 = Offset.fromIntSignExtend(4);
asm.emitPUSH_Reg(reg);
asm.emitPUSH_RegDisp(SP, of4);
asm.emitPUSH_Imm(locationMetadata);
genParameterRegisterLoad(asm, 3);
asm.emitCALL_RegDisp(JTOC, VM_Entrypoints.putstaticWriteBarrierMethod.getOffset());
}
static void compilePutstaticBarrierImm(VM_Assembler asm, Offset fieldOffset, int locationMetadata) {
// on entry java stack contains ...|ref_to_store|
// SP -> ref_to_store
Offset of4 = Offset.fromIntSignExtend(4);
asm.emitPUSH_Imm(fieldOffset.toInt());
asm.emitPUSH_RegDisp(SP, of4);
asm.emitPUSH_Imm(locationMetadata);
genParameterRegisterLoad(asm, 3);
asm.emitCALL_RegDisp(JTOC, VM_Entrypoints.putstaticWriteBarrierMethod.getOffset());
}
/**
* Generate a cheap nullcheck by attempting to load the TIB of the object
* at the given offset to SP.
*/
private static void genNullCheck(VM_Assembler asm, int offset) {
asm.emitMOV_Reg_RegDisp(T1, SP, Offset.fromIntZeroExtend(offset));
VM_ObjectModel.baselineEmitLoadTIB(asm, T1, T1, false);
}
static void compileModifyCheck(VM_Assembler asm, int offset) {
if (!VM_Configuration.ExtremeAssertions) return;
// on entry java stack contains ... [SP+offset] -> target_ref
// on exit: stack is the same
asm.emitPUSH_RegDisp(SP, Offset.fromIntSignExtend(offset)); // dup
genParameterRegisterLoad(asm, 1);
asm.emitCALL_RegDisp(JTOC, VM_Entrypoints.modifyCheckMethod.getOffset());
}
/**
* (Taken from VM_Compiler.java)
*
* Copy parameters from operand stack into registers.
* Assumption: parameters are layed out on the stack in order
* with SP pointing to the last parameter.
* Also, this method is called before the generation of a helper method call.
* Assumption: no floating-point parameters.
* @param params number of parameter words (including "this" if any).
*/
private static void genParameterRegisterLoad(VM_Assembler asm, int params) {
if (0 < NUM_PARAMETER_GPRS) {
asm.emitMOV_Reg_RegDisp(T0, SP, Offset.fromIntZeroExtend((params - 1) << LG_WORDSIZE));
}
if (1 < params && 1 < NUM_PARAMETER_GPRS) {
asm.emitMOV_Reg_RegDisp(T1, SP, Offset.fromIntZeroExtend((params - 2) << LG_WORDSIZE));
}
}
}