Bring our native stack usage down.

I'd have preferred to have a 512-byte limit, but there are some monsters
in the verifier; 2000-line functions and the like. I'm also not policing
tests (except for one silly one). They can use all the stack they like.

This fixes the IntMath test (the stack overflow test was failing because
we were using more than 4KiB to throw!).

Change-Id: I7e53e2fde2b39fde1910f8ee5b1712e8a66069c7
diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc
index e73ccc9..0eff7ea 100644
--- a/src/compiler/Dataflow.cc
+++ b/src/compiler/Dataflow.cc
@@ -1689,7 +1689,7 @@
                                   const MIR* mir)
 {
     char buffer[256];
-    char operand0[256], operand1[256];
+    char operand0[32], operand1[32];
     const DecodedInstruction *insn = &mir->dalvikInsn;
     int opcode = insn->opcode;
     int dfAttributes = oatDataFlowAttributes[opcode];
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 015aee9..bee0376 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -697,7 +697,6 @@
     }
     oatArenaReset();
 
-    CompilationUnit cUnit;
     art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker();
     const art::DexFile& dex_file = class_linker->FindDexFile(
          method->GetDeclaringClass()->GetDexCache());
@@ -710,59 +709,59 @@
 
     oatInit(compiler);
 
-    memset(&cUnit, 0, sizeof(cUnit));
-    cUnit.compiler = &compiler;
-    cUnit.method = method;
-    cUnit.instructionSet = (OatInstructionSetType)insnSet;
-    cUnit.insns = code_item->insns_;
-    cUnit.insnsSize = code_item->insns_size_;
+    UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
+    memset(cUnit.get(), 0, sizeof(*cUnit));
+    cUnit->compiler = &compiler;
+    cUnit->method = method;
+    cUnit->instructionSet = (OatInstructionSetType)insnSet;
+    cUnit->insns = code_item->insns_;
+    cUnit->insnsSize = code_item->insns_size_;
     bool useMatch = compilerMethodMatch.length() != 0;
     bool match = useMatch && (compilerFlipMatch ^
         (PrettyMethod(method).find(compilerMethodMatch) != std::string::npos));
     if (!useMatch || match) {
-        cUnit.disableOpt = compilerOptimizerDisableFlags;
-        cUnit.enableDebug = compilerDebugFlags;
-        cUnit.printMe = compiler.IsVerbose() ||
-            (cUnit.enableDebug & (1 << kDebugVerbose));
+        cUnit->disableOpt = compilerOptimizerDisableFlags;
+        cUnit->enableDebug = compilerDebugFlags;
+        cUnit->printMe = compiler.IsVerbose() || (cUnit->enableDebug & (1 << kDebugVerbose));
     }
 
     /* Assume non-throwing leaf */
-    cUnit.attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
+    cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
 
     /* Initialize the block list */
-    oatInitGrowableList(&cUnit.blockList, 40);
+    oatInitGrowableList(&cUnit->blockList, 40);
 
     /* Initialize the switchTables list */
-    oatInitGrowableList(&cUnit.switchTables, 4);
+    oatInitGrowableList(&cUnit->switchTables, 4);
 
     /* Intialize the fillArrayData list */
-    oatInitGrowableList(&cUnit.fillArrayData, 4);
+    oatInitGrowableList(&cUnit->fillArrayData, 4);
 
     /* Intialize the throwLaunchpads list */
-    oatInitGrowableList(&cUnit.throwLaunchpads, 4);
+    oatInitGrowableList(&cUnit->throwLaunchpads, 4);
 
     /* Intialize the suspendLaunchpads list */
-    oatInitGrowableList(&cUnit.suspendLaunchpads, 4);
+    oatInitGrowableList(&cUnit->suspendLaunchpads, 4);
 
     /* Allocate the bit-vector to track the beginning of basic blocks */
-    ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit.insnsSize,
+    ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit->insnsSize,
                                                      true /* expandable */);
-    cUnit.tryBlockAddr = tryBlockAddr;
+    cUnit->tryBlockAddr = tryBlockAddr;
 
     /* Create the default entry and exit blocks and enter them to the list */
     BasicBlock *entryBlock = oatNewBB(kEntryBlock, numBlocks++);
     BasicBlock *exitBlock = oatNewBB(kExitBlock, numBlocks++);
 
-    cUnit.entryBlock = entryBlock;
-    cUnit.exitBlock = exitBlock;
+    cUnit->entryBlock = entryBlock;
+    cUnit->exitBlock = exitBlock;
 
-    oatInsertGrowableList(&cUnit.blockList, (intptr_t) entryBlock);
-    oatInsertGrowableList(&cUnit.blockList, (intptr_t) exitBlock);
+    oatInsertGrowableList(&cUnit->blockList, (intptr_t) entryBlock);
+    oatInsertGrowableList(&cUnit->blockList, (intptr_t) exitBlock);
 
     /* Current block to record parsed instructions */
     BasicBlock *curBlock = oatNewBB(kDalvikByteCode, numBlocks++);
     curBlock->startOffset = 0;
-    oatInsertGrowableList(&cUnit.blockList, (intptr_t) curBlock);
+    oatInsertGrowableList(&cUnit->blockList, (intptr_t) curBlock);
     entryBlock->fallThrough = curBlock;
     oatSetBit(curBlock->predecessors, entryBlock->id);
 
@@ -770,10 +769,10 @@
      * Store back the number of blocks since new blocks may be created of
      * accessing cUnit.
      */
-    cUnit.numBlocks = numBlocks;
+    cUnit->numBlocks = numBlocks;
 
     /* Identify code range in try blocks and set up the empty catch blocks */
-    processTryCatchBlocks(&cUnit);
+    processTryCatchBlocks(cUnit.get());
 
     /* Parse all instructions and put them into containing basic blocks */
     while (codePtr < codeEnd) {
@@ -792,7 +791,7 @@
         int flags = dexGetFlagsFromOpcode(insn->dalvikInsn.opcode);
 
         if (flags & kInstrCanBranch) {
-            processCanBranch(&cUnit, curBlock, insn, curOffset, width, flags,
+            processCanBranch(cUnit.get(), curBlock, insn, curOffset, width, flags,
                              codePtr, codeEnd);
         } else if (flags & kInstrCanReturn) {
             curBlock->fallThrough = exitBlock;
@@ -807,7 +806,7 @@
                  * (incl. OP_NOP).
                  */
                 if (contentIsInsn(codePtr)) {
-                    findBlock(&cUnit, curOffset + width,
+                    findBlock(cUnit.get(), curOffset + width,
                               /* split */
                               false,
                               /* create */
@@ -815,13 +814,13 @@
                 }
             }
         } else if (flags & kInstrCanThrow) {
-            processCanThrow(&cUnit, curBlock, insn, curOffset, width, flags,
+            processCanThrow(cUnit.get(), curBlock, insn, curOffset, width, flags,
                             tryBlockAddr, codePtr, codeEnd);
         } else if (flags & kInstrCanSwitch) {
-            processCanSwitch(&cUnit, curBlock, insn, curOffset, width, flags);
+            processCanSwitch(cUnit.get(), curBlock, insn, curOffset, width, flags);
         }
         curOffset += width;
-        BasicBlock *nextBlock = findBlock(&cUnit, curOffset,
+        BasicBlock *nextBlock = findBlock(cUnit.get(), curOffset,
                                           /* split */
                                           false,
                                           /* create */
@@ -846,84 +845,74 @@
         }
     }
 
-    if (cUnit.printMe) {
-        oatDumpCompilationUnit(&cUnit);
+    if (cUnit->printMe) {
+        oatDumpCompilationUnit(cUnit.get());
     }
 
     /* Adjust this value accordingly once inlining is performed */
-    cUnit.numDalvikRegisters = cUnit.method->NumRegisters();
+    cUnit->numDalvikRegisters = cUnit->method->NumRegisters();
 
 
     /* Verify if all blocks are connected as claimed */
-    oatDataFlowAnalysisDispatcher(&cUnit, verifyPredInfo,
-                                          kAllNodes,
-                                          false /* isIterative */);
-
-
+    oatDataFlowAnalysisDispatcher(cUnit.get(), verifyPredInfo, kAllNodes, false /* isIterative */);
 
     /* Perform SSA transformation for the whole method */
-    oatMethodSSATransformation(&cUnit);
+    oatMethodSSATransformation(cUnit.get());
 
     /* Perform null check elimination */
-    oatMethodNullCheckElimination(&cUnit);
+    oatMethodNullCheckElimination(cUnit.get());
 
-    oatInitializeRegAlloc(&cUnit);  // Needs to happen after SSA naming
+    oatInitializeRegAlloc(cUnit.get());  // Needs to happen after SSA naming
 
     /* Allocate Registers using simple local allocation scheme */
-    oatSimpleRegAlloc(&cUnit);
+    oatSimpleRegAlloc(cUnit.get());
 
     /* Convert MIR to LIR, etc. */
-    oatMethodMIR2LIR(&cUnit);
+    oatMethodMIR2LIR(cUnit.get());
 
     // Debugging only
-    if (cUnit.enableDebug & (1 << kDebugDumpCFG)) {
-        oatDumpCFG(&cUnit, "/sdcard/cfg/");
+    if (cUnit->enableDebug & (1 << kDebugDumpCFG)) {
+        oatDumpCFG(cUnit.get(), "/sdcard/cfg/");
     }
 
     /* Method is not empty */
-    if (cUnit.firstLIRInsn) {
+    if (cUnit->firstLIRInsn) {
 
         // mark the targets of switch statement case labels
-        oatProcessSwitchTables(&cUnit);
+        oatProcessSwitchTables(cUnit.get());
 
         /* Convert LIR into machine code. */
-        oatAssembleLIR(&cUnit);
+        oatAssembleLIR(cUnit.get());
 
-        if (cUnit.printMe) {
-            oatCodegenDump(&cUnit);
+        if (cUnit->printMe) {
+            oatCodegenDump(cUnit.get());
         }
     }
 
     // Combine vmap tables - core regs, then fp regs - into vmapTable
     std::vector<uint16_t> vmapTable;
-    for (size_t i = 0 ; i < cUnit.coreVmapTable.size(); i++) {
-        vmapTable.push_back(cUnit.coreVmapTable[i]);
+    for (size_t i = 0 ; i < cUnit->coreVmapTable.size(); i++) {
+        vmapTable.push_back(cUnit->coreVmapTable[i]);
     }
     // Add a marker to take place of lr
-    cUnit.coreVmapTable.push_back(INVALID_VREG);
+    cUnit->coreVmapTable.push_back(INVALID_VREG);
     // Combine vmap tables - core regs, then fp regs
-    for (uint32_t i = 0; i < cUnit.fpVmapTable.size(); i++) {
-        cUnit.coreVmapTable.push_back(cUnit.fpVmapTable[i]);
+    for (uint32_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
+        cUnit->coreVmapTable.push_back(cUnit->fpVmapTable[i]);
     }
-    DCHECK(cUnit.coreVmapTable.size() == (uint32_t)
-        (__builtin_popcount(cUnit.coreSpillMask) +
-         __builtin_popcount(cUnit.fpSpillMask)));
+    DCHECK(cUnit->coreVmapTable.size() == (uint32_t)
+        (__builtin_popcount(cUnit->coreSpillMask) + __builtin_popcount(cUnit->fpSpillMask)));
     vmapTable.push_back(-1);
-    for (size_t i = 0; i < cUnit.fpVmapTable.size(); i++) {
-        vmapTable.push_back(cUnit.fpVmapTable[i]);
+    for (size_t i = 0; i < cUnit->fpVmapTable.size(); i++) {
+        vmapTable.push_back(cUnit->fpVmapTable[i]);
     }
     CompiledMethod* result = new CompiledMethod(art::kThumb2,
-                                                cUnit.codeBuffer,
-                                                cUnit.frameSize,
-                                                cUnit.frameSize - sizeof(intptr_t),
-                                                cUnit.coreSpillMask,
-                                                cUnit.fpSpillMask,
-                                                cUnit.mappingTable,
-                                                cUnit.coreVmapTable);
+        cUnit->codeBuffer, cUnit->frameSize, cUnit->frameSize - sizeof(intptr_t),
+        cUnit->coreSpillMask, cUnit->fpSpillMask, cUnit->mappingTable, cUnit->coreVmapTable);
 
     if (compiler.IsVerbose()) {
         LOG(INFO) << "Compiled " << PrettyMethod(method)
-                  << " (" << (cUnit.codeBuffer.size() * sizeof(cUnit.codeBuffer[0])) << " bytes)";
+                  << " (" << (cUnit->codeBuffer.size() * sizeof(cUnit->codeBuffer[0])) << " bytes)";
     }
 
     return result;
diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc
index c4d3b6d..2a20efa 100644
--- a/src/compiler/codegen/arm/ArchUtility.cc
+++ b/src/compiler/codegen/arm/ArchUtility.cc
@@ -18,6 +18,8 @@
 #include "ArmLIR.h"
 #include "../Ralloc.h"
 
+#include <string>
+
 static const char* coreRegNames[16] = {
     "r0",
     "r1",
@@ -104,11 +106,10 @@
  * Interpret a format string and build a string no longer than size
  * See format key in Assemble.c.
  */
-STATIC void buildInsnString(const char* fmt, ArmLIR* lir, char* buf,
-                            unsigned char* baseAddr, int size)
+STATIC std::string buildInsnString(const char* fmt, ArmLIR* lir, unsigned char* baseAddr)
 {
+    std::string buf;
     int i;
-    char* bufEnd = &buf[size-1];
     const char* fmtEnd = &fmt[strlen(fmt)];
     char tbuf[256];
     const char* name;
@@ -233,21 +234,14 @@
                    default:
                        strcpy(tbuf,"DecodeError1");
                        break;
-               }
-               if (buf+strlen(tbuf) <= bufEnd) {
-                   strcpy(buf, tbuf);
-                   buf += strlen(tbuf);
-               } else {
-                   break;
-               }
+                }
+                buf += tbuf;
             }
         } else {
-           *buf++ = *fmt++;
+           buf += *fmt++;
         }
-        if (buf == bufEnd)
-            break;
     }
-    *buf = 0;
+    return buf;
 }
 
 void oatDumpResourceMask(LIR* lir, u8 mask, const char* prefix)
@@ -365,19 +359,11 @@
             if (lir->flags.isNop && !dumpNop) {
                 break;
             } else {
-                // TODO: rewrite using string
-                char opOperands[256];
-                char opName[256];
-                buildInsnString(EncodingMap[lir->opcode].name, lir, opName,
-                                baseAddr, 256);
-                buildInsnString(EncodingMap[lir->opcode].fmt, lir, opOperands,
-                                baseAddr, 256);
-                char tBuf[256];
-                snprintf(tBuf, 256, "%p (%04x): %-9s%s%s%s",
-                         baseAddr + offset, offset,
-                         opName, opOperands, lir->flags.isNop ? "(nop)" : "",
-                         lir->flags.squashed ? "(squashed)" : "");
-                LOG(INFO) << tBuf;
+                std::string op_name(buildInsnString(EncodingMap[lir->opcode].name, lir, baseAddr));
+                std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt, lir, baseAddr));
+                LOG(INFO) << StringPrintf("%p (%04x): %-9s%s%s%s", baseAddr + offset, offset,
+                    op_name.c_str(), op_operands.c_str(), lir->flags.isNop ? "(nop)" : "",
+                    lir->flags.squashed ? "(squashed)" : "");
             }
             break;
     }
@@ -453,20 +439,14 @@
     }
     for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
         armLIR = (ArmLIR*) lirInsn;
-        char buf[100];
-        snprintf(buf, 100, "%x (%04x): .class (%s)",
-             armLIR->generic.offset, armLIR->generic.offset,
-             ((CallsiteInfo *) armLIR->operands[0])->classDescriptor);
-        LOG(INFO) << buf;
+        LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
+            armLIR->generic.offset, armLIR->generic.offset,
+            ((CallsiteInfo *) armLIR->operands[0])->classDescriptor);
     }
     for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
         armLIR = (ArmLIR*) lirInsn;
-        char buf[100];
-        snprintf(buf, 100, "%x (%04x): .word (%#x)",
-             armLIR->generic.offset, armLIR->generic.offset,
-             armLIR->operands[0]);
-        LOG(INFO) << buf;
-
+        LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
+            armLIR->generic.offset, armLIR->generic.offset, armLIR->operands[0]);
     }
 
     std::string signature = method->GetSignature()->ToModifiedUtf8();
@@ -474,22 +454,16 @@
     std::string descriptor = method->GetDeclaringClass()->GetDescriptor()->
         ToModifiedUtf8();
 
-    char buf[256];
-
     // Dump mapping table
     if (cUnit->mappingTable.size() > 0) {
-        sprintf(buf,"\n    MappingTable %s%s_%s_mappingTable[%d] = {",
-                descriptor.c_str(), name.c_str(), signature.c_str(),
-                cUnit->mappingTable.size());
-        for (unsigned int i = 0; i < strlen(buf); i++)
-            if (buf[i] == ';') buf[i] = '_';
-        LOG(INFO) << buf;
-        strcpy(buf,"       ");
+        std::string line(StringPrintf("\n    MappingTable %s%s_%s_mappingTable[%d] = {",
+            descriptor.c_str(), name.c_str(), signature.c_str(), cUnit->mappingTable.size()));
+        std::replace(line.begin(), line.end(), ';', '_');
+        LOG(INFO) << line;
         for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
-            sprintf(buf+strlen(buf)," {0x%08x, 0x%04x},",
+            line = StringPrintf("        {0x%08x, 0x%04x},",
                 cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
-            LOG(INFO) << buf;
-            strcpy(buf,"       ");
+            LOG(INFO) << line;
         }
         LOG(INFO) <<"    };\n\n";
     }
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index d88960f..00be2be 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -2037,10 +2037,9 @@
 {
     /* Print compiled opcode in this VM instance */
     int i, start, streak;
-    char buf[1024];
+    std::string buf;
 
     streak = i = 0;
-    buf[0] = 0;
     while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) {
         i++;
     }
@@ -2052,9 +2051,9 @@
             streak++;
         } else {
             if (streak == 1) {
-                sprintf(buf+strlen(buf), "%x,", start);
+                StringAppendF(&buf, "%x,", start);
             } else {
-                sprintf(buf+strlen(buf), "%x-%x,", start, start + streak - 1);
+                StringAppendF(&buf, "%x-%x,", start, start + streak - 1);
             }
             streak = 0;
             while (opcodeCoverage[i] == 0 && i < kNumPackedOpcodes) {
@@ -2068,12 +2067,12 @@
     }
     if (streak) {
         if (streak == 1) {
-            sprintf(buf+strlen(buf), "%x", start);
+            StringAppendF(&buf, "%x", start);
         } else {
-            sprintf(buf+strlen(buf), "%x-%x", start, start + streak - 1);
+            StringAppendF(&buf, "%x-%x", start, start + streak - 1);
         }
     }
-    if (strlen(buf)) {
+    if (!buf.empty()) {
         LOG(INFO) << "dalvik.vm.oat.op = " << buf;
     }
 }