aboutsummaryrefslogtreecommitdiff
path: root/vm/compiler/codegen/arm/CodegenDriver.c
diff options
context:
space:
mode:
authorBrian Carlstrom <bdc@google.com>2010-07-28 16:23:02 -0700
committerBrian Carlstrom <bdc@google.com>2010-07-28 16:43:20 -0700
commite6899ef57ca0bea419992ab9dd83b8ca65854284 (patch)
treeb445fe4b8983eef8c4ace042eaa77bfbbea5616e /vm/compiler/codegen/arm/CodegenDriver.c
parentb037a464512c0721bdca969ae19cce3d4b17b083 (diff)
parent106c5fd9745a47d663e28217f3dd5ac48f606f81 (diff)
Merge remote branch 'goog/dalvik-dev' into dalvik-dev-to-master
Change-Id: I990ca89cfd36271813e5af4bcad479290bee2502
Diffstat (limited to 'vm/compiler/codegen/arm/CodegenDriver.c')
-rw-r--r--vm/compiler/codegen/arm/CodegenDriver.c107
1 files changed, 88 insertions, 19 deletions
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index 03fc2af0f..0bcdd0e96 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -24,6 +24,25 @@
* applicable directory below this one.
*/
+/*
+ * Mark garbage collection card. Skip if the value we're storing is null.
+ */
+static void markCard(CompilationUnit *cUnit, int valReg, int tgtAddrReg)
+{
+ int regCardBase = dvmCompilerAllocTemp(cUnit);
+ int regCardNo = dvmCompilerAllocTemp(cUnit);
+ opRegImm(cUnit, kOpCmp, valReg, 0); /* storing null? */
+ ArmLIR *branchOver = opCondBranch(cUnit, kArmCondEq);
+ loadWordDisp(cUnit, rGLUE, offsetof(InterpState, cardTable),
+ regCardBase);
+ opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT);
+ storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0,
+ kUnsignedByte);
+ ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
+ target->defMask = ENCODE_ALL;
+ branchOver->generic.target = (LIR *)target;
+}
+
static bool genConversionCall(CompilationUnit *cUnit, MIR *mir, void *funct,
int srcSize, int tgtSize)
{
@@ -58,7 +77,6 @@ static bool genConversionCall(CompilationUnit *cUnit, MIR *mir, void *funct,
return false;
}
-
static bool genArithOpFloatPortable(CompilationUnit *cUnit, MIR *mir,
RegLocation rlDest, RegLocation rlSrc1,
RegLocation rlSrc2)
@@ -282,7 +300,7 @@ static void genIPutWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
*
*/
static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
- int fieldOffset)
+ int fieldOffset, bool isVolatile)
{
RegLocation rlResult;
RegisterClass regClass = dvmCompilerRegClassBySize(size);
@@ -297,6 +315,9 @@ static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
size, rlObj.sRegLow);
HEAP_ACCESS_SHADOW(false);
+ if (isVolatile) {
+ dvmCompilerGenMemBarrier(cUnit);
+ }
storeValue(cUnit, rlDest, rlResult);
}
@@ -306,7 +327,7 @@ static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
*
*/
static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
- int fieldOffset)
+ int fieldOffset, bool isObject, bool isVolatile)
{
RegisterClass regClass = dvmCompilerRegClassBySize(size);
RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
@@ -316,9 +337,16 @@ static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
NULL);/* null object? */
+ if (isVolatile) {
+ dvmCompilerGenMemBarrier(cUnit);
+ }
HEAP_ACCESS_SHADOW(true);
storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
HEAP_ACCESS_SHADOW(false);
+ if (isObject) {
+ /* NOTE: marking card based on object head */
+ markCard(cUnit, rlSrc.lowReg, rlObj.lowReg);
+ }
}
@@ -528,12 +556,14 @@ static void genArrayObjectPut(CompilationUnit *cUnit, MIR *mir,
dvmCompilerLockTemp(cUnit, regPtr); // r4PC
dvmCompilerLockTemp(cUnit, regIndex); // r7
dvmCompilerLockTemp(cUnit, r0);
+ dvmCompilerLockTemp(cUnit, r1);
/* Bad? - roll back and re-execute if so */
genRegImmCheck(cUnit, kArmCondEq, r0, 0, mir->offset, pcrLabel);
- /* Resume here - must reload element, regPtr & index preserved */
+ /* Resume here - must reload element & array, regPtr & index preserved */
loadValueDirectFixed(cUnit, rlSrc, r0);
+ loadValueDirectFixed(cUnit, rlArray, r1);
ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
target->defMask = ENCODE_ALL;
@@ -543,6 +573,9 @@ static void genArrayObjectPut(CompilationUnit *cUnit, MIR *mir,
storeBaseIndexed(cUnit, regPtr, regIndex, r0,
scale, kWord);
HEAP_ACCESS_SHADOW(false);
+
+ /* NOTE: marking card here based on object head */
+ markCard(cUnit, r0, r1);
}
static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir,
@@ -1416,6 +1449,8 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
storeValue(cUnit, rlDest, rlResult);
break;
}
+ case OP_SGET_VOLATILE:
+ case OP_SGET_OBJECT_VOLATILE:
case OP_SGET_OBJECT:
case OP_SGET_BOOLEAN:
case OP_SGET_CHAR:
@@ -1424,6 +1459,7 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
case OP_SGET: {
int valOffset = offsetof(StaticField, value);
int tReg = dvmCompilerAllocTemp(cUnit);
+ bool isVolatile;
void *fieldPtr = (void*)
(cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
@@ -1432,10 +1468,17 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
dvmAbort();
}
+ isVolatile = (mir->dalvikInsn.opCode == OP_SGET_VOLATILE) ||
+ (mir->dalvikInsn.opCode == OP_SGET_OBJECT_VOLATILE) ||
+ dvmIsVolatileField(fieldPtr);
+
rlDest = dvmCompilerGetDest(cUnit, mir, 0);
rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
loadConstant(cUnit, tReg, (int) fieldPtr + valOffset);
+ if (isVolatile) {
+ dvmCompilerGenMemBarrier(cUnit);
+ }
HEAP_ACCESS_SHADOW(true);
loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
HEAP_ACCESS_SHADOW(false);
@@ -1473,9 +1516,14 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
case OP_SPUT: {
int valOffset = offsetof(StaticField, value);
int tReg = dvmCompilerAllocTemp(cUnit);
- void *fieldPtr = (void*)
+ bool isVolatile;
+ Field *fieldPtr =
(cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]);
+ isVolatile = (mir->dalvikInsn.opCode == OP_SPUT_VOLATILE) ||
+ (mir->dalvikInsn.opCode == OP_SPUT_OBJECT_VOLATILE) ||
+ dvmIsVolatileField(fieldPtr);
+
if (fieldPtr == NULL) {
LOGE("Unexpected null static field");
dvmAbort();
@@ -1488,6 +1536,13 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
HEAP_ACCESS_SHADOW(true);
storeWordDisp(cUnit, tReg, 0 ,rlSrc.lowReg);
HEAP_ACCESS_SHADOW(false);
+ if (isVolatile) {
+ dvmCompilerGenMemBarrier(cUnit);
+ }
+ if (mir->dalvikInsn.opCode == OP_SPUT_OBJECT) {
+ /* NOTE: marking card based on field address */
+ markCard(cUnit, rlSrc.lowReg, tReg);
+ }
break;
}
@@ -2088,17 +2143,18 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
{
OpCode dalvikOpCode = mir->dalvikInsn.opCode;
int fieldOffset;
+ bool isVolatile = false;
if (dalvikOpCode >= OP_IGET && dalvikOpCode <= OP_IPUT_SHORT) {
- InstField *pInstField = (InstField *)
+ Field *fieldPtr =
cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC];
- if (pInstField == NULL) {
+ if (fieldPtr == NULL) {
LOGE("Unexpected null instance field");
dvmAbort();
}
-
- fieldOffset = pInstField->byteOffset;
+ isVolatile = dvmIsVolatileField(fieldPtr);
+ fieldOffset = ((InstField *)fieldPtr)->byteOffset;
} else {
/* Deliberately break the code while make the compiler happy */
fieldOffset = -1;
@@ -2198,36 +2254,47 @@ static bool handleFmt22c(CompilationUnit *cUnit, MIR *mir)
case OP_IGET_WIDE:
genIGetWide(cUnit, mir, fieldOffset);
break;
+ case OP_IGET_VOLATILE:
+ case OP_IGET_OBJECT_VOLATILE:
+ isVolatile = true;
+ // NOTE: intentional fallthrough
case OP_IGET:
case OP_IGET_OBJECT:
- genIGet(cUnit, mir, kWord, fieldOffset);
+ genIGet(cUnit, mir, kWord, fieldOffset, isVolatile);
break;
case OP_IGET_BOOLEAN:
- genIGet(cUnit, mir, kUnsignedByte, fieldOffset);
+ genIGet(cUnit, mir, kUnsignedByte, fieldOffset, isVolatile);
break;
case OP_IGET_BYTE:
- genIGet(cUnit, mir, kSignedByte, fieldOffset);
+ genIGet(cUnit, mir, kSignedByte, fieldOffset, isVolatile);
break;
case OP_IGET_CHAR:
- genIGet(cUnit, mir, kUnsignedHalf, fieldOffset);
+ genIGet(cUnit, mir, kUnsignedHalf, fieldOffset, isVolatile);
break;
case OP_IGET_SHORT:
- genIGet(cUnit, mir, kSignedHalf, fieldOffset);
+ genIGet(cUnit, mir, kSignedHalf, fieldOffset, isVolatile);
break;
case OP_IPUT_WIDE:
genIPutWide(cUnit, mir, fieldOffset);
break;
case OP_IPUT:
+ genIPut(cUnit, mir, kWord, fieldOffset, false, isVolatile);
+ break;
+ case OP_IPUT_OBJECT_VOLATILE:
+ isVolatile = true;
+ // NOTE: intentional fallthrough
case OP_IPUT_OBJECT:
- genIPut(cUnit, mir, kWord, fieldOffset);
+ genIPut(cUnit, mir, kWord, fieldOffset, true, isVolatile);
break;
case OP_IPUT_SHORT:
case OP_IPUT_CHAR:
- genIPut(cUnit, mir, kUnsignedHalf, fieldOffset);
+ genIPut(cUnit, mir, kUnsignedHalf, fieldOffset, false, isVolatile);
break;
case OP_IPUT_BYTE:
+ genIPut(cUnit, mir, kSignedByte, fieldOffset, false, isVolatile);
+ break;
case OP_IPUT_BOOLEAN:
- genIPut(cUnit, mir, kUnsignedByte, fieldOffset);
+ genIPut(cUnit, mir, kUnsignedByte, fieldOffset, false, isVolatile);
break;
case OP_IGET_WIDE_VOLATILE:
case OP_IPUT_WIDE_VOLATILE:
@@ -2248,11 +2315,13 @@ static bool handleFmt22cs(CompilationUnit *cUnit, MIR *mir)
switch (dalvikOpCode) {
case OP_IGET_QUICK:
case OP_IGET_OBJECT_QUICK:
- genIGet(cUnit, mir, kWord, fieldOffset);
+ genIGet(cUnit, mir, kWord, fieldOffset, false);
break;
case OP_IPUT_QUICK:
+ genIPut(cUnit, mir, kWord, fieldOffset, false, false);
+ break;
case OP_IPUT_OBJECT_QUICK:
- genIPut(cUnit, mir, kWord, fieldOffset);
+ genIPut(cUnit, mir, kWord, fieldOffset, true, false);
break;
case OP_IGET_WIDE_QUICK:
genIGetWide(cUnit, mir, fieldOffset);