summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/induction_var_analysis.cc3
-rw-r--r--compiler/optimizing/induction_var_analysis_test.cc41
-rw-r--r--compiler/utils/test_dex_file_builder.h2
-rw-r--r--runtime/dex_file.cc14
-rw-r--r--runtime/dex_file.h7
-rwxr-xr-xtest/370-dex-v37/build30
-rw-r--r--test/370-dex-v37/expected.txt1
-rw-r--r--test/370-dex-v37/info.txt1
-rw-r--r--test/370-dex-v37/src/Main.java21
9 files changed, 114 insertions, 6 deletions
diff --git a/compiler/optimizing/induction_var_analysis.cc b/compiler/optimizing/induction_var_analysis.cc
index 266cb10ab3..c06d19dce0 100644
--- a/compiler/optimizing/induction_var_analysis.cc
+++ b/compiler/optimizing/induction_var_analysis.cc
@@ -141,7 +141,7 @@ void HInductionVarAnalysis::VisitLoop(HLoopInformation* loop) {
DCHECK(stack_.empty());
map_.clear();
- // Determine the loop's trip count.
+ // Determine the loop's trip-count.
VisitControl(loop);
}
@@ -917,6 +917,7 @@ bool HInductionVarAnalysis::InductionEqual(InductionInfo* info1,
info1->induction_class == info2->induction_class &&
info1->operation == info2->operation &&
info1->fetch == info2->fetch &&
+ info1->type == info2->type &&
InductionEqual(info1->op_a, info2->op_a) &&
InductionEqual(info1->op_b, info2->op_b);
}
diff --git a/compiler/optimizing/induction_var_analysis_test.cc b/compiler/optimizing/induction_var_analysis_test.cc
index 0fbb67d0d9..580d24b74b 100644
--- a/compiler/optimizing/induction_var_analysis_test.cc
+++ b/compiler/optimizing/induction_var_analysis_test.cc
@@ -157,6 +157,13 @@ class InductionVarAnalysisTest : public CommonCompilerTest {
iva_->LookupInfo(loop_body_[d]->GetLoopInformation(), instruction));
}
+ // Returns true if instructions have identical induction.
+ bool HaveSameInduction(HInstruction* instruction1, HInstruction* instruction2) {
+ return HInductionVarAnalysis::InductionEqual(
+ iva_->LookupInfo(loop_body_[0]->GetLoopInformation(), instruction1),
+ iva_->LookupInfo(loop_body_[0]->GetLoopInformation(), instruction2));
+ }
+
// Performs InductionVarAnalysis (after proper set up).
void PerformInductionVarAnalysis() {
graph_->BuildDominatorTree();
@@ -228,6 +235,9 @@ TEST_F(InductionVarAnalysisTest, FindBasicInduction) {
EXPECT_STREQ("((1) * i + (0)):PrimInt", GetInductionInfo(store->InputAt(1), 0).c_str());
EXPECT_STREQ("((1) * i + (1)):PrimInt", GetInductionInfo(increment_[0], 0).c_str());
+ // Offset matters!
+ EXPECT_FALSE(HaveSameInduction(store->InputAt(1), increment_[0]));
+
// Trip-count.
EXPECT_STREQ("((100) (TC-loop) ((0) < (100)))",
GetInductionInfo(loop_header_[0]->GetLastInstruction(), 0).c_str());
@@ -320,6 +330,10 @@ TEST_F(InductionVarAnalysisTest, FindTwoWayBasicInduction) {
PerformInductionVarAnalysis();
EXPECT_STREQ("((1) * i + (1)):PrimInt", GetInductionInfo(store->InputAt(1), 0).c_str());
+
+ // Both increments get same induction.
+ EXPECT_TRUE(HaveSameInduction(store->InputAt(1), inc1));
+ EXPECT_TRUE(HaveSameInduction(store->InputAt(1), inc2));
}
TEST_F(InductionVarAnalysisTest, FindTwoWayDerivedInduction) {
@@ -570,6 +584,33 @@ TEST_F(InductionVarAnalysisTest, FindDeepLoopInduction) {
}
}
+TEST_F(InductionVarAnalysisTest, ByteInductionIntLoopControl) {
+ // Setup:
+ // for (int i = 0; i < 100; i++) {
+ // k = (byte) i;
+ // a[k] = 0;
+ // a[i] = 0;
+ // }
+ BuildLoopNest(1);
+ HInstruction *conv = InsertInstruction(
+ new (&allocator_) HTypeConversion(Primitive::kPrimByte, basic_[0], -1), 0);
+ HInstruction* store1 = InsertArrayStore(conv, 0);
+ HInstruction* store2 = InsertArrayStore(basic_[0], 0);
+ PerformInductionVarAnalysis();
+
+ // Regular int induction (i) is "transferred" over conversion into byte induction (k).
+ EXPECT_STREQ("((1) * i + (0)):PrimByte", GetInductionInfo(store1->InputAt(1), 0).c_str());
+ EXPECT_STREQ("((1) * i + (0)):PrimInt", GetInductionInfo(store2->InputAt(1), 0).c_str());
+ EXPECT_STREQ("((1) * i + (1)):PrimInt", GetInductionInfo(increment_[0], 0).c_str());
+
+ // Type matters!
+ EXPECT_FALSE(HaveSameInduction(store1->InputAt(1), store2->InputAt(1)));
+
+ // Trip-count.
+ EXPECT_STREQ("((100) (TC-loop) ((0) < (100)))",
+ GetInductionInfo(loop_header_[0]->GetLastInstruction(), 0).c_str());
+}
+
TEST_F(InductionVarAnalysisTest, ByteLoopControl1) {
// Setup:
// for (byte i = -128; i < 127; i++) { // just fits!
diff --git a/compiler/utils/test_dex_file_builder.h b/compiler/utils/test_dex_file_builder.h
index 2958dc6e2a..fb37804649 100644
--- a/compiler/utils/test_dex_file_builder.h
+++ b/compiler/utils/test_dex_file_builder.h
@@ -88,7 +88,7 @@ class TestDexFileBuilder {
std::memset(header_data.data, 0, sizeof(header_data.data));
DexFile::Header* header = reinterpret_cast<DexFile::Header*>(&header_data.data);
std::copy_n(DexFile::kDexMagic, 4u, header->magic_);
- std::copy_n(DexFile::kDexMagicVersion, 4u, header->magic_ + 4u);
+ std::copy_n(DexFile::kDexMagicVersions[0], 4u, header->magic_ + 4u);
header->header_size_ = sizeof(DexFile::Header);
header->endian_tag_ = DexFile::kDexEndianConstant;
header->link_size_ = 0u; // Unused.
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 4a0a6fc8ad..60caa73b72 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -62,7 +62,12 @@
namespace art {
const uint8_t DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
-const uint8_t DexFile::kDexMagicVersion[] = { '0', '3', '5', '\0' };
+const uint8_t DexFile::kDexMagicVersions[DexFile::kNumDexVersions][DexFile::kDexVersionLen] = {
+ {'0', '3', '5', '\0'},
+ // Dex version 036 skipped because of an old dalvik bug on some versions of android where dex
+ // files with that version number would erroneously be accepted and run.
+ {'0', '3', '7', '\0'}
+};
bool DexFile::GetChecksum(const char* filename, uint32_t* checksum, std::string* error_msg) {
CHECK(checksum != nullptr);
@@ -493,7 +498,12 @@ bool DexFile::IsMagicValid(const uint8_t* magic) {
bool DexFile::IsVersionValid(const uint8_t* magic) {
const uint8_t* version = &magic[sizeof(kDexMagic)];
- return (memcmp(version, kDexMagicVersion, sizeof(kDexMagicVersion)) == 0);
+ for (uint32_t i = 0; i < kNumDexVersions; i++) {
+ if (memcmp(version, kDexMagicVersions[i], kDexVersionLen) == 0) {
+ return true;
+ }
+ }
+ return false;
}
uint32_t DexFile::GetVersion() const {
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index e497e9c6db..68499846cd 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -58,7 +58,10 @@ class ZipArchive;
class DexFile {
public:
static const uint8_t kDexMagic[];
- static const uint8_t kDexMagicVersion[];
+ static constexpr size_t kNumDexVersions = 2;
+ static constexpr size_t kDexVersionLen = 4;
+ static const uint8_t kDexMagicVersions[kNumDexVersions][kDexVersionLen];
+
static constexpr size_t kSha1DigestSize = 20;
static constexpr uint32_t kDexEndianConstant = 0x12345678;
@@ -71,7 +74,7 @@ class DexFile {
// The value of an invalid index.
static const uint16_t kDexNoIndex16 = 0xFFFF;
- // The separator charactor in MultiDex locations.
+ // The separator character in MultiDex locations.
static constexpr char kMultiDexSeparator = ':';
// A string version of the previous. This is a define so that we can merge string literals in the
diff --git a/test/370-dex-v37/build b/test/370-dex-v37/build
new file mode 100755
index 0000000000..f472428e27
--- /dev/null
+++ b/test/370-dex-v37/build
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Copyright 2015 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# make us exit on a failure
+set -e
+
+./default-build "$@"
+
+if [[ $@ != *"--jvm"* ]]; then
+ # Change the generated dex file to have a v36 magic number if it is version 35
+ if test -f classes.dex && head -c 7 classes.dex | grep -q 035; then
+ # place ascii value '037' into the classes.dex file starting at byte 4.
+ printf '037' | dd status=none conv=notrunc of=classes.dex bs=1 seek=4 count=3
+ rm -f $TEST_NAME.jar
+ zip $TEST_NAME.jar classes.dex
+ fi
+fi
diff --git a/test/370-dex-v37/expected.txt b/test/370-dex-v37/expected.txt
new file mode 100644
index 0000000000..af5626b4a1
--- /dev/null
+++ b/test/370-dex-v37/expected.txt
@@ -0,0 +1 @@
+Hello, world!
diff --git a/test/370-dex-v37/info.txt b/test/370-dex-v37/info.txt
new file mode 100644
index 0000000000..5ca9c7663f
--- /dev/null
+++ b/test/370-dex-v37/info.txt
@@ -0,0 +1 @@
+Print "Hello, World!" with a version 37 dex file.
diff --git a/test/370-dex-v37/src/Main.java b/test/370-dex-v37/src/Main.java
new file mode 100644
index 0000000000..1ef6289559
--- /dev/null
+++ b/test/370-dex-v37/src/Main.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+ public static void main(String[] args) {
+ System.out.println("Hello, world!");
+ }
+}