Merge "Fix the handful of leaks detectable in our tests." into dalvik-dev
diff --git a/src/compiled_method.cc b/src/compiled_method.cc
index 40230b4..ca7858a 100644
--- a/src/compiled_method.cc
+++ b/src/compiled_method.cc
@@ -50,22 +50,7 @@
CHECK_NE(mapping_table_.size(), 0U);
CHECK_NE(vmap_table_.size(), 0U);
- std::vector<uint8_t> length_prefixed_gc_map;
- length_prefixed_gc_map.push_back((gc_map.size() & 0xff000000) >> 24);
- length_prefixed_gc_map.push_back((gc_map.size() & 0x00ff0000) >> 16);
- length_prefixed_gc_map.push_back((gc_map.size() & 0x0000ff00) >> 8);
- length_prefixed_gc_map.push_back((gc_map.size() & 0x000000ff) >> 0);
- length_prefixed_gc_map.insert(length_prefixed_gc_map.end(),
- gc_map.begin(),
- gc_map.end());
- DCHECK_EQ(gc_map.size() + 4, length_prefixed_gc_map.size());
- DCHECK_EQ(gc_map.size(),
- static_cast<size_t>((length_prefixed_gc_map[0] << 24) |
- (length_prefixed_gc_map[1] << 16) |
- (length_prefixed_gc_map[2] << 8) |
- (length_prefixed_gc_map[3] << 0)));
-
- gc_map_ = length_prefixed_gc_map;
+ gc_map_ = gc_map;
}
CompiledMethod::CompiledMethod(InstructionSet instruction_set,
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 2eba586..5be51f4 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -115,7 +115,8 @@
/* Split an existing block from the specified code offset into two */
STATIC BasicBlock *splitBlock(CompilationUnit* cUnit,
unsigned int codeOffset,
- BasicBlock* origBlock)
+ BasicBlock* origBlock,
+ BasicBlock** immedPredBlockP)
{
MIR* insn = origBlock->firstMIRInsn;
while (insn) {
@@ -176,16 +177,28 @@
insn->prev->next = NULL;
insn->prev = NULL;
+ /*
+ * Update the immediate predecessor block pointer so that outgoing edges
+ * can be applied to the proper block.
+ */
+ if (immedPredBlockP) {
+ DCHECK_EQ(*immedPredBlockP, origBlock);
+ *immedPredBlockP = bottomBlock;
+ }
return bottomBlock;
}
/*
* Given a code offset, find out the block that starts with it. If the offset
- * is in the middle of an existing block, split it into two.
+ * is in the middle of an existing block, split it into two. If immedPredBlockP
+ * is not non-null and is the block being split, update *immedPredBlockP to
+ * point to the bottom block so that outgoing edges can be set up properly
+ * (by the caller)
*/
STATIC BasicBlock *findBlock(CompilationUnit* cUnit,
unsigned int codeOffset,
- bool split, bool create)
+ bool split, bool create,
+ BasicBlock** immedPredBlockP)
{
GrowableList* blockList = &cUnit->blockList;
BasicBlock* bb;
@@ -199,7 +212,9 @@
if ((split == true) && (codeOffset > bb->startOffset) &&
(bb->lastMIRInsn != NULL) &&
(codeOffset <= bb->lastMIRInsn->offset)) {
- BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb);
+ BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb,
+ bb == *immedPredBlockP ?
+ immedPredBlockP : NULL);
return newBB;
}
}
@@ -445,7 +460,8 @@
art::CatchHandlerIterator iterator(handlers_ptr);
for (; iterator.HasNext(); iterator.Next()) {
uint32_t address = iterator.GetHandlerAddress();
- findBlock(cUnit, address, false /* split */, true /*create*/);
+ findBlock(cUnit, address, false /* split */, true /*create*/,
+ /* immedPredBlockP */ NULL);
}
handlers_ptr = iterator.EndDataPointer();
}
@@ -484,22 +500,13 @@
LOG(FATAL) << "Unexpected opcode(" << (int)insn->dalvikInsn.opcode
<< ") with kInstrCanBranch set";
}
- /*
- * Some ugliness here. It is possible that findBlock will
- * split the current block. In that case, we need to operate
- * on the 2nd half on the split pair. It isn't directly obvious
- * when this happens, so we infer.
- */
- DCHECK(curBlock->lastMIRInsn == insn);
BasicBlock *takenBlock = findBlock(cUnit, target,
/* split */
true,
/* create */
- true);
- if (curBlock->lastMIRInsn != insn) {
- DCHECK(takenBlock->lastMIRInsn == insn);
- curBlock = curBlock->fallThrough;
- }
+ true,
+ /* immedPredBlockP */
+ &curBlock);
curBlock->taken = takenBlock;
oatSetBit(takenBlock->predecessors, curBlock->id);
@@ -521,7 +528,9 @@
*/
true,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ &curBlock);
curBlock->fallThrough = fallthroughBlock;
oatSetBit(fallthroughBlock->predecessors, curBlock->id);
} else if (codePtr < codeEnd) {
@@ -531,7 +540,9 @@
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
}
}
return curBlock;
@@ -595,7 +606,9 @@
/* split */
true,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ &curBlock);
SuccessorBlockInfo *successorBlockInfo =
(SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
false);
@@ -613,7 +626,9 @@
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
curBlock->fallThrough = fallthroughBlock;
oatSetBit(fallthroughBlock->predecessors, curBlock->id);
}
@@ -641,7 +656,8 @@
for (;iterator.HasNext(); iterator.Next()) {
BasicBlock *catchBlock = findBlock(cUnit, iterator.GetHandlerAddress(),
false /* split*/,
- false /* creat */);
+ false /* creat */,
+ NULL /* immedPredBlockP */);
catchBlock->catchEntry = true;
SuccessorBlockInfo *successorBlockInfo =
(SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
@@ -675,7 +691,9 @@
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
/*
* OP_THROW is an unconditional branch. NOTE:
* OP_THROW_VERIFICATION_ERROR is also an unconditional
@@ -822,7 +840,9 @@
/* split */
false,
/* create */
- true);
+ true,
+ /* immedPredBlockP */
+ NULL);
}
}
} else if (flags & kInstrCanThrow) {
@@ -836,7 +856,9 @@
/* split */
false,
/* create */
- false);
+ false,
+ /* immedPredBlockP */
+ NULL);
if (nextBlock) {
/*
* The next instruction could be the target of a previously parsed
diff --git a/src/dalvik_system_VMRuntime.cc b/src/dalvik_system_VMRuntime.cc
index 3a1eac0..5dcbb41 100644
--- a/src/dalvik_system_VMRuntime.cc
+++ b/src/dalvik_system_VMRuntime.cc
@@ -117,7 +117,8 @@
if (targetSdkVersion > 0 && targetSdkVersion <= 13 /* honeycomb-mr2 */) {
// TODO: running with CheckJNI should override this and force you to obey the strictest rules.
LOG(INFO) << "Turning on JNI app bug workarounds for target SDK version " << targetSdkVersion << "...";
- Runtime::Current()->GetJavaVM()->work_around_app_jni_bugs = true;
+ // Runtime::Current()->GetJavaVM()->work_around_app_jni_bugs = true;
+ UNIMPLEMENTED(WARNING) << "Support work arounds for app JNI bugs";
}
}
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index c219042..deffdc2 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -24,7 +24,22 @@
static const bool gDebugVerify = false;
std::ostream& operator<<(std::ostream& os, const VerifyError& rhs) {
- return os << (int)rhs;
+ switch (rhs) {
+ case VERIFY_ERROR_NONE: os << "VERIFY_ERROR_NONE"; break;
+ case VERIFY_ERROR_GENERIC: os << "VERIFY_ERROR_GENERIC"; break;
+ case VERIFY_ERROR_NO_CLASS: os << "VERIFY_ERROR_NO_CLASS"; break;
+ case VERIFY_ERROR_NO_FIELD: os << "VERIFY_ERROR_NO_FIELD"; break;
+ case VERIFY_ERROR_NO_METHOD: os << "VERIFY_ERROR_NO_METHOD"; break;
+ case VERIFY_ERROR_ACCESS_CLASS: os << "VERIFY_ERROR_ACCESS_CLASS"; break;
+ case VERIFY_ERROR_ACCESS_FIELD: os << "VERIFY_ERROR_ACCESS_FIELD"; break;
+ case VERIFY_ERROR_ACCESS_METHOD: os << "VERIFY_ERROR_ACCESS_METHOD"; break;
+ case VERIFY_ERROR_CLASS_CHANGE: os << "VERIFY_ERROR_CLASS_CHANGE"; break;
+ case VERIFY_ERROR_INSTANTIATION: os << "VERIFY_ERROR_INSTANTIATION"; break;
+ default:
+ os << "VerifyError[" << static_cast<int>(rhs) << "]";
+ break;
+ }
+ return os;
}
static const char* type_strings[] = {
@@ -941,6 +956,8 @@
bool DexVerifier::VerifyMethod(Method* method) {
DexVerifier verifier(method);
bool success = verifier.Verify();
+ CHECK_EQ(success, verifier.failure_ == VERIFY_ERROR_NONE);
+
// We expect either success and no verification error, or failure and a generic failure to
// reject the class.
if (success) {
@@ -1496,6 +1513,24 @@
return true;
}
+const std::vector<uint8_t>* CreateLengthPrefixedGcMap(const std::vector<uint8_t>& gc_map) {
+ std::vector<uint8_t>* length_prefixed_gc_map = new std::vector<uint8_t>;
+ length_prefixed_gc_map->push_back((gc_map.size() & 0xff000000) >> 24);
+ length_prefixed_gc_map->push_back((gc_map.size() & 0x00ff0000) >> 16);
+ length_prefixed_gc_map->push_back((gc_map.size() & 0x0000ff00) >> 8);
+ length_prefixed_gc_map->push_back((gc_map.size() & 0x000000ff) >> 0);
+ length_prefixed_gc_map->insert(length_prefixed_gc_map->end(),
+ gc_map.begin(),
+ gc_map.end());
+ DCHECK_EQ(gc_map.size() + 4, length_prefixed_gc_map->size());
+ DCHECK_EQ(gc_map.size(),
+ static_cast<size_t>((length_prefixed_gc_map->at(0) << 24) |
+ (length_prefixed_gc_map->at(1) << 16) |
+ (length_prefixed_gc_map->at(2) << 8) |
+ (length_prefixed_gc_map->at(3) << 0)));
+ return length_prefixed_gc_map;
+}
+
bool DexVerifier::VerifyCodeFlow() {
uint16_t registers_size = code_item_->registers_size_;
uint32_t insns_size = code_item_->insns_size_in_code_units_;
@@ -1519,19 +1554,23 @@
}
/* Perform code flow verification. */
if (!CodeFlowVerifyMethod()) {
+ DCHECK_NE(failure_, VERIFY_ERROR_NONE);
return false;
}
/* Generate a register map and add it to the method. */
- const std::vector<uint8_t>* map = GenerateGcMap();
- if (map == NULL) {
+ UniquePtr<const std::vector<uint8_t> > map(GenerateGcMap());
+ if (map.get() == NULL) {
+ DCHECK_NE(failure_, VERIFY_ERROR_NONE);
return false; // Not a real failure, but a failure to encode
}
- Compiler::MethodReference ref(dex_file_, method_->GetDexMethodIndex());
- verifier::DexVerifier::SetGcMap(ref, *map);
#ifndef NDEBUG
VerifyGcMap(*map);
#endif
+ const std::vector<uint8_t>* gc_map = CreateLengthPrefixedGcMap(*(map.get()));
+ Compiler::MethodReference ref(dex_file_, method_->GetDexMethodIndex());
+ verifier::DexVerifier::SetGcMap(ref, *gc_map);
+ method_->SetGcMap(&gc_map->at(0));
return true;
}
diff --git a/test/083-jit-regressions/expected.txt b/test/083-jit-regressions/expected.txt
index 1f30d21..4b9ad5b 100644
--- a/test/083-jit-regressions/expected.txt
+++ b/test/083-jit-regressions/expected.txt
@@ -1,3 +1,4 @@
b2296099 passes
b2302318 passes
b2487514 passes
+b5884080 passes
diff --git a/test/083-jit-regressions/info.txt b/test/083-jit-regressions/info.txt
index b791aba..00c24ee 100644
--- a/test/083-jit-regressions/info.txt
+++ b/test/083-jit-regressions/info.txt
@@ -8,3 +8,4 @@
2296099 JIT shift bug
2302318 Crash during spin-on-suspend testing
2487514 Missed exception in PriorityBlockingQueueTest.testToArray1_BadArg
+5884080 ICS JIT regression in nested loop formation
diff --git a/test/083-jit-regressions/src/Main.java b/test/083-jit-regressions/src/Main.java
index 1f1dee3..3b596db 100644
--- a/test/083-jit-regressions/src/Main.java
+++ b/test/083-jit-regressions/src/Main.java
@@ -24,6 +24,7 @@
b2296099Test();
b2302318Test();
b2487514Test();
+ b5884080Test();
}
static void b2296099Test() throws Exception {
@@ -105,6 +106,26 @@
" (expecting 1000)");
}
}
+
+ static void b5884080Test() {
+ int vA = 1;
+
+ int l = 0;
+ do
+ {
+ int k = 0;
+ do
+ vA += 1;
+ while(++k < 100);
+ } while(++l < 1000);
+ if (vA == 100001) {
+ System.out.println("b5884080 passes");
+ }
+ else {
+ System.out.println("b5884080 fails: vA is " + vA +
+ " (expecting 100001)");
+ }
+ }
}
class SpinThread extends Thread {