Remove pad word from arrays
This change removes the 4 byte pad from all arrays except longs and
doubles. It saves 76kb from the boot image, and will also reduce the
size of arrays in the heap (and thereby reduce garbage collection).
Change-Id: I3ff277d5bf14c57c0f7552215818e588ec6cc275
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index 79a62ad..bdadf6e 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -229,6 +229,10 @@
*/
oatLockTemp(cUnit, r0);
+ // TODO: use the correct component size, currently all supported types share array alignment
+ // with ints (see comment at head of function)
+ size_t component_size = sizeof(int32_t);
+
// Having a range of 0 is legal
if (isRange && (dInsn->vA > 0)) {
/*
@@ -262,7 +266,7 @@
oatSRegOffset(cUnit, rlFirst.sRegLow));
// Set up the target pointer
opRegRegImm(cUnit, kOpAdd, rDst, r0,
- Array::DataOffset().Int32Value());
+ Array::DataOffset(component_size).Int32Value());
// Set up the loop counter (known to be > 0)
loadConstant(cUnit, rIdx, dInsn->vA - 1);
// Generate the copy loop. Going backwards for convenience
@@ -281,7 +285,7 @@
RegLocation rlArg = loadValue(cUnit,
oatGetSrc(cUnit, mir, i), kCoreReg);
storeBaseDisp(cUnit, r0,
- Array::DataOffset().Int32Value() +
+ Array::DataOffset(component_size).Int32Value() +
i * 4, rlArg.lowReg, kWord);
// If the loadValue caused a temp to be allocated, free it
if (oatIsTemp(cUnit, rlArg.lowReg)) {
@@ -330,7 +334,7 @@
Method::DexCacheInitializedStaticStorageOffset().Int32Value(),
rBase);
loadWordDisp(cUnit, rBase,
- Array::DataOffset().Int32Value() + sizeof(int32_t*) *
+ Array::DataOffset(sizeof(Object*)).Int32Value() + sizeof(int32_t*) *
ssbIndex, rBase);
// rBase now points at appropriate static storage base (Class*)
// or NULL if not initialized. Check for NULL and call helper if NULL.
@@ -424,7 +428,8 @@
Method::DexCacheInitializedStaticStorageOffset().Int32Value(),
rBase);
loadWordDisp(cUnit, rBase,
- Array::DataOffset().Int32Value() + sizeof(int32_t*) * ssbIndex,
+ Array::DataOffset(sizeof(Object*)).Int32Value() +
+ sizeof(int32_t*) * ssbIndex,
rBase);
// rBase now points at appropriate static storage base (Class*)
// or NULL if not initialized. Check for NULL and call helper if NULL.
@@ -497,7 +502,8 @@
break;
case 2: // Grab target method*
loadWordDisp(cUnit, r0,
- Array::DataOffset().Int32Value() + dexIdx * 4, r0);
+ Array::DataOffset(sizeof(Object*)).Int32Value() + dexIdx * 4,
+ r0);
break;
case 3: // Grab the code from the method*
loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR);
@@ -538,7 +544,7 @@
break;
case 3: // Get target method [use rLR, set r0]
loadWordDisp(cUnit, rLR, (methodIdx * 4) +
- Array::DataOffset().Int32Value(), r0);
+ Array::DataOffset(sizeof(Object*)).Int32Value(), r0);
break;
case 4: // Get the target compiled code address [uses r0, sets rLR]
loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR);
@@ -584,7 +590,7 @@
break;
case 3: // Get target method [use rLR, set r0]
loadWordDisp(cUnit, rLR, (methodIdx * 4) +
- Array::DataOffset().Int32Value(), r0);
+ Array::DataOffset(sizeof(Object*)).Int32Value(), r0);
break;
case 4: // Get the target compiled code address [uses r0, sets rLR]
loadWordDisp(cUnit, r0, Method::GetCodeOffset().Int32Value(), rLR);
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index c385f35..5a9750a 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -510,7 +510,8 @@
// We're don't need access checks, load type from dex cache
int32_t dex_cache_offset = Method::DexCacheResolvedTypesOffset().Int32Value();
loadWordDisp(cUnit, mReg, dex_cache_offset, resReg);
- int32_t offset_of_type = Array::DataOffset().Int32Value() + (sizeof(Class*) * type_idx);
+ int32_t offset_of_type = Array::DataOffset(sizeof(Class*)).Int32Value() +
+ (sizeof(Class*) * type_idx);
loadWordDisp(cUnit, resReg, offset_of_type, rlResult.lowReg);
if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(cUnit->dex_cache,
type_idx) ||
@@ -571,7 +572,8 @@
{
/* NOTE: Most strings should be available at compile time */
uint32_t string_idx = mir->dalvikInsn.vB;
- int32_t offset_of_string = Array::DataOffset().Int32Value() + (sizeof(String*) * string_idx);
+ int32_t offset_of_string = Array::DataOffset(sizeof(String*)).Int32Value() +
+ (sizeof(String*) * string_idx);
if (!cUnit->compiler->CanAssumeStringIsPresentInDexCache(cUnit->dex_cache, string_idx) ||
SLOW_STRING_PATH) {
// slow path, resolve string if not in dex cache
@@ -664,7 +666,8 @@
// Load dex cache entry into classReg (r2)
loadValueDirectFixed(cUnit, rlSrc, r0); // r0 <= ref
loadWordDisp(cUnit, r1, Method::DexCacheResolvedTypesOffset().Int32Value(), classReg);
- int32_t offset_of_type = Array::DataOffset().Int32Value() + (sizeof(Class*) * type_idx);
+ int32_t offset_of_type = Array::DataOffset(sizeof(Class*)).Int32Value() +
+ (sizeof(Class*) * type_idx);
loadWordDisp(cUnit, classReg, offset_of_type, classReg);
if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(cUnit->dex_cache, type_idx)) {
// Need to test presence of type in dex cache at runtime
@@ -728,7 +731,8 @@
} else {
// Load dex cache entry into classReg (r2)
loadWordDisp(cUnit, r1, Method::DexCacheResolvedTypesOffset().Int32Value(), classReg);
- int32_t offset_of_type = Array::DataOffset().Int32Value() + (sizeof(Class*) * type_idx);
+ int32_t offset_of_type = Array::DataOffset(sizeof(Class*)).Int32Value() +
+ (sizeof(Class*) * type_idx);
loadWordDisp(cUnit, classReg, offset_of_type, classReg);
if (!cUnit->compiler->CanAssumeTypeIsPresentInDexCache(cUnit->dex_cache, type_idx)) {
// Need to test presence of type in dex cache at runtime
@@ -1253,7 +1257,7 @@
{
RegisterClass regClass = oatRegClassBySize(kWord);
int lenOffset = Array::LengthOffset().Int32Value();
- int dataOffset = Array::DataOffset().Int32Value();
+ int dataOffset = Array::DataOffset(sizeof(Object*)).Int32Value();
oatFlushAllRegs(cUnit);
/* Make sure it's a legal object Put. Use direct regs at first */
@@ -1313,12 +1317,18 @@
{
RegisterClass regClass = oatRegClassBySize(size);
int lenOffset = Array::LengthOffset().Int32Value();
- int dataOffset = Array::DataOffset().Int32Value();
+ int dataOffset;
RegLocation rlResult;
rlArray = loadValue(cUnit, rlArray, kCoreReg);
rlIndex = loadValue(cUnit, rlIndex, kCoreReg);
int regPtr;
+ if (size == kLong || size == kDouble) {
+ dataOffset = Array::DataOffset(sizeof(int64_t)).Int32Value();
+ } else {
+ dataOffset = Array::DataOffset(sizeof(int32_t)).Int32Value();
+ }
+
/* null object? */
genNullCheck(cUnit, rlArray.sRegLow, rlArray.lowReg, mir);
@@ -1375,7 +1385,13 @@
{
RegisterClass regClass = oatRegClassBySize(size);
int lenOffset = Array::LengthOffset().Int32Value();
- int dataOffset = Array::DataOffset().Int32Value();
+ int dataOffset;
+
+ if (size == kLong || size == kDouble) {
+ dataOffset = Array::DataOffset(sizeof(int64_t)).Int32Value();
+ } else {
+ dataOffset = Array::DataOffset(sizeof(int32_t)).Int32Value();
+ }
int regPtr;
rlArray = loadValue(cUnit, rlArray, kCoreReg);