Merge "Fix a couple of JDWP bugs." into ics-mr1-plus-art
diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h
index 2f95be2..4d749ce 100644
--- a/src/compiler/Compiler.h
+++ b/src/compiler/Compiler.h
@@ -127,6 +127,9 @@
kDebugShowMemoryUsage,
kDebugShowNops,
kDebugCountOpcodes,
+#if defined(ART_USE_QUICK_COMPILER)
+ kDebugDumpBitcodeFile,
+#endif
};
enum OatMethodAttributes {
@@ -193,6 +196,7 @@
void oatProcessSwitchTables(CompilationUnit* cUnit);
bool oatIsFpReg(int reg);
uint32_t oatFpRegMask(void);
+void oatReplaceSpecialChars(std::string& str);
} // namespace art
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index b1c7427..ba99715 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -504,6 +504,7 @@
/* SSA name for Method* */
int methodSReg;
+ RegLocation methodLoc; // Describes location of method*
/*
* Set to the Dalvik PC of the switch instruction if it has more than
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index d5e6b12..3d6e983 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -52,6 +52,9 @@
//(1 << kDebugShowMemoryUsage) |
//(1 << kDebugShowNops) |
//(1 << kDebugCountOpcodes) |
+#if defined(ART_USE_QUICK_COMPILER)
+ //(1 << kDebugDumpBitcodeFile) |
+#endif
0;
inline bool contentIsInsn(const u2* codePtr) {
@@ -243,37 +246,26 @@
return bb;
}
+/* Turn method name into a legal Linux file name */
+void oatReplaceSpecialChars(std::string& str)
+{
+ static const struct { const char before; const char after; } match[] =
+ {{'/','-'}, {';','#'}, {' ','#'}, {'$','+'},
+ {'(','@'}, {')','@'}, {'<','='}, {'>','='}};
+ for (unsigned int i = 0; i < sizeof(match)/sizeof(match[0]); i++) {
+ std::replace(str.begin(), str.end(), match[i].before, match[i].after);
+ }
+}
+
/* Dump the CFG into a DOT graph */
void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix)
{
FILE* file;
- std::string name(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
- char startOffset[80];
- sprintf(startOffset, "_%x", cUnit->entryBlock->fallThrough->startOffset);
- char* fileName = (char*) oatNew(cUnit, strlen(dirPrefix) +
- name.length() + strlen(".dot") + 1,
- true, kAllocDebugInfo);
- sprintf(fileName, "%s%s%s.dot", dirPrefix, name.c_str(), startOffset);
-
- /*
- * Convert the special characters into a filesystem- and shell-friendly
- * format.
- */
- int i;
- for (i = strlen(dirPrefix); fileName[i]; i++) {
- if (fileName[i] == '/') {
- fileName[i] = '_';
- } else if (fileName[i] == ';') {
- fileName[i] = '#';
- } else if (fileName[i] == '$') {
- fileName[i] = '+';
- } else if (fileName[i] == '(' || fileName[i] == ')') {
- fileName[i] = '@';
- } else if (fileName[i] == '<' || fileName[i] == '>') {
- fileName[i] = '=';
- }
- }
- file = fopen(fileName, "w");
+ std::string fname(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
+ oatReplaceSpecialChars(fname);
+ fname = StringPrintf("%s%s%x.dot", dirPrefix, fname.c_str(),
+ cUnit->entryBlock->fallThrough->startOffset);
+ file = fopen(fname.c_str(), "w");
if (file == NULL) {
return;
}
@@ -788,6 +780,7 @@
#if defined(ART_USE_QUICK_COMPILER)
if (cUnit->genBitcode) {
cUnit->printMe = true;
+ cUnit->enableDebug |= (1 << kDebugDumpBitcodeFile);
}
#endif
if (cUnit->instructionSet == kX86) {
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index 29766e0..0062f53 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -339,6 +339,17 @@
INVALID_REG, INVALID_REG, INVALID_SREG,
INVALID_SREG};
+int oatComputeFrameSize(CompilationUnit* cUnit) {
+ /* Figure out the frame size */
+ static const uint32_t kAlignMask = kStackAlignment - 1;
+ uint32_t size = (cUnit->numCoreSpills + cUnit->numFPSpills +
+ 1 /* filler word */ + cUnit->numRegs + cUnit->numOuts +
+ cUnit->numCompilerTemps + 1 /* curMethod* */)
+ * sizeof(uint32_t);
+ /* Align and set */
+ return (size + kAlignMask) & ~(kAlignMask);
+}
+
/*
* Simple register allocation. Some Dalvik virtual registers may
* be promoted to physical registers. Most of the work for temp
@@ -459,19 +470,16 @@
oatDoPromotion(cUnit);
+ /* Get easily-accessable post-promotion copy of RegLocation for Method* */
+ cUnit->methodLoc = cUnit->regLocation[cUnit->methodSReg];
+
if (cUnit->printMe && !(cUnit->disableOpt & (1 << kPromoteRegs))) {
LOG(INFO) << "After Promotion";
oatDumpRegLocTable(cUnit->regLocation, cUnit->numSSARegs);
}
- /* Figure out the frame size */
- static const uint32_t kAlignMask = kStackAlignment - 1;
- uint32_t size = (cUnit->numCoreSpills + cUnit->numFPSpills +
- 1 /* filler word */ + cUnit->numRegs + cUnit->numOuts +
- cUnit->numCompilerTemps + 1 /* curMethod* */)
- * sizeof(uint32_t);
- /* Align and set */
- cUnit->frameSize = (size + kAlignMask) & ~(kAlignMask);
+ /* Set the frame size */
+ cUnit->frameSize = oatComputeFrameSize(cUnit);
}
} // namespace art
diff --git a/src/compiler/SSATransformation.cc b/src/compiler/SSATransformation.cc
index 6eb0415..7d6a733 100644
--- a/src/compiler/SSATransformation.cc
+++ b/src/compiler/SSATransformation.cc
@@ -206,7 +206,6 @@
if (mismatch) {
LOG(INFO) << "Mismatch for "
<< PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
- oatDumpCFG(cUnit, "/tmp/");
LOG(INFO) << "New dfs";
for (unsigned int i = 0; i < cUnit->dfsOrder.numUsed; i++) {
LOG(INFO) << i << " - " << cUnit->dfsOrder.elemList[i];
diff --git a/src/compiler/codegen/CodegenFactory.cc b/src/compiler/codegen/CodegenFactory.cc
index 71b557c..9d380c7 100644
--- a/src/compiler/codegen/CodegenFactory.cc
+++ b/src/compiler/codegen/CodegenFactory.cc
@@ -292,17 +292,17 @@
/* Utilities to load the current Method* */
void loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt)
{
- loadValueDirectFixed(cUnit, cUnit->regLocation[cUnit->methodSReg], rTgt);
+ loadValueDirectFixed(cUnit, cUnit->methodLoc, rTgt);
}
RegLocation loadCurrMethod(CompilationUnit *cUnit)
{
- return loadValue(cUnit, cUnit->regLocation[cUnit->methodSReg], kCoreReg);
+ return loadValue(cUnit, cUnit->methodLoc, kCoreReg);
}
bool methodStarInReg(CompilationUnit* cUnit)
{
- return (cUnit->regLocation[cUnit->methodSReg].location == kLocPhysReg);
+ return (cUnit->methodLoc.location == kLocPhysReg);
}
diff --git a/src/compiler/codegen/GenInvoke.cc b/src/compiler/codegen/GenInvoke.cc
index bcc9067..7c2cf1c 100644
--- a/src/compiler/codegen/GenInvoke.cc
+++ b/src/compiler/codegen/GenInvoke.cc
@@ -33,16 +33,18 @@
* If there are any ins passed in registers that have not been promoted
* to a callee-save register, flush them to the frame. Perform intial
* assignment of promoted arguments.
+ *
+ * argLocs is an array of location records describing the incoming arguments
+ * with one location record per word of argument.
*/
-void flushIns(CompilationUnit* cUnit)
+void flushIns(CompilationUnit* cUnit, RegLocation* argLocs, RegLocation rlMethod)
{
/*
* Dummy up a RegLocation for the incoming Method*
* It will attempt to keep rARG0 live (or copy it to home location
* if promoted).
*/
- RegLocation rlSrc = cUnit->regLocation[cUnit->methodSReg];
- RegLocation rlMethod = cUnit->regLocation[cUnit->methodSReg];
+ RegLocation rlSrc = rlMethod;
rlSrc.location = kLocPhysReg;
rlSrc.lowReg = rARG0;
rlSrc.home = false;
@@ -75,7 +77,7 @@
if (i < numArgRegs) {
// If arriving in register
bool needFlush = true;
- RegLocation* tLoc = &cUnit->regLocation[startVReg + i];
+ RegLocation* tLoc = &argLocs[i];
if ((vMap->coreLocation == kLocPhysReg) && !tLoc->fp) {
opRegCopy(cUnit, vMap->coreReg, argRegs[i]);
needFlush = false;
diff --git a/src/compiler/codegen/MethodBitcode.cc b/src/compiler/codegen/MethodBitcode.cc
index f13a473..66823c2 100644
--- a/src/compiler/codegen/MethodBitcode.cc
+++ b/src/compiler/codegen/MethodBitcode.cc
@@ -27,6 +27,7 @@
#include <llvm/Type.h>
#include <llvm/Instructions.h>
#include <llvm/Support/Casting.h>
+#include <llvm/Support/InstIterator.h>
const char* labelFormat = "L0x%x_%d";
@@ -75,6 +76,50 @@
return res;
}
+/* Create an in-memory RegLocation from an llvm Value. */
+void createLocFromValue(CompilationUnit* cUnit, llvm::Value* val)
+{
+ // NOTE: llvm takes shortcuts with c_str() - get to std::string firstt
+ std::string s(val->getName().str());
+ const char* valName = s.c_str();
+ if (cUnit->printMe) {
+ LOG(INFO) << "Processing llvm Value " << valName;
+ }
+ SafeMap<llvm::Value*, RegLocation>::iterator it = cUnit->locMap.find(val);
+ DCHECK(it == cUnit->locMap.end()) << " - already defined: " << valName;
+ int baseSReg = INVALID_SREG;
+ int subscript = -1;
+ sscanf(valName, "v%d_%d", &baseSReg, &subscript);
+ if ((baseSReg == INVALID_SREG) && (!strcmp(valName, "method"))) {
+ baseSReg = SSA_METHOD_BASEREG;
+ subscript = 0;
+ }
+ if (cUnit->printMe) {
+ LOG(INFO) << "Base: " << baseSReg << ", Sub: " << subscript;
+ }
+ DCHECK_NE(baseSReg, INVALID_SREG);
+ DCHECK_NE(subscript, -1);
+ // TODO: redo during C++'ification
+ RegLocation loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0, INVALID_REG,
+ INVALID_REG, INVALID_SREG, INVALID_SREG};
+ llvm::Type* ty = val->getType();
+ loc.wide = ((ty == cUnit->irb->getInt64Ty()) ||
+ (ty == cUnit->irb->getDoubleTy()));
+ loc.defined = true;
+ if ((ty == cUnit->irb->getFloatTy()) ||
+ (ty == cUnit->irb->getDoubleTy())) {
+ loc.fp = true;
+ } else if (ty == cUnit->irb->GetJObjectTy()) {
+ loc.ref = true;
+ } else {
+ loc.core = true;
+ }
+ loc.home = false; // Will change during promotion
+ loc.sRegLow = baseSReg;
+ loc.origSReg = cUnit->locMap.size();
+ cUnit->locMap.Put(val, loc);
+}
+
void initIR(CompilationUnit* cUnit)
{
cUnit->context = new llvm::LLVMContext();
@@ -1372,19 +1417,25 @@
llvm::verifyFunction(*cUnit->func, llvm::PrintMessageAction);
- // Write bitcode to file
- std::string errmsg;
+ if (cUnit->enableDebug & (1 << kDebugDumpBitcodeFile)) {
+ // Write bitcode to file
+ std::string errmsg;
+ std::string fname(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
+ oatReplaceSpecialChars(fname);
+ // TODO: make configurable
+ fname = StringPrintf("/tmp/%s.bc", fname.c_str());
- llvm::OwningPtr<llvm::tool_output_file> out_file(
- new llvm::tool_output_file("/tmp/foo.bc", errmsg,
- llvm::raw_fd_ostream::F_Binary));
+ llvm::OwningPtr<llvm::tool_output_file> out_file(
+ new llvm::tool_output_file(fname.c_str(), errmsg,
+ llvm::raw_fd_ostream::F_Binary));
- if (!errmsg.empty()) {
- LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
+ if (!errmsg.empty()) {
+ LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
+ }
+
+ llvm::WriteBitcodeToFile(cUnit->module, out_file->os());
+ out_file->keep();
}
-
- llvm::WriteBitcodeToFile(cUnit->module, out_file->os());
- out_file->keep();
}
RegLocation getLoc(CompilationUnit* cUnit, llvm::Value* val) {
@@ -1575,11 +1626,6 @@
UNIMPLEMENTED(FATAL);
}
-void setMethodInfo(CompilationUnit* cUnit, llvm::CallInst* callInst)
-{
- UNIMPLEMENTED(WARNING) << "Net setMethodInfo";
-}
-
void cvtCopy(CompilationUnit* cUnit, llvm::CallInst* callInst)
{
DCHECK(callInst->getNumArgOperands() == 1);
@@ -1670,6 +1716,14 @@
genInvoke(cUnit, info);
}
+/* Look up the RegLocation associated with a Value. Must already be defined */
+RegLocation valToLoc(CompilationUnit* cUnit, llvm::Value* val)
+{
+ SafeMap<llvm::Value*, RegLocation>::iterator it = cUnit->locMap.find(val);
+ DCHECK(it != cUnit->locMap.end()) << "Missing definition";
+ return it->second;
+}
+
bool methodBitcodeBlockCodeGen(CompilationUnit* cUnit, llvm::BasicBlock* bb)
{
bool isEntry = (bb == &cUnit->func->getEntryBlock());
@@ -1697,7 +1751,19 @@
if (isEntry) {
cUnit->currentDalvikOffset = 0;
- genEntrySequence(cUnit);
+ RegLocation* argLocs = (RegLocation*)
+ oatNew(cUnit, sizeof(RegLocation) * cUnit->numIns, true, kAllocMisc);
+ llvm::Function::arg_iterator it(cUnit->func->arg_begin());
+ llvm::Function::arg_iterator it_end(cUnit->func->arg_end());
+ for (unsigned i = 0; it != it_end; ++it) {
+ llvm::Value* val = it;
+ argLocs[i++] = valToLoc(cUnit, val);
+ llvm::Type* ty = val->getType();
+ if ((ty == cUnit->irb->getInt64Ty()) || (ty == cUnit->irb->getDoubleTy())) {
+ argLocs[i++].sRegLow = INVALID_SREG;
+ }
+ }
+ genEntrySequence(cUnit, argLocs, cUnit->methodLoc);
}
// Visit all of the instructions in the block
@@ -1779,7 +1845,7 @@
cvtConst(cUnit, callInst);
break;
case greenland::IntrinsicHelper::MethodInfo:
- setMethodInfo(cUnit, callInst);
+ // Already dealt with - just ignore it here.
break;
case greenland::IntrinsicHelper::CheckSuspend:
genSuspendTest(cUnit, 0 /* optFlags already applied */);
@@ -1891,17 +1957,62 @@
*/
void oatMethodBitcode2LIR(CompilationUnit* cUnit)
{
- int numBasicBlocks = cUnit->func->getBasicBlockList().size();
+ llvm::Function* func = cUnit->func;
+ int numBasicBlocks = func->getBasicBlockList().size();
// Allocate a list for LIR basic block labels
cUnit->blockLabelList =
(void*)oatNew(cUnit, sizeof(LIR) * numBasicBlocks, true, kAllocLIR);
LIR* labelList = (LIR*)cUnit->blockLabelList;
int nextLabel = 0;
- for (llvm::Function::iterator i = cUnit->func->begin(),
- e = cUnit->func->end(); i != e; ++i) {
+ for (llvm::Function::iterator i = func->begin(),
+ e = func->end(); i != e; ++i) {
cUnit->blockToLabelMap.Put(static_cast<llvm::BasicBlock*>(i),
&labelList[nextLabel++]);
}
+
+ /*
+ * Keep honest - clear regLocations, Value => RegLocation,
+ * promotion map and VmapTables.
+ */
+ cUnit->locMap.clear(); // Start fresh
+ cUnit->regLocation = NULL;
+ for (int i = 0; i < cUnit->numDalvikRegisters + cUnit->numCompilerTemps + 1;
+ i++) {
+ cUnit->promotionMap[i].coreLocation = kLocDalvikFrame;
+ cUnit->promotionMap[i].fpLocation = kLocDalvikFrame;
+ }
+ cUnit->coreSpillMask = 0;
+ cUnit->numCoreSpills = 0;
+ cUnit->fpSpillMask = 0;
+ cUnit->numFPSpills = 0;
+ cUnit->coreVmapTable.clear();
+ cUnit->fpVmapTable.clear();
+ oatAdjustSpillMask(cUnit);
+ cUnit->frameSize = oatComputeFrameSize(cUnit);
+
+ /*
+ * At this point, we've lost all knowledge of register promotion.
+ * Rebuild that info from the MethodInfo intrinsic (if it
+ * exists - not required for correctness).
+ */
+ // TODO: find and recover MethodInfo.
+
+ // Create RegLocations for arguments
+ llvm::Function::arg_iterator it(cUnit->func->arg_begin());
+ llvm::Function::arg_iterator it_end(cUnit->func->arg_end());
+ for (; it != it_end; ++it) {
+ llvm::Value* val = it;
+ createLocFromValue(cUnit, val);
+ }
+ // Create RegLocations for all non-argument defintions
+ for (llvm::inst_iterator i = llvm::inst_begin(func),
+ e = llvm::inst_end(func); i != e; ++i) {
+ llvm::Value* val = &*i;
+ if (val->hasName() && (val->getName().str().c_str()[0] == 'v')) {
+ createLocFromValue(cUnit, val);
+ }
+ }
+
// Walk the blocks, generating code.
for (llvm::Function::iterator i = cUnit->func->begin(),
e = cUnit->func->end(); i != e; ++i) {
diff --git a/src/compiler/codegen/MethodCodegenDriver.cc b/src/compiler/codegen/MethodCodegenDriver.cc
index aab323b..7898ddb 100644
--- a/src/compiler/codegen/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/MethodCodegenDriver.cc
@@ -904,7 +904,9 @@
LIR* headLIR = NULL;
if (bb->blockType == kEntryBlock) {
- genEntrySequence(cUnit);
+ int startVReg = cUnit->numDalvikRegisters - cUnit->numIns;
+ genEntrySequence(cUnit, &cUnit->regLocation[startVReg],
+ cUnit->regLocation[cUnit->methodSReg]);
} else if (bb->blockType == kExitBlock) {
genExitSequence(cUnit);
}
diff --git a/src/compiler/codegen/Ralloc.h b/src/compiler/codegen/Ralloc.h
index 8c3887a..ec47e22 100644
--- a/src/compiler/codegen/Ralloc.h
+++ b/src/compiler/codegen/Ralloc.h
@@ -229,6 +229,7 @@
extern void oatAdjustSpillMask(CompilationUnit* cUnit);
void oatMarkPreservedSingle(CompilationUnit* cUnit, int vReg, int reg);
void oatRegCopy(CompilationUnit* cUnit, int rDest, int rSrc);
+int oatComputeFrameSize(CompilationUnit* cUnit);
} // namespace art
diff --git a/src/compiler/codegen/RallocUtil.cc b/src/compiler/codegen/RallocUtil.cc
index e2f2cd6..074fd26 100644
--- a/src/compiler/codegen/RallocUtil.cc
+++ b/src/compiler/codegen/RallocUtil.cc
@@ -29,17 +29,6 @@
namespace art {
-#define SREG(c, s) ((c)->regLocation[(s)].sRegLow)
-/*
- * Get the "real" sreg number associated with an sReg slot. In general,
- * sReg values passed through codegen are the SSA names created by
- * dataflow analysis and refer to slot numbers in the cUnit->regLocation
- * array. However, renaming is accomplished by simply replacing RegLocation
- * entries in the cUnit->reglocation[] array. Therefore, when location
- * records for operands are first created, we need to ask the locRecord
- * identified by the dataflow pass what it's new name is.
- */
-
/*
* Free all allocated temps in the temp pools. Note that this does
* not affect the "liveness" of a temp register, which will stay
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index c0d91a4..ba49277 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -56,7 +56,8 @@
return rLR;
}
-void genEntrySequence(CompilationUnit* cUnit)
+void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs,
+ RegLocation rlMethod)
{
int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
/*
@@ -101,7 +102,7 @@
opRegImm(cUnit, kOpSub, rSP, cUnit->frameSize - (spillCount * 4));
}
- flushIns(cUnit);
+ flushIns(cUnit, argLocs, rlMethod);
if (cUnit->genDebugger) {
// Refresh update debugger callout
diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc
index bf4c8a6..4a61efb 100644
--- a/src/compiler/codegen/mips/ArchFactory.cc
+++ b/src/compiler/codegen/mips/ArchFactory.cc
@@ -144,7 +144,8 @@
opRegImm(cUnit, kOpAdd, rSP, cUnit->frameSize);
}
-void genEntrySequence(CompilationUnit* cUnit)
+void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs,
+ RegLocation rlMethod)
{
int spillCount = cUnit->numCoreSpills + cUnit->numFPSpills;
/*
@@ -183,7 +184,7 @@
opRegImm(cUnit, kOpSub, rSP, cUnit->frameSize - (spillCount * 4));
}
- flushIns(cUnit);
+ flushIns(cUnit, argLocs, rlMethod);
if (cUnit->genDebugger) {
// Refresh update debugger callout
diff --git a/src/compiler/codegen/x86/ArchFactory.cc b/src/compiler/codegen/x86/ArchFactory.cc
index b3cebdc..1620044 100644
--- a/src/compiler/codegen/x86/ArchFactory.cc
+++ b/src/compiler/codegen/x86/ArchFactory.cc
@@ -163,7 +163,8 @@
newLIR2(cUnit, opcode, rDest, threadOffset);
}
-void genEntrySequence(CompilationUnit* cUnit)
+void genEntrySequence(CompilationUnit* cUnit, RegLocation* argLocs,
+ RegLocation rlMethod)
{
/*
* On entry, rARG0, rARG1, rARG2 are live. Let the register
@@ -199,7 +200,7 @@
oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
}
- flushIns(cUnit);
+ flushIns(cUnit, argLocs, rlMethod);
if (cUnit->genDebugger) {
// Refresh update debugger callout