Continuing Quick compiler refactoring
With this CL, we no longer include any .cc files - all source
files compile stand-alone. We still build a separate .so for
each target, but all code in the target-independent "codegen"
directory is now truly independent and doesn't rely on any
target-specific macros to compile.
Header file inclusion is still a bit of a mess, but that will be
addressed in a subsequent CL.
Next up: create a codegen class to hold code generator routines
overrideable by target.
Change-Id: I3a93118d11afeab11f310950a6a73381a99e26e1
diff --git a/src/compiler/codegen/gen_invoke.cc b/src/compiler/codegen/gen_invoke.cc
index fbab59f..90fc14b 100644
--- a/src/compiler/codegen/gen_invoke.cc
+++ b/src/compiler/codegen/gen_invoke.cc
@@ -15,6 +15,9 @@
*/
#include "oat/runtime/oat_support_entrypoints.h"
+#include "../compiler_ir.h"
+#include "ralloc_util.h"
+#include "codegen_util.h"
namespace art {
@@ -999,5 +1002,157 @@
return false;
}
+void genInvoke(CompilationUnit* cUnit, CallInfo* info)
+{
+ if (genIntrinsic(cUnit, info)) {
+ return;
+ }
+ InvokeType originalType = info->type; // avoiding mutation by ComputeInvokeInfo
+ int callState = 0;
+ LIR* nullCk;
+ LIR** pNullCk = NULL;
+ NextCallInsn nextCallInsn;
+ oatFlushAllRegs(cUnit); /* Everything to home location */
+ // Explicit register usage
+ oatLockCallTemps(cUnit);
+
+ OatCompilationUnit mUnit(cUnit->class_loader, cUnit->class_linker,
+ *cUnit->dex_file,
+ cUnit->code_item, cUnit->method_idx,
+ cUnit->access_flags);
+
+ uint32_t dexMethodIdx = info->index;
+ int vtableIdx;
+ uintptr_t directCode;
+ uintptr_t directMethod;
+ bool skipThis;
+ bool fastPath =
+ cUnit->compiler->ComputeInvokeInfo(dexMethodIdx, &mUnit, info->type,
+ vtableIdx, directCode,
+ directMethod)
+ && !SLOW_INVOKE_PATH;
+ if (info->type == kInterface) {
+ if (fastPath) {
+ pNullCk = &nullCk;
+ }
+ nextCallInsn = fastPath ? nextInterfaceCallInsn
+ : nextInterfaceCallInsnWithAccessCheck;
+ skipThis = false;
+ } else if (info->type == kDirect) {
+ if (fastPath) {
+ pNullCk = &nullCk;
+ }
+ nextCallInsn = fastPath ? nextSDCallInsn : nextDirectCallInsnSP;
+ skipThis = false;
+ } else if (info->type == kStatic) {
+ nextCallInsn = fastPath ? nextSDCallInsn : nextStaticCallInsnSP;
+ skipThis = false;
+ } else if (info->type == kSuper) {
+ DCHECK(!fastPath); // Fast path is a direct call.
+ nextCallInsn = nextSuperCallInsnSP;
+ skipThis = false;
+ } else {
+ DCHECK_EQ(info->type, kVirtual);
+ nextCallInsn = fastPath ? nextVCallInsn : nextVCallInsnSP;
+ skipThis = fastPath;
+ }
+ if (!info->isRange) {
+ callState = genDalvikArgsNoRange(cUnit, info, callState, pNullCk,
+ nextCallInsn, dexMethodIdx,
+ vtableIdx, directCode, directMethod,
+ originalType, skipThis);
+ } else {
+ callState = genDalvikArgsRange(cUnit, info, callState, pNullCk,
+ nextCallInsn, dexMethodIdx, vtableIdx,
+ directCode, directMethod, originalType,
+ skipThis);
+ }
+ // Finish up any of the call sequence not interleaved in arg loading
+ while (callState >= 0) {
+ callState = nextCallInsn(cUnit, info, callState, dexMethodIdx,
+ vtableIdx, directCode, directMethod,
+ originalType);
+ }
+ if (cUnit->enableDebug & (1 << kDebugDisplayMissingTargets)) {
+ genShowTarget(cUnit);
+ }
+ LIR* callInst;
+ if (cUnit->instructionSet != kX86) {
+ callInst = opReg(cUnit, kOpBlx, targetReg(kInvokeTgt));
+ } else {
+ if (fastPath && info->type != kInterface) {
+ callInst = opMem(cUnit, kOpBlx, targetReg(kArg0),
+ AbstractMethod::GetCodeOffset().Int32Value());
+ } else {
+ int trampoline = 0;
+ switch (info->type) {
+ case kInterface:
+ trampoline = fastPath ? ENTRYPOINT_OFFSET(pInvokeInterfaceTrampoline)
+ : ENTRYPOINT_OFFSET(pInvokeInterfaceTrampolineWithAccessCheck);
+ break;
+ case kDirect:
+ trampoline = ENTRYPOINT_OFFSET(pInvokeDirectTrampolineWithAccessCheck);
+ break;
+ case kStatic:
+ trampoline = ENTRYPOINT_OFFSET(pInvokeStaticTrampolineWithAccessCheck);
+ break;
+ case kSuper:
+ trampoline = ENTRYPOINT_OFFSET(pInvokeSuperTrampolineWithAccessCheck);
+ break;
+ case kVirtual:
+ trampoline = ENTRYPOINT_OFFSET(pInvokeVirtualTrampolineWithAccessCheck);
+ break;
+ default:
+ LOG(FATAL) << "Unexpected invoke type";
+ }
+ callInst = opThreadMem(cUnit, kOpBlx, trampoline);
+ }
+ }
+ markSafepointPC(cUnit, callInst);
+
+ oatClobberCalleeSave(cUnit);
+ if (info->result.location != kLocInvalid) {
+ // We have a following MOVE_RESULT - do it now.
+ if (info->result.wide) {
+ RegLocation retLoc = oatGetReturnWide(cUnit, info->result.fp);
+ storeValueWide(cUnit, info->result, retLoc);
+ } else {
+ RegLocation retLoc = oatGetReturn(cUnit, info->result.fp);
+ storeValue(cUnit, info->result, retLoc);
+ }
+ }
+}
+
+/*
+ * Build an array of location records for the incoming arguments.
+ * Note: one location record per word of arguments, with dummy
+ * high-word loc for wide arguments. Also pull up any following
+ * MOVE_RESULT and incorporate it into the invoke.
+ */
+CallInfo* oatNewCallInfo(CompilationUnit* cUnit, BasicBlock* bb, MIR* mir,
+ InvokeType type, bool isRange)
+{
+ CallInfo* info = static_cast<CallInfo*>(oatNew(cUnit, sizeof(CallInfo), true, kAllocMisc));
+ MIR* moveResultMIR = oatFindMoveResult(cUnit, bb, mir);
+ if (moveResultMIR == NULL) {
+ info->result.location = kLocInvalid;
+ } else {
+ info->result = oatGetRawDest(cUnit, moveResultMIR);
+ moveResultMIR->dalvikInsn.opcode = Instruction::NOP;
+ }
+ info->numArgWords = mir->ssaRep->numUses;
+ info->args = (info->numArgWords == 0) ? NULL : static_cast<RegLocation*>
+ (oatNew(cUnit, sizeof(RegLocation) * info->numArgWords, false, kAllocMisc));
+ for (int i = 0; i < info->numArgWords; i++) {
+ info->args[i] = oatGetRawSrc(cUnit, mir, i);
+ }
+ info->optFlags = mir->optimizationFlags;
+ info->type = type;
+ info->isRange = isRange;
+ info->index = mir->dalvikInsn.vB;
+ info->offset = mir->offset;
+ return info;
+}
+
} // namespace art