In an attempt to avoid unnecessary register copies, the JIT allows
data items to live in either floating point or core registers until
an instruction is used which requires one or the other. The bug here
was that sub-word data was allowed to live in floating point registers
at the point of a load or store. This cl forces the use of core registers
in those cases.
Change-Id: Iaee57545c6a62990186a5d0ab5bb22728d75dd60
{
int regPtr;
RegLocation rlResult;
{
int regPtr;
RegLocation rlResult;
- DecodedInstruction *dInsn = &mir->dalvikInsn;
+ RegisterClass regClass = dvmCompilerRegClassBySize(size);
RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
rlObj = loadValue(cUnit, rlObj, kCoreReg);
RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 0);
RegLocation rlDest = dvmCompilerGetDest(cUnit, mir, 0);
rlObj = loadValue(cUnit, rlObj, kCoreReg);
- rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
+ rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true);
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
NULL);/* null object? */
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
NULL);/* null object? */
static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
int fieldOffset)
{
static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
int fieldOffset)
{
- DecodedInstruction *dInsn = &mir->dalvikInsn;
+ RegisterClass regClass = dvmCompilerRegClassBySize(size);
RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 1);
rlObj = loadValue(cUnit, rlObj, kCoreReg);
RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
RegLocation rlObj = dvmCompilerGetSrc(cUnit, mir, 1);
rlObj = loadValue(cUnit, rlObj, kCoreReg);
- rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
- int regPtr;
+ rlSrc = loadValue(cUnit, rlSrc, regClass);
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
NULL);/* null object? */
genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
NULL);/* null object? */
RegLocation rlArray, RegLocation rlIndex,
RegLocation rlDest, int scale)
{
RegLocation rlArray, RegLocation rlIndex,
RegLocation rlDest, int scale)
{
+ RegisterClass regClass = dvmCompilerRegClassBySize(size);
int lenOffset = offsetof(ArrayObject, length);
int dataOffset = offsetof(ArrayObject, contents);
RegLocation rlResult;
int lenOffset = offsetof(ArrayObject, length);
int dataOffset = offsetof(ArrayObject, contents);
RegLocation rlResult;
} else {
opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
}
} else {
opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
}
- rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
+ rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true);
HEAP_ACCESS_SHADOW(true);
loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
HEAP_ACCESS_SHADOW(true);
loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
dvmCompilerFreeTemp(cUnit, regPtr);
storeValueWide(cUnit, rlDest, rlResult);
} else {
dvmCompilerFreeTemp(cUnit, regPtr);
storeValueWide(cUnit, rlDest, rlResult);
} else {
- rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
+ rlResult = dvmCompilerEvalLoc(cUnit, rlDest, regClass, true);
HEAP_ACCESS_SHADOW(true);
loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
HEAP_ACCESS_SHADOW(true);
loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
RegLocation rlArray, RegLocation rlIndex,
RegLocation rlSrc, int scale)
{
RegLocation rlArray, RegLocation rlIndex,
RegLocation rlSrc, int scale)
{
+ RegisterClass regClass = dvmCompilerRegClassBySize(size);
int lenOffset = offsetof(ArrayObject, length);
int dataOffset = offsetof(ArrayObject, contents);
int lenOffset = offsetof(ArrayObject, length);
int dataOffset = offsetof(ArrayObject, contents);
} else {
opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
}
} else {
opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
}
- rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
+ rlSrc = loadValueWide(cUnit, rlSrc, regClass);
HEAP_ACCESS_SHADOW(true);
storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
HEAP_ACCESS_SHADOW(true);
storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
dvmCompilerFreeTemp(cUnit, regPtr);
} else {
dvmCompilerFreeTemp(cUnit, regPtr);
} else {
- rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
+ rlSrc = loadValue(cUnit, rlSrc, regClass);
HEAP_ACCESS_SHADOW(true);
storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
HEAP_ACCESS_SHADOW(true);
storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
#include "compiler/Dataflow.h"
#include "compiler/codegen/arm/ArmLIR.h"
#include "compiler/Dataflow.h"
#include "compiler/codegen/arm/ArmLIR.h"
+/*
+ * Return most flexible allowed register class based on size.
+ * Bug: 2813841
+ * Must use a core register for data types narrower than word (due
+ * to possible unaligned load/store.
+ */
+static inline RegisterClass dvmCompilerRegClassBySize(OpSize size)
+{
+ return (size == kUnsignedHalf ||
+ size == kSignedHalf ||
+ size == kUnsignedByte ||
+ size == kSignedByte ) ? kCoreReg : kAnyReg;
+}
+
static inline int dvmCompilerS2VReg(CompilationUnit *cUnit, int sReg)
{
assert(sReg != INVALID_SREG);
static inline int dvmCompilerS2VReg(CompilationUnit *cUnit, int sReg)
{
assert(sReg != INVALID_SREG);
if (FPREG(rSrc)) {
assert(SINGLEREG(rSrc));
if (FPREG(rSrc)) {
assert(SINGLEREG(rSrc));
- if ((size != kWord) && (size != kSingle)) {
- /* Move float value into core register */
- int tReg = dvmCompilerAllocTemp(cUnit);
- dvmCompilerRegCopy(cUnit, tReg, rSrc);
- rSrc = tReg;
- } else {
- opCode = kThumb2Vstrs;
- size = kSingle;
- }
+ assert((size == kWord) || (size == kSingle));
+ opCode = kThumb2Vstrs;
+ size = kSingle;
} else {
if (size == kSingle)
size = kWord;
} else {
if (size == kSingle)
size = kWord;
+/* Stress mode for testing: if defined will reverse corereg/floatreg hint */
+//#define REGCLASS_STRESS_MODE
+
/*
* Alloc a pair of core registers, or a double. Low reg in low byte,
* high reg in next byte.
/*
* Alloc a pair of core registers, or a double. Low reg in low byte,
* high reg in next byte.
int highReg;
int lowReg;
int res = 0;
int highReg;
int lowReg;
int res = 0;
+
+#if defined(REGCLASS_STRESS_MODE)
+ fpHint = !fpHint;
+#endif
+
if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
lowReg = dvmCompilerAllocTempDouble(cUnit);
highReg = lowReg + 1;
if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg)) {
lowReg = dvmCompilerAllocTempDouble(cUnit);
highReg = lowReg + 1;
int dvmCompilerAllocTypedTemp(CompilationUnit *cUnit, bool fpHint,
int regClass)
{
int dvmCompilerAllocTypedTemp(CompilationUnit *cUnit, bool fpHint,
int regClass)
{
+#if defined(REGCLASS_STRESS_MODE)
+ fpHint = !fpHint;
+#endif
if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg))
return dvmCompilerAllocTempFloat(cUnit);
return dvmCompilerAllocTemp(cUnit);
if (((regClass == kAnyReg) && fpHint) || (regClass == kFPReg))
return dvmCompilerAllocTempFloat(cUnit);
return dvmCompilerAllocTemp(cUnit);