diff options
| author | 2011-09-04 11:22:20 -0700 | |
|---|---|---|
| committer | 2011-09-04 12:46:26 -0700 | |
| commit | 1da522de18ac6e4c2913c3233529e9dd115059f8 (patch) | |
| tree | d64473583896cb02f6d5bad52cbac940059bdefa | |
| parent | 193a44d9637b51724274b1de384245776e264a46 (diff) | |
Complete static field accesses; clear TODO's
This adds the fast path for static field accesses. Miscellaneous
changes include adding dummy helper for filled array allocation,
elimination of redunant arg1/r1 load, deleting TODO's that I'm not
going to do, and altered compiler_test to use System.out.println
instead of System.out.printf.
Change-Id: I560aa6093c98f1d288d64f346c8fd9ab7f180994
| -rw-r--r-- | src/compiler/codegen/arm/MethodCodegenDriver.cc | 365 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Gen.cc | 6 | ||||
| -rw-r--r-- | src/object.h | 7 | ||||
| -rw-r--r-- | src/thread.cc | 14 | ||||
| -rw-r--r-- | src/thread.h | 4 | ||||
| -rw-r--r-- | test/IntMath/IntMath.java | 88 |
6 files changed, 256 insertions, 228 deletions
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc index eb9296bb05..81eb24cbcb 100644 --- a/src/compiler/codegen/arm/MethodCodegenDriver.cc +++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc @@ -60,10 +60,8 @@ static void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange) typeId = dInsn->vC; } oatFlushAllRegs(cUnit); /* Everything to home location */ - // TODO: Alloc variant that checks types (see header comment) */ - UNIMPLEMENTED(WARNING) << "Need AllocFromCode variant w/ extra checks"; loadWordDisp(cUnit, rSELF, - OFFSETOF_MEMBER(Thread, pAllocFromCode), rLR); + OFFSETOF_MEMBER(Thread, pCheckAndAllocFromCode), rLR); loadCurrMethodDirect(cUnit, r1); // arg1 <- Method* loadConstant(cUnit, r0, typeId); // arg0 <- type_id loadConstant(cUnit, r2, elems); // arg2 <- count @@ -139,17 +137,14 @@ static void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange) static void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { - bool slow_path = true; bool isObject = ((mir->dalvikInsn.opcode == OP_SPUT_OBJECT) || (mir->dalvikInsn.opcode == OP_SPUT_OBJECT_VOLATILE)); - UNIMPLEMENTED(WARNING) << "Implement sput fast path"; - int funcOffset; - if (slow_path) { - if (isObject) { - funcOffset = OFFSETOF_MEMBER(Thread, pSetObjStatic); - } else { - funcOffset = OFFSETOF_MEMBER(Thread, pSet32Static); - } + int fieldIdx = mir->dalvikInsn.vB; + Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx); + if (field == NULL) { + // Slow path + int funcOffset = isObject ? OFFSETOF_MEMBER(Thread, pSetObjStatic) + : OFFSETOF_MEMBER(Thread, pSet32Static); oatFlushAllRegs(cUnit); loadWordDisp(cUnit, rSELF, funcOffset, rLR); loadConstant(cUnit, r0, mir->dalvikInsn.vB); @@ -158,153 +153,171 @@ static void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) opReg(cUnit, kOpBlx, rLR); oatClobberCallRegs(cUnit); } else { - UNIMPLEMENTED(FATAL) << "Must update for new world"; -#if 0 - int valOffset = OFFSETOF_MEMBER(StaticField, value); - int tReg = oatAllocTemp(cUnit); - int objHead; - bool isVolatile; - bool isSputObject; - const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ? - mir->meta.calleeMethod : cUnit->method; - void* fieldPtr = (void*) - (method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]); - Opcode opcode = mir->dalvikInsn.opcode; - - if (fieldPtr == NULL) { - // FIXME: need to handle this case for oat(); - UNIMPLEMENTED(FATAL); - } - + // fast path + int fieldOffset = field->GetOffset().Int32Value(); + art::ClassLinker* class_linker = art::Runtime::Current()-> + GetClassLinker(); + const art::DexFile& dex_file = class_linker-> + FindDexFile(field->GetDeclaringClass()->GetDexCache()); + const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx); + int typeIdx = field_id.class_idx_; + // Using fixed register to sync with slow path + int rMethod = r1; + oatLockTemp(cUnit, rMethod); + loadCurrMethodDirect(cUnit, rMethod); + int rBase = r0; + oatLockTemp(cUnit, rBase); + loadWordDisp(cUnit, rMethod, + Method::DexCacheInitializedStaticStorageOffset().Int32Value(), + rBase); + loadWordDisp(cUnit, rBase, art::Array::DataOffset().Int32Value() + + sizeof(int32_t*)* typeIdx, rBase); + // TUNING: fast path should fall through + ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondNe, rBase, 0); + loadWordDisp(cUnit, rSELF, + OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR); + loadConstant(cUnit, r0, typeIdx); + opReg(cUnit, kOpBlx, rLR); + ArmLIR* skipTarget = newLIR0(cUnit, kArmPseudoTargetLabel); + skipTarget->defMask = ENCODE_ALL; + branchOver->generic.target = (LIR*)skipTarget; + rlSrc = oatGetSrc(cUnit, mir, 0); + rlSrc = loadValue(cUnit, rlSrc, kAnyReg); + storeWordDisp(cUnit, rBase, fieldOffset, rlSrc.lowReg); #if ANDROID_SMP != 0 - isVolatile = (opcode == OP_SPUT_VOLATILE) || - (opcode == OP_SPUT_VOLATILE_JUMBO) || - (opcode == OP_SPUT_OBJECT_VOLATILE) || - (opcode == OP_SPUT_OBJECT_VOLATILE_JUMBO); - assert(isVolatile == artIsVolatileField((Field *) fieldPtr)); -#else - isVolatile = artIsVolatileField((Field *) fieldPtr); -#endif - - isSputObject = (opcode == OP_SPUT_OBJECT) || - (opcode == OP_SPUT_OBJECT_VOLATILE); - - rlSrc = oatGetSrc(cUnit, mir, 0); - rlSrc = loadValue(cUnit, rlSrc, kAnyReg); - loadConstant(cUnit, tReg, (int) fieldPtr); - if (isSputObject) { - objHead = oatAllocTemp(cUnit); - loadWordDisp(cUnit, tReg, OFFSETOF_MEMBER(Field, clazz), objHead); - } - storeWordDisp(cUnit, tReg, valOffset ,rlSrc.lowReg); - oatFreeTemp(cUnit, tReg); - if (isVolatile) { - oatGenMemBarrier(cUnit, kSY); - } - if (isSputObject) { - /* NOTE: marking card based sfield->clazz */ - markGCCard(cUnit, rlSrc.lowReg, objHead); - oatFreeTemp(cUnit, objHead); - } + if (field->IsVolatile()) { + oatGenMemBarrier(cUnit, kSY); + } #endif + if (isObject) { + markGCCard(cUnit, rlSrc.lowReg, rBase); + } + oatFreeTemp(cUnit, rBase); } } static void genSputWide(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { - bool slow_path = true; - UNIMPLEMENTED(WARNING) << "Implement sput-wide fast path"; - int funcOffset; - if (slow_path) { - funcOffset = OFFSETOF_MEMBER(Thread, pSet64Static); + int fieldIdx = mir->dalvikInsn.vB; + Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx); + if (field == NULL) { oatFlushAllRegs(cUnit); - loadWordDisp(cUnit, rSELF, funcOffset, rLR); + loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pSet64Static), rLR); loadConstant(cUnit, r0, mir->dalvikInsn.vB); loadCurrMethodDirect(cUnit, r1); loadValueDirectWideFixed(cUnit, rlSrc, r2, r3); opReg(cUnit, kOpBlx, rLR); oatClobberCallRegs(cUnit); } else { - UNIMPLEMENTED(FATAL) << "Must update for new world"; -#if 0 - int tReg = oatAllocTemp(cUnit); - int valOffset = OFFSETOF_MEMBER(StaticField, value); - const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ? - mir->meta.calleeMethod : cUnit->method; - void* fieldPtr = (void*) - (method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]); - - if (fieldPtr == NULL) { - // FIXME: need to handle this case for oat(); - UNIMPLEMENTED(FATAL); - } - - rlSrc = oatGetSrcWide(cUnit, mir, 0, 1); - rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg); - loadConstant(cUnit, tReg, (int) fieldPtr + valOffset); - - storePair(cUnit, tReg, rlSrc.lowReg, rlSrc.highReg); + // fast path + int fieldOffset = field->GetOffset().Int32Value(); + art::ClassLinker* class_linker = art::Runtime::Current()-> + GetClassLinker(); + const art::DexFile& dex_file = class_linker-> + FindDexFile(field->GetDeclaringClass()->GetDexCache()); + const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx); + int typeIdx = field_id.class_idx_; + // Using fixed register to sync with slow path + int rMethod = r1; + oatLockTemp(cUnit, rMethod); + loadCurrMethodDirect(cUnit, r1); + int rBase = r0; + oatLockTemp(cUnit, rBase); + loadWordDisp(cUnit, rMethod, + Method::DexCacheInitializedStaticStorageOffset().Int32Value(), + rBase); + loadWordDisp(cUnit, rBase, art::Array::DataOffset().Int32Value() + + sizeof(int32_t*)* typeIdx, rBase); + // TUNING: fast path should fall through + ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondNe, rBase, 0); + loadWordDisp(cUnit, rSELF, + OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR); + loadConstant(cUnit, r0, typeIdx); + opReg(cUnit, kOpBlx, rLR); + ArmLIR* skipTarget = newLIR0(cUnit, kArmPseudoTargetLabel); + skipTarget->defMask = ENCODE_ALL; + branchOver->generic.target = (LIR*)skipTarget; + rlSrc = oatGetSrcWide(cUnit, mir, 0, 1); + rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg); + storeBaseDispWide(cUnit, rBase, fieldOffset, rlSrc.lowReg, + rlSrc.highReg); +#if ANDROID_SMP != 0 + if (field->IsVolatile()) { + oatGenMemBarrier(cUnit, kSY); + } #endif + oatFreeTemp(cUnit, rBase); } } - static void genSgetWide(CompilationUnit* cUnit, MIR* mir, RegLocation rlResult, RegLocation rlDest) { - bool slow_path = true; - UNIMPLEMENTED(WARNING) << "Implement sget-wide fast path"; - int funcOffset; - if (slow_path) { - funcOffset = OFFSETOF_MEMBER(Thread, pGet64Static); + int fieldIdx = mir->dalvikInsn.vB; + Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx); + if (field == NULL) { oatFlushAllRegs(cUnit); - loadWordDisp(cUnit, rSELF, funcOffset, rLR); + loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pGet64Static), rLR); loadConstant(cUnit, r0, mir->dalvikInsn.vB); loadCurrMethodDirect(cUnit, r1); opReg(cUnit, kOpBlx, rLR); RegLocation rlResult = oatGetReturnWide(cUnit); storeValueWide(cUnit, rlDest, rlResult); } else { - UNIMPLEMENTED(FATAL) << "Must update for new world"; -#if 0 - int valOffset = OFFSETOF_MEMBER(StaticField, value); - const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ? - mir->meta.calleeMethod : cUnit->method; - void* fieldPtr = (void*) - (method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]); - - if (fieldPtr == NULL) { - // FIXME: need to handle this case for oat(); - UNIMPLEMENTED(FATAL); - } - - int tReg = oatAllocTemp(cUnit); - rlDest = oatGetDestWide(cUnit, mir, 0, 1); - rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true); - loadConstant(cUnit, tReg, (int) fieldPtr + valOffset); - - loadPair(cUnit, tReg, rlResult.lowReg, rlResult.highReg); - - storeValueWide(cUnit, rlDest, rlResult); + // Fast path + int fieldOffset = field->GetOffset().Int32Value(); + art::ClassLinker* class_linker = art::Runtime::Current()-> + GetClassLinker(); + const art::DexFile& dex_file = class_linker-> + FindDexFile(field->GetDeclaringClass()->GetDexCache()); + const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx); + int typeIdx = field_id.class_idx_; + // Using fixed register to sync with slow path + int rMethod = r1; + oatLockTemp(cUnit, rMethod); + loadCurrMethodDirect(cUnit, rMethod); + int rBase = r0; + oatLockTemp(cUnit, rBase); + loadWordDisp(cUnit, rMethod, + Method::DexCacheInitializedStaticStorageOffset().Int32Value(), + rBase); + loadWordDisp(cUnit, rBase, art::Array::DataOffset().Int32Value() + + sizeof(int32_t*)* typeIdx, rBase); + // TUNING: fast path should fall through + ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondNe, rBase, 0); + loadWordDisp(cUnit, rSELF, + OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR); + loadConstant(cUnit, r0, typeIdx); + opReg(cUnit, kOpBlx, rLR); + ArmLIR* skipTarget = newLIR0(cUnit, kArmPseudoTargetLabel); + skipTarget->defMask = ENCODE_ALL; + branchOver->generic.target = (LIR*)skipTarget; + rlDest = oatGetDestWide(cUnit, mir, 0, 1); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true); +#if ANDROID_SMP != 0 + if (isVolatile) { + oatGenMemBarrier(cUnit, kSY); + } #endif + loadBaseDispWide(cUnit, NULL, rBase, fieldOffset, rlResult.lowReg, + rlResult.highReg, INVALID_SREG); + oatFreeTemp(cUnit, rBase); + storeValueWide(cUnit, rlDest, rlResult); } } static void genSget(CompilationUnit* cUnit, MIR* mir, RegLocation rlResult, RegLocation rlDest) { - bool slow_path = true; + int fieldIdx = mir->dalvikInsn.vB; + Field* field = cUnit->method->GetDexCacheResolvedFields()->Get(fieldIdx); bool isObject = ((mir->dalvikInsn.opcode == OP_SGET_OBJECT) || (mir->dalvikInsn.opcode == OP_SGET_OBJECT_VOLATILE)); - UNIMPLEMENTED(WARNING) << "Implement sget fast path"; - int funcOffset; - if (slow_path) { - if (isObject) { - funcOffset = OFFSETOF_MEMBER(Thread, pGetObjStatic); - } else { - funcOffset = OFFSETOF_MEMBER(Thread, pGet32Static); - } + if (field == NULL) { + // Slow path + int funcOffset = isObject ? OFFSETOF_MEMBER(Thread, pGetObjStatic) + : OFFSETOF_MEMBER(Thread, pGet32Static); oatFlushAllRegs(cUnit); loadWordDisp(cUnit, rSELF, funcOffset, rLR); loadConstant(cUnit, r0, mir->dalvikInsn.vB); @@ -313,48 +326,44 @@ static void genSget(CompilationUnit* cUnit, MIR* mir, RegLocation rlResult = oatGetReturn(cUnit); storeValue(cUnit, rlDest, rlResult); } else { - UNIMPLEMENTED(FATAL) << "Must update for new world"; -#if 0 - int valOffset = OFFSETOF_MEMBER(StaticField, value); - int tReg = oatAllocTemp(cUnit); - bool isVolatile; - const Method *method = cUnit->method; - void* fieldPtr = (void*) - (method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vB]); - - if (fieldPtr == NULL) { - // FIXME: need to handle this case for oat(); - UNIMPLEMENTED(FATAL); - } - - /* - * On SMP systems, Dalvik opcodes found to be referencing - * volatile fields are rewritten to their _VOLATILE variant. - * However, this does not happen on non-SMP systems. The compiler - * still needs to know about volatility to avoid unsafe - * optimizations so we determine volatility based on either - * the opcode or the field access flags. - */ + // Fast path + int fieldOffset = field->GetOffset().Int32Value(); + art::ClassLinker* class_linker = art::Runtime::Current()-> + GetClassLinker(); + const art::DexFile& dex_file = class_linker-> + FindDexFile(field->GetDeclaringClass()->GetDexCache()); + const art::DexFile::FieldId& field_id = dex_file.GetFieldId(fieldIdx); + int typeIdx = field_id.class_idx_; + // Using fixed register to sync with slow path + int rMethod = r1; + oatLockTemp(cUnit, rMethod); + loadCurrMethodDirect(cUnit, rMethod); + int rBase = r0; + oatLockTemp(cUnit, rBase); + loadWordDisp(cUnit, rMethod, + Method::DexCacheInitializedStaticStorageOffset().Int32Value(), + rBase); + loadWordDisp(cUnit, rBase, art::Array::DataOffset().Int32Value() + + sizeof(int32_t*)* typeIdx, rBase); + // TUNING: fast path should fall through + ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondNe, rBase, 0); + loadWordDisp(cUnit, rSELF, + OFFSETOF_MEMBER(Thread, pInitializeStaticStorage), rLR); + loadConstant(cUnit, r0, typeIdx); + opReg(cUnit, kOpBlx, rLR); + ArmLIR* skipTarget = newLIR0(cUnit, kArmPseudoTargetLabel); + skipTarget->defMask = ENCODE_ALL; + branchOver->generic.target = (LIR*)skipTarget; + rlDest = oatGetDest(cUnit, mir, 0); + rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true); #if ANDROID_SMP != 0 - Opcode opcode = mir->dalvikInsn.opcode; - isVolatile = (opcode == OP_SGET_VOLATILE) || - (opcode == OP_SGET_OBJECT_VOLATILE); - assert(isVolatile == artIsVolatileField((Field *) fieldPtr)); -#else - isVolatile = artIsVolatileField((Field *) fieldPtr); -#endif - - rlDest = oatGetDest(cUnit, mir, 0); - rlResult = oatEvalLoc(cUnit, rlDest, kAnyReg, true); - loadConstant(cUnit, tReg, (int) fieldPtr + valOffset); - - if (isVolatile) { - oatGenMemBarrier(cUnit, kSY); - } - loadWordDisp(cUnit, tReg, 0, rlResult.lowReg); - - storeValue(cUnit, rlDest, rlResult); + if (isVolatile) { + oatGenMemBarrier(cUnit, kSY); + } #endif + loadWordDisp(cUnit, rBase, fieldOffset, rlResult.lowReg); + oatFreeTemp(cUnit, rBase); + storeValue(cUnit, rlDest, rlResult); } } @@ -694,7 +703,8 @@ static int nextSuperCallInsnSP(CompilationUnit* cUnit, MIR* mir, static int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir, DecodedInstruction* dInsn, int callState, ArmLIR** pcrLabel, bool isRange, - NextCallInsn nextCallInsn, ArmLIR* rollback) + NextCallInsn nextCallInsn, ArmLIR* rollback, + bool skipThis) { RegLocation rlArg; int registerArgs[3]; @@ -726,7 +736,7 @@ static int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir, } /* Load register arguments r1..r3 */ - for (unsigned int i = 0; i < 3; i++) { + for (unsigned int i = skipThis ? 1 : 0; i < 3; i++) { if (i < dInsn->vA) registerArgs[i] = (isRange) ? dInsn->vC + i : i; else @@ -761,7 +771,7 @@ static int genDalvikArgsNoRange(CompilationUnit* cUnit, MIR* mir, static int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir, DecodedInstruction* dInsn, int callState, ArmLIR** pcrLabel, NextCallInsn nextCallInsn, - ArmLIR* rollback) + ArmLIR* rollback, bool skipThis) { int firstArg = dInsn->vC; int numArgs = dInsn->vA; @@ -769,7 +779,7 @@ static int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir, // If we can treat it as non-range (Jumbo ops will use range form) if (numArgs <= 5) return genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pcrLabel, - true, nextCallInsn, rollback); + true, nextCallInsn, rollback, skipThis); /* * Make sure range list doesn't span the break between in normal * Dalvik vRegs and the ins. @@ -789,7 +799,6 @@ static int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir, // Scan the rest of the args - if in physReg flush to memory for (int i = 4; i < numArgs; i++) { RegLocation loc = oatGetSrc(cUnit, mir, i); - //TODO: generic loc flushing routine if (loc.wide) { loc = oatUpdateLocWide(cUnit, loc); if (loc.location == kLocPhysReg) { // TUNING: if dirty? @@ -831,7 +840,7 @@ static int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir, } // Handle the 1st 3 in r1, r2 & r3 - for (unsigned int i = 0; i < dInsn->vA && i < 3; i++) { + for (unsigned int i = skipThis? 1 : 0; i < dInsn->vA && i < 3; i++) { RegLocation loc = oatGetSrc(cUnit, mir, firstArg + i); loadValueDirectFixed(cUnit, loc, r1 + i); callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback); @@ -856,10 +865,10 @@ static void genInvokeStaticDirect(CompilationUnit* cUnit, MIR* mir, if (range) { callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, pNullCk, - nextCallInsn, NULL); + nextCallInsn, NULL, false); } else { callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, pNullCk, - false, nextCallInsn, NULL); + false, nextCallInsn, NULL, false); } // Finish up any of the call sequence not interleaved in arg loading while (callState >= 0) { @@ -881,10 +890,11 @@ static void genInvokeInterface(CompilationUnit* cUnit, MIR* mir) callState = nextInterfaceCallInsn(cUnit, mir, dInsn, callState, NULL); if (mir->dalvikInsn.opcode == OP_INVOKE_INTERFACE) callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, &nullCk, - false, nextInterfaceCallInsn, NULL); + false, nextInterfaceCallInsn, NULL, + true); else callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, &nullCk, - nextInterfaceCallInsn, NULL); + nextInterfaceCallInsn, NULL, true); // Finish up any of the call sequence not interleaved in arg loading while (callState >= 0) { callState = nextInterfaceCallInsn(cUnit, mir, dInsn, callState, NULL); @@ -925,13 +935,12 @@ static void genInvokeSuper(CompilationUnit* cUnit, MIR* mir) rollback = newLIR0(cUnit, kArmPseudoTargetLabel); rollback->defMask = -1; } -// TODO - redundantly loading arg0/r1 ("this") if (mir->dalvikInsn.opcode == OP_INVOKE_SUPER) callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, &nullCk, - false, nextCallInsn, rollback); + false, nextCallInsn, rollback, true); else callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, &nullCk, - nextCallInsn, rollback); + nextCallInsn, rollback, true); // Finish up any of the call sequence not interleaved in arg loading while (callState >= 0) { callState = nextSuperCallInsn(cUnit, mir, dInsn, callState, NULL); @@ -960,13 +969,12 @@ static void genInvokeVirtual(CompilationUnit* cUnit, MIR* mir) nextCallInsn = nextVCallInsn; rollback = NULL; } - // TODO - redundantly loading arg0/r1 ("this") if (mir->dalvikInsn.opcode == OP_INVOKE_VIRTUAL) callState = genDalvikArgsNoRange(cUnit, mir, dInsn, callState, &nullCk, - false, nextCallInsn, rollback); + false, nextCallInsn, rollback, true); else callState = genDalvikArgsRange(cUnit, mir, dInsn, callState, &nullCk, - nextCallInsn, rollback); + nextCallInsn, rollback, true); // Finish up any of the call sequence not interleaved in arg loading while (callState >= 0) { callState = nextCallInsn(cUnit, mir, dInsn, callState, rollback); @@ -974,7 +982,6 @@ static void genInvokeVirtual(CompilationUnit* cUnit, MIR* mir) newLIR1(cUnit, kThumbBlxR, rLR); } -// TODO: break out the case handlers. Might make it easier to support x86 static bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir, BasicBlock* bb, ArmLIR* labelList) { @@ -1058,7 +1065,7 @@ static bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir, * formation in storeValueWide. */ assert(retLocWide.lowReg == r0); - assert(retLocWide.lowReg == r1); + assert(retLocWide.highReg == r1); oatLockTemp(cUnit, retLocWide.lowReg); oatLockTemp(cUnit, retLocWide.highReg); storeValueWide(cUnit, rlDest, retLocWide); diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc index c4a1fed931..d0b0683a5b 100644 --- a/src/compiler/codegen/arm/Thumb2/Gen.cc +++ b/src/compiler/codegen/arm/Thumb2/Gen.cc @@ -596,8 +596,7 @@ static void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> GetResolvedType(mir->dalvikInsn.vC); if (classPtr == NULL) { - /* Shouldn't happen */ - LOG(FATAL) << "Unexpected null class pointer"; + UNIMPLEMENTED(FATAL) << "Handle null class pointer"; } oatFlushAllRegs(cUnit); /* Everything to home location */ loadValueDirectFixed(cUnit, rlSrc, r0); /* Ref */ @@ -631,8 +630,7 @@ static void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> GetResolvedType(mir->dalvikInsn.vB); if (classPtr == NULL) { - /* Shouldn't happen with our current model */ - LOG(FATAL) << "Unexpected null class pointer"; + UNIMPLEMENTED(FATAL) << "Unimplemented null class pointer"; } oatFlushAllRegs(cUnit); /* Everything to home location */ loadConstant(cUnit, r1, (int) classPtr ); diff --git a/src/object.h b/src/object.h index ca84dac39a..4edae14a2a 100644 --- a/src/object.h +++ b/src/object.h @@ -563,11 +563,11 @@ class Field : public AccessibleObject { static void SetClass(Class* java_lang_reflect_Field); static void ResetClass(); - private: bool IsVolatile() const { return (GetAccessFlags() & kAccVolatile) != 0; } + private: // private implementation of field access using raw data uint32_t Get32(const Object* object) const; void Set32(Object* object, uint32_t new_value) const; @@ -758,6 +758,11 @@ class Method : public AccessibleObject { return OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_); } + static MemberOffset DexCacheInitializedStaticStorageOffset() { + return OFFSET_OF_OBJECT_MEMBER(Method, + dex_cache_initialized_static_storage_); + } + ObjectArray<Class>* GetDexCacheResolvedTypes() const; void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types); diff --git a/src/thread.cc b/src/thread.cc index 31786c9970..a617fb48ec 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -106,6 +106,18 @@ static void ResolveMethodFromCode(Method* method, uint32_t method_idx) { */ } +// TODO: placeholder. Helper function to alloc array for OP_FILLED_NEW_ARRAY +static Array* CheckAndAllocFromCode(uint32_t type_index, Method* method, + int32_t component_count) +{ + /* + * Just a wrapper around Array::AllocFromCode() that additionally + * throws a runtime exception "bad Filled array req" for 'D' and 'J'. + */ + UNIMPLEMENTED(WARNING) << "Need check that not 'D' or 'J'"; + return Array::AllocFromCode(type_index, method, component_count); +} + void Thread::InitFunctionPointers() { #if defined(__arm__) pShlLong = art_shl_long; @@ -137,6 +149,7 @@ void Thread::InitFunctionPointers() { pInvokeInterfaceTrampoline = art_invoke_interface_trampoline; #endif pAllocFromCode = Array::AllocFromCode; + pCheckAndAllocFromCode = CheckAndAllocFromCode; pAllocObjectFromCode = Class::AllocObjectFromCode; pMemcpy = memcpy; pHandleFillArrayDataFromCode = HandleFillArrayDataFromCode; @@ -150,6 +163,7 @@ void Thread::InitFunctionPointers() { pThrowException = ThrowException; pInitializeTypeFromCode = InitializeTypeFromCode; pResolveMethodFromCode = ResolveMethodFromCode; + pInitializeStaticStorage = ClassLinker::InitializeStaticStorageFromCode; pDebugMe = DebugMe; #if 0 bool (Thread::*pUnlockObject)(Thread*, Object*); diff --git a/src/thread.h b/src/thread.h index fc523a3d97..070933b389 100644 --- a/src/thread.h +++ b/src/thread.h @@ -29,6 +29,8 @@ class Thread; class ThreadList; class Throwable; class StackTraceElement; +class StaticStorageBase; + template<class T> class ObjectArray; template<class T> class PrimitiveArray; typedef PrimitiveArray<int32_t> IntArray; @@ -204,6 +206,7 @@ class Thread { long long (*pLmul)(long long, long long); long long (*pLdivmod)(long long, long long); Array* (*pAllocFromCode)(uint32_t, Method*, int32_t); + Array* (*pCheckAndAllocFromCode)(uint32_t, Method*, int32_t); Object* (*pAllocObjectFromCode)(uint32_t, Method*); uint32_t (*pGet32Static)(uint32_t, const Method*); void (*pSet32Static)(uint32_t, const Method*, uint32_t); @@ -221,6 +224,7 @@ class Thread { Class* (*pInitializeTypeFromCode)(uint32_t, Method*); void (*pResolveMethodFromCode)(Method*, uint32_t); void (*pInvokeInterfaceTrampoline)(void*, void*, void*, void*); + StaticStorageBase* (*pInitializeStaticStorage)(uint32_t, const Method*); class StackVisitor { public: diff --git a/test/IntMath/IntMath.java b/test/IntMath/IntMath.java index ba7d575927..1be8a98b0f 100644 --- a/test/IntMath/IntMath.java +++ b/test/IntMath/IntMath.java @@ -712,107 +712,107 @@ class IntMath extends IntMathBase { public static void main(String[] args) { int res = unopTest(38); if (res == 37) { - System.out.printf("unopTest PASSED\n"); + System.out.println("unopTest PASSED"); } else { - System.out.printf("unopTest FAILED: %d\n", res); + System.out.println("unopTest FAILED: " + res); } res = shiftTest1(); if (res == 0) { - System.out.printf("shiftTest1 PASSED\n"); + System.out.println("shiftTest1 PASSED"); } else { - System.out.printf("shiftTest1 FAILED: %d\n", res); + System.out.println("shiftTest1 FAILED: " + res); } res = shiftTest2(); if (res == 0) { - System.out.printf("shiftTest2 PASSED\n"); + System.out.println("shiftTest2 PASSED"); } else { - System.out.printf("shiftTest2 FAILED: %d\n", res); + System.out.println("shiftTest2 FAILED: " + res); } res = unsignedShiftTest(); if (res == 0) { - System.out.printf("unsignedShiftTest PASSED\n"); + System.out.println("unsignedShiftTest PASSED"); } else { - System.out.printf("unsignedShiftTest FAILED: %d\n", res); + System.out.println("unsignedShiftTest FAILED: " + res); } res = convTest(); if (res == 0) { - System.out.printf("convTest PASSED\n"); + System.out.println("convTest PASSED"); } else { - System.out.printf("convTest FAILED: %d\n", res); + System.out.println("convTest FAILED: " + res); } res = charSubTest(); if (res == 0) { - System.out.printf("charSubTest PASSED\n"); + System.out.println("charSubTest PASSED"); } else { - System.out.printf("charSubTest FAILED: %d\n", res); + System.out.println("charSubTest FAILED: " + res); } res = intOperTest(70000, -3); if (res == 0) { - System.out.printf("intOperTest PASSED\n"); + System.out.println("intOperTest PASSED"); } else { - System.out.printf("intOperTest FAILED: %d\n", res); + System.out.println("intOperTest FAILED: " + res); } res = longOperTest(70000000000L, -3L); if (res == 0) { - System.out.printf("longOperTest PASSED\n"); + System.out.println("longOperTest PASSED"); } else { - System.out.printf("longOperTest FAILED: %d\n", res); + System.out.println("longOperTest FAILED: " + res); } long lres = longShiftTest(0xd5aa96deff00aa01L, 16); if (lres == 0x96deff00aa010000L) { - System.out.printf("longShiftTest PASSED\n"); + System.out.println("longShiftTest PASSED"); } else { - System.out.printf("longShiftTest FAILED: %d\n", res); + System.out.println("longShiftTest FAILED: " + res); } res = switchTest(1); if (res == 1234) { - System.out.printf("switchTest PASSED\n"); + System.out.println("switchTest PASSED"); } else { - System.out.printf("switchTest FAILED: %d\n", res); + System.out.println("switchTest FAILED: " + res); } res = testIntCompare(-5, 4, 4, 0); if (res == 1111) { - System.out.printf("testIntCompare PASSED\n"); + System.out.println("testIntCompare PASSED"); } else { - System.out.printf("testIntCompare FAILED: %d\n", res); + System.out.println("testIntCompare FAILED: " + res); } res = testLongCompare(-5L, -4294967287L, 4L, 8L); if (res == 2222) { - System.out.printf("testLongCompare PASSED\n"); + System.out.println("testLongCompare PASSED"); } else { - System.out.printf("testLongCompare FAILED: %d\n", res); + System.out.println("testLongCompare FAILED: " + res); } res = testFloatCompare(-5.0f, 4.0f, 4.0f, (1.0f/0.0f) / (1.0f/0.0f)); if (res == 3333) { - System.out.printf("testFloatCompare PASSED\n"); + System.out.println("testFloatCompare PASSED"); } else { - System.out.printf("testFloatCompare FAILED: %d\n", res); + System.out.println("testFloatCompare FAILED: " + res); } res = testDoubleCompare(-5.0, 4.0, 4.0, (1.0/0.0) / (1.0/0.0)); if (res == 4444) { - System.out.printf("testDoubleCompare PASSED\n"); + System.out.println("testDoubleCompare PASSED"); } else { - System.out.printf("testDoubleCompare FAILED: %d\n", res); + System.out.println("testDoubleCompare FAILED: " + res); } res = fibonacci(10); if (res == 55) { - System.out.printf("fibonacci PASSED\n"); + System.out.println("fibonacci PASSED"); } else { - System.out.printf("fibonacci FAILED: %d\n", res); + System.out.println("fibonacci FAILED: " + res); } /* res = throwAndCatch(); if (res == 0) { - System.out.printf("throwAndCatch PASSED\n"); + System.out.println("throwAndCatch PASSED"); } else { - System.out.printf("throwAndCatch FAILED: %d\n", res); + System.out.println("throwAndCatch FAILED: " + res); } */ @@ -820,44 +820,44 @@ class IntMath extends IntMathBase { (short)11, 12, (char)13, 14, 15, (byte)-16, true, 18, 19, 20L, 21L, 22, 23, 24, 25, 26); if (res == -1) { - System.out.printf("manyArgs PASSED\n"); + System.out.println("manyArgs PASSED"); } else { - System.out.printf("manyArgs FAILED: %d\n", res); + System.out.println("manyArgs FAILED: " + res); } res = staticCall(3); if (res == 6) { - System.out.printf("virtualCall PASSED\n"); + System.out.println("virtualCall PASSED"); } else { - System.out.printf("virtualCall FAILED: %d\n", res); + System.out.println("virtualCall FAILED: " + res); } res = testIGetPut(111); if (res == 333) { - System.out.printf("testGetPut PASSED\n"); + System.out.println("testGetPut PASSED"); } else { - System.out.printf("testGetPut FAILED: %d\n", res); + System.out.println("testGetPut FAILED: " + res); } res = staticFieldTest(404); if (res == 1404) { - System.out.printf("staticFieldTest PASSED\n"); + System.out.println("staticFieldTest PASSED"); } else { - System.out.printf("staticFieldTest FAILED: %d\n", res); + System.out.println("staticFieldTest FAILED: " + res); } res = catchBlock(1000); if (res == 1579) { - System.out.printf("catchBlock PASSED\n"); + System.out.println("catchBlock PASSED"); } else { - System.out.printf("catchBlock FAILED: %d\n", res); + System.out.println("catchBlock FAILED: " + res); } res = superTest(4141); if (res == 4175) { - System.out.printf("superTest PASSED\n"); + System.out.println("superTest PASSED"); } else { - System.out.printf("superTest FAILED: %d\n", res); + System.out.println("superTest FAILED: " + res); } } } |