summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCalin Juravle <calin@google.com>2015-05-08 15:52:48 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2015-05-08 15:52:49 +0000
commit6727a48193db2a0cf01af971cccffe1a6518c247 (patch)
treef86189e3d30e38377666f309693fc58d90eb7d6a
parentadd1d9ba61b6ddd52f2161587baf3ae4bc8717af (diff)
parent702d26018769f9fbc4763c7ed02331aed596ac7d (diff)
downloadart-6727a48193db2a0cf01af971cccffe1a6518c247.zip
art-6727a48193db2a0cf01af971cccffe1a6518c247.tar.gz
art-6727a48193db2a0cf01af971cccffe1a6518c247.tar.bz2
Merge "Skip compilation when falling-through out of method code."
-rw-r--r--compiler/optimizing/builder.cc24
-rw-r--r--compiler/optimizing/builder.h5
-rw-r--r--compiler/optimizing/optimizing_compiler_stats.h44
-rw-r--r--test/Android.run-test.mk1
4 files changed, 47 insertions, 27 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 0f44af0..a5c6f23 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -282,7 +282,10 @@ bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
// To avoid splitting blocks, we compute ahead of time the instructions that
// start a new block, and create these blocks.
- ComputeBranchTargets(code_ptr, code_end, &number_of_branches);
+ if (!ComputeBranchTargets(code_ptr, code_end, &number_of_branches)) {
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledBranchOutsideMethodCode);
+ return false;
+ }
// Note that the compiler driver is null when unit testing.
if ((compiler_driver_ != nullptr) && SkipCompilation(code_item, number_of_branches)) {
@@ -349,7 +352,7 @@ void HGraphBuilder::MaybeUpdateCurrentBlock(size_t index) {
current_block_ = block;
}
-void HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr,
+bool HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr,
const uint16_t* code_end,
size_t* number_of_branches) {
branch_targets_.SetSize(code_end - code_ptr);
@@ -374,7 +377,14 @@ void HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr,
}
dex_pc += instruction.SizeInCodeUnits();
code_ptr += instruction.SizeInCodeUnits();
- if ((code_ptr < code_end) && (FindBlockStartingAt(dex_pc) == nullptr)) {
+
+ if (code_ptr >= code_end) {
+ if (instruction.CanFlowThrough()) {
+ // In the normal case we should never hit this but someone can artificially forge a dex
+ // file to fall-through out the method code. In this case we bail out compilation.
+ return false;
+ }
+ } else if (FindBlockStartingAt(dex_pc) == nullptr) {
block = new (arena_) HBasicBlock(graph_, dex_pc);
branch_targets_.Put(dex_pc, block);
}
@@ -406,7 +416,12 @@ void HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr,
// Fall-through. Add a block if there is more code afterwards.
dex_pc += instruction.SizeInCodeUnits();
code_ptr += instruction.SizeInCodeUnits();
- if ((code_ptr < code_end) && (FindBlockStartingAt(dex_pc) == nullptr)) {
+ if (code_ptr >= code_end) {
+ // In the normal case we should never hit this but someone can artificially forge a dex
+ // file to fall-through out the method code. In this case we bail out compilation.
+ // (A switch can fall-through so we don't need to check CanFlowThrough().)
+ return false;
+ } else if (FindBlockStartingAt(dex_pc) == nullptr) {
block = new (arena_) HBasicBlock(graph_, dex_pc);
branch_targets_.Put(dex_pc, block);
}
@@ -415,6 +430,7 @@ void HGraphBuilder::ComputeBranchTargets(const uint16_t* code_ptr,
dex_pc += instruction.SizeInCodeUnits();
}
}
+ return true;
}
HBasicBlock* HGraphBuilder::FindBlockStartingAt(int32_t index) const {
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index dc6d97e..36503ce 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -88,7 +88,10 @@ class HGraphBuilder : public ValueObject {
// the newly created blocks.
// As a side effect, also compute the number of dex instructions, blocks, and
// branches.
- void ComputeBranchTargets(const uint16_t* start,
+ // Returns true if all the branches fall inside the method code, false otherwise.
+ // (In normal cases this should always return true but someone can artificially
+ // create a code unit in which branches fall-through out of it).
+ bool ComputeBranchTargets(const uint16_t* start,
const uint16_t* end,
size_t* number_of_branches);
void MaybeUpdateCurrentBlock(size_t index);
diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h
index 65c84e6..b6b1bb1 100644
--- a/compiler/optimizing/optimizing_compiler_stats.h
+++ b/compiler/optimizing/optimizing_compiler_stats.h
@@ -29,25 +29,26 @@ enum MethodCompilationStat {
kCompiledBaseline,
kCompiledOptimized,
kCompiledQuick,
- kInstructionSimplifications,
kInlinedInvoke,
- kNotCompiledUnsupportedIsa,
- kNotCompiledPathological,
+ kInstructionSimplifications,
+ kNotCompiledBranchOutsideMethodCode,
+ kNotCompiledCannotBuildSSA,
+ kNotCompiledCantAccesType,
+ kNotCompiledClassNotVerified,
kNotCompiledHugeMethod,
kNotCompiledLargeMethodNoBranches,
- kNotCompiledCannotBuildSSA,
kNotCompiledNoCodegen,
- kNotCompiledUnresolvedMethod,
- kNotCompiledUnresolvedField,
kNotCompiledNonSequentialRegPair,
+ kNotCompiledPathological,
kNotCompiledSpaceFilter,
- kNotOptimizedTryCatch,
- kNotOptimizedDisabled,
- kNotCompiledCantAccesType,
- kNotOptimizedRegisterAllocator,
kNotCompiledUnhandledInstruction,
+ kNotCompiledUnresolvedField,
+ kNotCompiledUnresolvedMethod,
+ kNotCompiledUnsupportedIsa,
kNotCompiledVerifyAtRuntime,
- kNotCompiledClassNotVerified,
+ kNotOptimizedDisabled,
+ kNotOptimizedRegisterAllocator,
+ kNotOptimizedTryCatch,
kRemovedCheckedCast,
kRemovedDeadInstruction,
kRemovedNullCheck,
@@ -98,23 +99,24 @@ class OptimizingCompilerStats {
case kCompiledQuick : return "kCompiledQuick";
case kInlinedInvoke : return "kInlinedInvoke";
case kInstructionSimplifications: return "kInstructionSimplifications";
- case kNotCompiledUnsupportedIsa : return "kNotCompiledUnsupportedIsa";
- case kNotCompiledPathological : return "kNotCompiledPathological";
+ case kNotCompiledBranchOutsideMethodCode: return "kNotCompiledBranchOutsideMethodCode";
+ case kNotCompiledCannotBuildSSA : return "kNotCompiledCannotBuildSSA";
+ case kNotCompiledCantAccesType : return "kNotCompiledCantAccesType";
+ case kNotCompiledClassNotVerified : return "kNotCompiledClassNotVerified";
case kNotCompiledHugeMethod : return "kNotCompiledHugeMethod";
case kNotCompiledLargeMethodNoBranches : return "kNotCompiledLargeMethodNoBranches";
- case kNotCompiledCannotBuildSSA : return "kNotCompiledCannotBuildSSA";
case kNotCompiledNoCodegen : return "kNotCompiledNoCodegen";
- case kNotCompiledUnresolvedMethod : return "kNotCompiledUnresolvedMethod";
- case kNotCompiledUnresolvedField : return "kNotCompiledUnresolvedField";
case kNotCompiledNonSequentialRegPair : return "kNotCompiledNonSequentialRegPair";
- case kNotOptimizedDisabled : return "kNotOptimizedDisabled";
- case kNotOptimizedTryCatch : return "kNotOptimizedTryCatch";
- case kNotCompiledCantAccesType : return "kNotCompiledCantAccesType";
+ case kNotCompiledPathological : return "kNotCompiledPathological";
case kNotCompiledSpaceFilter : return "kNotCompiledSpaceFilter";
- case kNotOptimizedRegisterAllocator : return "kNotOptimizedRegisterAllocator";
case kNotCompiledUnhandledInstruction : return "kNotCompiledUnhandledInstruction";
+ case kNotCompiledUnresolvedField : return "kNotCompiledUnresolvedField";
+ case kNotCompiledUnresolvedMethod : return "kNotCompiledUnresolvedMethod";
+ case kNotCompiledUnsupportedIsa : return "kNotCompiledUnsupportedIsa";
case kNotCompiledVerifyAtRuntime : return "kNotCompiledVerifyAtRuntime";
- case kNotCompiledClassNotVerified : return "kNotCompiledClassNotVerified";
+ case kNotOptimizedDisabled : return "kNotOptimizedDisabled";
+ case kNotOptimizedRegisterAllocator : return "kNotOptimizedRegisterAllocator";
+ case kNotOptimizedTryCatch : return "kNotOptimizedTryCatch";
case kRemovedCheckedCast: return "kRemovedCheckedCast";
case kRemovedDeadInstruction: return "kRemovedDeadInstruction";
case kRemovedNullCheck: return "kRemovedNullCheck";
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 515b8af..40f5f00 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -385,7 +385,6 @@ TEST_ART_BROKEN_OPTIMIZING_ARM64_RUN_TESTS :=
# Known broken tests for the optimizing compiler.
TEST_ART_BROKEN_OPTIMIZING_RUN_TESTS :=
-TEST_ART_BROKEN_OPTIMIZING_RUN_TESTS += 472-unreachable-if-regression # b/19988134
ifneq (,$(filter optimizing,$(COMPILER_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \