diff options
| -rw-r--r-- | compiler/optimizing/induction_var_analysis.cc | 3 | ||||
| -rw-r--r-- | compiler/optimizing/induction_var_analysis_test.cc | 41 | ||||
| -rw-r--r-- | compiler/utils/test_dex_file_builder.h | 2 | ||||
| -rw-r--r-- | runtime/dex_file.cc | 14 | ||||
| -rw-r--r-- | runtime/dex_file.h | 7 | ||||
| -rwxr-xr-x | test/370-dex-v37/build | 30 | ||||
| -rw-r--r-- | test/370-dex-v37/expected.txt | 1 | ||||
| -rw-r--r-- | test/370-dex-v37/info.txt | 1 | ||||
| -rw-r--r-- | test/370-dex-v37/src/Main.java | 21 |
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!"); + } +} |