summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/graph_visualizer.cc3
-rw-r--r--compiler/optimizing/inliner.cc44
-rw-r--r--compiler/optimizing/load_store_elimination.cc9
-rw-r--r--dexlayout/dexlayout_test.cc1
-rw-r--r--runtime/common_runtime_test.cc68
-rw-r--r--runtime/common_runtime_test.h2
-rw-r--r--runtime/dex/base64_test_util.h99
-rw-r--r--runtime/dex/code_item_accessors_test.cc46
-rw-r--r--runtime/dex/compact_dex_debug_info_test.cc17
-rw-r--r--runtime/dex/dex_file_test.cc1
-rw-r--r--runtime/dex/dex_file_verifier_test.cc52
-rw-r--r--runtime/dex/utf_test.cc8
-rw-r--r--runtime/runtime.cc7
-rw-r--r--test/530-checker-lse/expected.txt1
-rw-r--r--test/530-checker-lse/src/Main.java23
-rw-r--r--test/675-checker-unverified-method/expected.txt1
-rw-r--r--test/675-checker-unverified-method/info.txt1
-rw-r--r--test/675-checker-unverified-method/smali/TestCase.smali55
-rw-r--r--test/675-checker-unverified-method/src/Main.java28
-rw-r--r--test/956-methodhandles/src/Main.java18
-rw-r--r--tools/external_oj_libjdwp_art_failures.txt13
-rw-r--r--tools/prebuilt_libjdwp_art_failures.txt13
22 files changed, 349 insertions, 161 deletions
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 6144162f68..bbf8c26d59 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -445,6 +445,9 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
? GetGraph()->GetDexFile().PrettyMethod(invoke->GetDexMethodIndex(), kWithSignature)
: method->PrettyMethod(kWithSignature);
StartAttributeStream("method_name") << method_name;
+ StartAttributeStream("always_throws") << std::boolalpha
+ << invoke->AlwaysThrows()
+ << std::noboolalpha;
}
void VisitInvokeUnresolved(HInvokeUnresolved* invoke) OVERRIDE {
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 035e5ce3e1..b9ae0ffb12 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -392,10 +392,33 @@ ArtMethod* HInliner::TryCHADevirtualization(ArtMethod* resolved_method) {
return single_impl;
}
-static bool AlwaysThrows(ArtMethod* method)
+static bool IsMethodUnverified(CompilerDriver* const compiler_driver, ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_) {
- CodeItemDataAccessor accessor(method->DexInstructionData());
+ if (!method->GetDeclaringClass()->IsVerified()) {
+ if (Runtime::Current()->UseJitCompilation()) {
+ // We're at runtime, we know this is cold code if the class
+ // is not verified, so don't bother analyzing.
+ return true;
+ }
+ uint16_t class_def_idx = method->GetDeclaringClass()->GetDexClassDefIndex();
+ if (!compiler_driver->IsMethodVerifiedWithoutFailures(
+ method->GetDexMethodIndex(), class_def_idx, *method->GetDexFile())) {
+ // Method has soft or hard failures, don't analyze.
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool AlwaysThrows(CompilerDriver* const compiler_driver, ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK(method != nullptr);
+ // Skip non-compilable and unverified methods.
+ if (!method->IsCompilable() || IsMethodUnverified(compiler_driver, method)) {
+ return false;
+ }
// Skip native methods, methods with try blocks, and methods that are too large.
+ CodeItemDataAccessor accessor(method->DexInstructionData());
if (!accessor.HasCodeItem() ||
accessor.TriesSize() != 0 ||
accessor.InsnsSizeInCodeUnits() > kMaximumNumberOfTotalInstructions) {
@@ -478,7 +501,7 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) {
MaybeRecordStat(stats_, MethodCompilationStat::kInlinedInvokeVirtualOrInterface);
}
}
- } else if (!cha_devirtualize && AlwaysThrows(actual_method)) {
+ } else if (!cha_devirtualize && AlwaysThrows(compiler_driver_, actual_method)) {
// Set always throws property for non-inlined method call with single target
// (unless it was obtained through CHA, because that would imply we have
// to add the CHA dependency, which seems not worth it).
@@ -1450,16 +1473,11 @@ bool HInliner::TryBuildAndInline(HInvoke* invoke_instruction,
<< " has soft failures un-handled by the compiler, so it cannot be inlined";
}
- if (!method->GetDeclaringClass()->IsVerified()) {
- uint16_t class_def_idx = method->GetDeclaringClass()->GetDexClassDefIndex();
- if (Runtime::Current()->UseJitCompilation() ||
- !compiler_driver_->IsMethodVerifiedWithoutFailures(
- method->GetDexMethodIndex(), class_def_idx, *method->GetDexFile())) {
- LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedNotVerified)
- << "Method " << method->PrettyMethod()
- << " couldn't be verified, so it cannot be inlined";
- return false;
- }
+ if (IsMethodUnverified(compiler_driver_, method)) {
+ LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedNotVerified)
+ << "Method " << method->PrettyMethod()
+ << " couldn't be verified, so it cannot be inlined";
+ return false;
}
if (invoke_instruction->IsInvokeStaticOrDirect() &&
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc
index 8b4eae1780..237ecd3c10 100644
--- a/compiler/optimizing/load_store_elimination.cc
+++ b/compiler/optimizing/load_store_elimination.cc
@@ -882,6 +882,7 @@ class LSEVisitor : public HGraphDelegateVisitor {
}
if (ref_info->IsSingletonAndRemovable() && !new_instance->NeedsChecks()) {
DCHECK(!new_instance->IsFinalizable());
+ // new_instance can potentially be eliminated.
singleton_new_instances_.push_back(new_instance);
}
ScopedArenaVector<HInstruction*>& heap_values =
@@ -904,7 +905,13 @@ class LSEVisitor : public HGraphDelegateVisitor {
return;
}
if (ref_info->IsSingletonAndRemovable()) {
- singleton_new_instances_.push_back(new_array);
+ if (new_array->GetLength()->IsIntConstant() &&
+ new_array->GetLength()->AsIntConstant()->GetValue() >= 0) {
+ // new_array can potentially be eliminated.
+ singleton_new_instances_.push_back(new_array);
+ } else {
+ // new_array may throw NegativeArraySizeException. Keep it.
+ }
}
ScopedArenaVector<HInstruction*>& heap_values =
heap_values_for_[new_array->GetBlock()->GetBlockId()];
diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc
index bebdc202e7..a1901f08f3 100644
--- a/dexlayout/dexlayout_test.cc
+++ b/dexlayout/dexlayout_test.cc
@@ -24,6 +24,7 @@
#include "base/unix_file/fd_file.h"
#include "common_runtime_test.h"
#include "dex/art_dex_file_loader.h"
+#include "dex/base64_test_util.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_loader.h"
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 39dbebfdf2..8c268d8ab9 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -73,74 +73,6 @@ namespace art {
using android::base::StringPrintf;
-static const uint8_t kBase64Map[256] = {
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
- 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
- 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
- 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255
-};
-
-uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
- CHECK(dst_size != nullptr);
- std::vector<uint8_t> tmp;
- uint32_t t = 0, y = 0;
- int g = 3;
- for (size_t i = 0; src[i] != '\0'; ++i) {
- uint8_t c = kBase64Map[src[i] & 0xFF];
- if (c == 255) continue;
- // the final = symbols are read and used to trim the remaining bytes
- if (c == 254) {
- c = 0;
- // prevent g < 0 which would potentially allow an overflow later
- if (--g < 0) {
- *dst_size = 0;
- return nullptr;
- }
- } else if (g != 3) {
- // we only allow = to be at the end
- *dst_size = 0;
- return nullptr;
- }
- t = (t << 6) | c;
- if (++y == 4) {
- tmp.push_back((t >> 16) & 255);
- if (g > 1) {
- tmp.push_back((t >> 8) & 255);
- }
- if (g > 2) {
- tmp.push_back(t & 255);
- }
- y = t = 0;
- }
- }
- if (y != 0) {
- *dst_size = 0;
- return nullptr;
- }
- std::unique_ptr<uint8_t[]> dst(new uint8_t[tmp.size()]);
- *dst_size = tmp.size();
- std::copy(tmp.begin(), tmp.end(), dst.get());
- return dst.release();
-}
-
ScratchFile::ScratchFile() {
// ANDROID_DATA needs to be set
CHECK_NE(static_cast<char*>(nullptr), getenv("ANDROID_DATA")) <<
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index 0aed70a330..b2b4d545cb 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -53,8 +53,6 @@ typedef std::vector<std::pair<std::string, const void*>> RuntimeOptions;
class Thread;
class VariableSizedHandleScope;
-uint8_t* DecodeBase64(const char* src, size_t* dst_size);
-
class ScratchFile {
public:
ScratchFile();
diff --git a/runtime/dex/base64_test_util.h b/runtime/dex/base64_test_util.h
new file mode 100644
index 0000000000..0657f9fd01
--- /dev/null
+++ b/runtime/dex/base64_test_util.h
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_RUNTIME_DEX_BASE64_TEST_UTIL_H_
+#define ART_RUNTIME_DEX_BASE64_TEST_UTIL_H_
+
+#include <base/logging.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <memory>
+#include <vector>
+
+namespace art {
+
+static inline uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
+ static const uint8_t kBase64Map[256] = {
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
+ 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
+ 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
+ 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+ 255, 255, 255, 255
+ };
+
+ CHECK(dst_size != nullptr);
+ std::vector<uint8_t> tmp;
+ uint32_t t = 0, y = 0;
+ int g = 3;
+ for (size_t i = 0; src[i] != '\0'; ++i) {
+ uint8_t c = kBase64Map[src[i] & 0xFF];
+ if (c == 255) continue;
+ // the final = symbols are read and used to trim the remaining bytes
+ if (c == 254) {
+ c = 0;
+ // prevent g < 0 which would potentially allow an overflow later
+ if (--g < 0) {
+ *dst_size = 0;
+ return nullptr;
+ }
+ } else if (g != 3) {
+ // we only allow = to be at the end
+ *dst_size = 0;
+ return nullptr;
+ }
+ t = (t << 6) | c;
+ if (++y == 4) {
+ tmp.push_back((t >> 16) & 255);
+ if (g > 1) {
+ tmp.push_back((t >> 8) & 255);
+ }
+ if (g > 2) {
+ tmp.push_back(t & 255);
+ }
+ y = t = 0;
+ }
+ }
+ if (y != 0) {
+ *dst_size = 0;
+ return nullptr;
+ }
+ std::unique_ptr<uint8_t[]> dst(new uint8_t[tmp.size()]);
+ *dst_size = tmp.size();
+ std::copy(tmp.begin(), tmp.end(), dst.get());
+ return dst.release();
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_DEX_BASE64_TEST_UTIL_H_
diff --git a/runtime/dex/code_item_accessors_test.cc b/runtime/dex/code_item_accessors_test.cc
index 1bd12a6f09..2bb4dde649 100644
--- a/runtime/dex/code_item_accessors_test.cc
+++ b/runtime/dex/code_item_accessors_test.cc
@@ -18,42 +18,35 @@
#include <sys/mman.h>
#include <memory>
+#include <vector>
-#include "common_runtime_test.h"
-#include "art_dex_file_loader.h"
#include "dex_file_loader.h"
-#include "mem_map.h"
+#include "gtest/gtest.h"
namespace art {
-class CodeItemAccessorsTest : public CommonRuntimeTest {};
+class CodeItemAccessorsTest : public testing::Test {};
-std::unique_ptr<const DexFile> CreateFakeDex(bool compact_dex) {
- std::string error_msg;
- std::unique_ptr<MemMap> map(
- MemMap::MapAnonymous(/*name*/ "map",
- /*addr*/ nullptr,
- /*byte_count*/ kPageSize,
- PROT_READ | PROT_WRITE,
- /*low_4gb*/ false,
- /*reuse*/ false,
- &error_msg));
- CHECK(map != nullptr) << error_msg;
+std::unique_ptr<const DexFile> CreateFakeDex(bool compact_dex, std::vector<uint8_t>* data) {
+ data->resize(kPageSize);
if (compact_dex) {
CompactDexFile::Header* header =
- const_cast<CompactDexFile::Header*>(CompactDexFile::Header::At(map->Begin()));
+ const_cast<CompactDexFile::Header*>(CompactDexFile::Header::At(data->data()));
CompactDexFile::WriteMagic(header->magic_);
CompactDexFile::WriteCurrentVersion(header->magic_);
header->data_off_ = 0;
- header->data_size_ = map->Size();
+ header->data_size_ = data->size();
} else {
- StandardDexFile::WriteMagic(map->Begin());
- StandardDexFile::WriteCurrentVersion(map->Begin());
+ StandardDexFile::WriteMagic(data->data());
+ StandardDexFile::WriteCurrentVersion(data->data());
}
- const ArtDexFileLoader dex_file_loader;
- std::unique_ptr<const DexFile> dex(dex_file_loader.Open("location",
+ const DexFileLoader dex_file_loader;
+ std::string error_msg;
+ std::unique_ptr<const DexFile> dex(dex_file_loader.Open(data->data(),
+ data->size(),
+ "location",
/*location_checksum*/ 123,
- std::move(map),
+ /*oat_dex_file*/nullptr,
/*verify*/false,
/*verify_checksum*/false,
&error_msg));
@@ -62,10 +55,13 @@ std::unique_ptr<const DexFile> CreateFakeDex(bool compact_dex) {
}
TEST(CodeItemAccessorsTest, TestDexInstructionsAccessor) {
- MemMap::Init();
- std::unique_ptr<const DexFile> standard_dex(CreateFakeDex(/*compact_dex*/false));
+ std::vector<uint8_t> standard_dex_data;
+ std::unique_ptr<const DexFile> standard_dex(CreateFakeDex(/*compact_dex*/false,
+ &standard_dex_data));
ASSERT_TRUE(standard_dex != nullptr);
- std::unique_ptr<const DexFile> compact_dex(CreateFakeDex(/*compact_dex*/true));
+ std::vector<uint8_t> compact_dex_data;
+ std::unique_ptr<const DexFile> compact_dex(CreateFakeDex(/*compact_dex*/true,
+ &compact_dex_data));
ASSERT_TRUE(compact_dex != nullptr);
static constexpr uint16_t kRegisterSize = 2;
static constexpr uint16_t kInsSize = 1;
diff --git a/runtime/dex/compact_dex_debug_info_test.cc b/runtime/dex/compact_dex_debug_info_test.cc
index 02b95e68d7..3267612443 100644
--- a/runtime/dex/compact_dex_debug_info_test.cc
+++ b/runtime/dex/compact_dex_debug_info_test.cc
@@ -15,18 +15,14 @@
*/
#include <vector>
-#include <sys/mman.h>
#include "base/logging.h"
#include "dex/compact_dex_debug_info.h"
#include "gtest/gtest.h"
-#include "mem_map.h"
namespace art {
TEST(CompactDexDebugInfoTest, TestBuildAndAccess) {
- MemMap::Init();
-
const size_t kDebugInfoMinOffset = 1234567;
std::vector<uint32_t> offsets = {
0, 17, 2, 3, 11, 0, 0, 0, 0, 1, 0, 1552, 100, 122, 44, 1234567, 0, 0,
@@ -58,17 +54,10 @@ TEST(CompactDexDebugInfoTest, TestBuildAndAccess) {
std::string error_msg;
// Leave some extra room since we don't copy the table at the start (for testing).
constexpr size_t kExtraOffset = 4 * 128;
- std::unique_ptr<MemMap> fake_dex(MemMap::MapAnonymous("fake dex",
- nullptr,
- data.size() + kExtraOffset,
- PROT_READ | PROT_WRITE,
- /*low_4gb*/ false,
- /*reuse*/ false,
- &error_msg));
- ASSERT_TRUE(fake_dex != nullptr) << error_msg;
- std::copy(data.begin(), data.end(), fake_dex->Begin() + kExtraOffset);
+ std::vector<uint8_t> fake_dex(data.size() + kExtraOffset);
+ std::copy(data.begin(), data.end(), fake_dex.data() + kExtraOffset);
- CompactDexDebugInfoOffsetTable::Accessor accessor(fake_dex->Begin() + kExtraOffset,
+ CompactDexDebugInfoOffsetTable::Accessor accessor(fake_dex.data() + kExtraOffset,
base_offset,
table_offset);
for (size_t i = 0; i < offsets.size(); ++i) {
diff --git a/runtime/dex/dex_file_test.cc b/runtime/dex/dex_file_test.cc
index 998bfd6c7f..2bb86672dc 100644
--- a/runtime/dex/dex_file_test.cc
+++ b/runtime/dex/dex_file_test.cc
@@ -23,6 +23,7 @@
#include "art_dex_file_loader.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
+#include "base64_test_util.h"
#include "code_item_accessors-inl.h"
#include "common_runtime_test.h"
#include "descriptors_names.h"
diff --git a/runtime/dex/dex_file_verifier_test.cc b/runtime/dex/dex_file_verifier_test.cc
index d73a7fbfa3..1cd4b2c07b 100644
--- a/runtime/dex/dex_file_verifier_test.cc
+++ b/runtime/dex/dex_file_verifier_test.cc
@@ -16,28 +16,26 @@
#include "dex_file_verifier.h"
-#include <sys/mman.h>
#include <zlib.h>
#include <functional>
#include <memory>
-#include "art_dex_file_loader.h"
#include "base/bit_utils.h"
#include "base/macros.h"
-#include "base/unix_file/fd_file.h"
-#include "common_runtime_test.h"
+#include "base64_test_util.h"
#include "descriptors_names.h"
#include "dex_file-inl.h"
#include "dex_file_loader.h"
#include "dex_file_types.h"
+#include "gtest/gtest.h"
#include "leb128.h"
-#include "scoped_thread_state_change-inl.h"
#include "standard_dex_file.h"
-#include "thread-current-inl.h"
namespace art {
+static constexpr char kLocationString[] = "dex_file_location";
+
// Make the Dex file version 37.
static void MakeDexVersion37(DexFile* dex_file) {
size_t offset = OFFSETOF_MEMBER(DexFile::Header, magic_) + 6;
@@ -55,7 +53,7 @@ static void FixUpChecksum(uint8_t* dex_file) {
header->checksum_ = adler_checksum;
}
-class DexFileVerifierTest : public CommonRuntimeTest {
+class DexFileVerifierTest : public testing::Test {
protected:
DexFile* GetDexFile(const uint8_t* dex_bytes, size_t length) {
return new StandardDexFile(dex_bytes, length, "tmp", 0, nullptr, nullptr);
@@ -101,28 +99,19 @@ static std::unique_ptr<const DexFile> OpenDexFileBase64(const char* base64,
std::unique_ptr<uint8_t[]> dex_bytes(DecodeBase64(base64, &length));
CHECK(dex_bytes.get() != nullptr);
- // write to provided file
- std::unique_ptr<File> file(OS::CreateEmptyFile(location));
- CHECK(file.get() != nullptr);
- if (!file->WriteFully(dex_bytes.get(), length)) {
- PLOG(FATAL) << "Failed to write base64 as dex file";
- }
- if (file->FlushCloseOrErase() != 0) {
- PLOG(FATAL) << "Could not flush and close test file.";
- }
- file.reset();
-
- // read dex file
- ScopedObjectAccess soa(Thread::Current());
+ // read dex
std::vector<std::unique_ptr<const DexFile>> tmp;
- const ArtDexFileLoader dex_file_loader;
- bool success = dex_file_loader.Open(
- location, location, /* verify */ true, /* verify_checksum */ true, error_msg, &tmp);
+ const DexFileLoader dex_file_loader;
+ bool success = dex_file_loader.OpenAll(dex_bytes.get(),
+ length,
+ location,
+ /* verify */ true,
+ /* verify_checksum */ true,
+ error_msg,
+ &tmp);
CHECK(success) << *error_msg;
EXPECT_EQ(1U, tmp.size());
std::unique_ptr<const DexFile> dex_file = std::move(tmp[0]);
- EXPECT_EQ(PROT_READ, dex_file->GetPermissions());
- EXPECT_TRUE(dex_file->IsReadOnly());
return dex_file;
}
@@ -148,9 +137,9 @@ static const char kGoodTestDex[] =
"AAIgAAANAAAAWgEAAAMgAAACAAAA6AEAAAAgAAABAAAA8wEAAAAQAAABAAAABAIAAA==";
TEST_F(DexFileVerifierTest, GoodDex) {
- ScratchFile tmp;
std::string error_msg;
- std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kGoodTestDex, tmp.GetFilename().c_str(),
+ std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kGoodTestDex,
+ kLocationString,
&error_msg));
ASSERT_TRUE(raw.get() != nullptr) << error_msg;
}
@@ -1311,10 +1300,9 @@ static const char kDebugInfoTestDex[] =
TEST_F(DexFileVerifierTest, DebugInfoTypeIdxTest) {
{
// The input dex file should be good before modification.
- ScratchFile tmp;
std::string error_msg;
std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kDebugInfoTestDex,
- tmp.GetFilename().c_str(),
+ kLocationString,
&error_msg));
ASSERT_TRUE(raw.get() != nullptr) << error_msg;
}
@@ -1333,10 +1321,9 @@ TEST_F(DexFileVerifierTest, SectionAlignment) {
{
// The input dex file should be good before modification. Any file is fine, as long as it
// uses all sections.
- ScratchFile tmp;
std::string error_msg;
std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kGoodTestDex,
- tmp.GetFilename().c_str(),
+ kLocationString,
&error_msg));
ASSERT_TRUE(raw.get() != nullptr) << error_msg;
}
@@ -1417,10 +1404,9 @@ static const char kProtoOrderingTestDex[] =
TEST_F(DexFileVerifierTest, ProtoOrdering) {
{
// The input dex file should be good before modification.
- ScratchFile tmp;
std::string error_msg;
std::unique_ptr<const DexFile> raw(OpenDexFileBase64(kProtoOrderingTestDex,
- tmp.GetFilename().c_str(),
+ kLocationString,
&error_msg));
ASSERT_TRUE(raw.get() != nullptr) << error_msg;
}
diff --git a/runtime/dex/utf_test.cc b/runtime/dex/utf_test.cc
index d1e97515d3..d2f22d16ef 100644
--- a/runtime/dex/utf_test.cc
+++ b/runtime/dex/utf_test.cc
@@ -16,15 +16,15 @@
#include "utf.h"
-#include "common_runtime_test.h"
-#include "utf-inl.h"
-
#include <map>
#include <vector>
+#include "gtest/gtest.h"
+#include "utf-inl.h"
+
namespace art {
-class UtfTest : public CommonRuntimeTest {};
+class UtfTest : public testing::Test {};
TEST_F(UtfTest, GetLeadingUtf16Char) {
EXPECT_EQ(0xffff, GetLeadingUtf16Char(0xeeeeffff));
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 3afd320f05..b26b09c156 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1178,7 +1178,12 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
// (b) Zygote forked a new process that is not exempt (see ZygoteHooks).
// TODO(dbrazdil): Turn the NoHiddenApiChecks negative flag into a positive one
// to clean up this logic.
- do_hidden_api_checks_ = IsAotCompiler() && !runtime_options.Exists(Opt::NoHiddenApiChecks);
+ if (kIsTargetBuild && IsAotCompiler() && !runtime_options.Exists(Opt::NoHiddenApiChecks)) {
+ // dex2oat on target without -Xno-hidden-api-checks.
+ do_hidden_api_checks_ = !IsCompilingBootImage();
+ } else {
+ do_hidden_api_checks_ = false;
+ }
DCHECK(!is_zygote_ || !do_hidden_api_checks_)
<< "Zygote should not be started with hidden API checks";
diff --git a/test/530-checker-lse/expected.txt b/test/530-checker-lse/expected.txt
index ddae16aff4..fb67e22d0b 100644
--- a/test/530-checker-lse/expected.txt
+++ b/test/530-checker-lse/expected.txt
@@ -1 +1,2 @@
java.lang.ArrayIndexOutOfBoundsException: length=3; index=3
+Got NegativeArraySizeException.
diff --git a/test/530-checker-lse/src/Main.java b/test/530-checker-lse/src/Main.java
index 98838c5089..ebde3bf845 100644
--- a/test/530-checker-lse/src/Main.java
+++ b/test/530-checker-lse/src/Main.java
@@ -1052,6 +1052,23 @@ public class Main {
return array[1] + array[i];
}
+ /// CHECK-START: int Main.testAllocationEliminationOfArray5(int) load_store_elimination (before)
+ /// CHECK: NewArray
+ /// CHECK: ArraySet
+ /// CHECK: ArrayGet
+
+ /// CHECK-START: int Main.testAllocationEliminationOfArray5(int) load_store_elimination (after)
+ /// CHECK: NewArray
+ /// CHECK-NOT: ArraySet
+ /// CHECK-NOT: ArrayGet
+ private static int testAllocationEliminationOfArray5(int i) {
+ // Cannot eliminate array allocation due to unknown i that may
+ // cause NegativeArraySizeException.
+ int[] array = new int[i];
+ array[1] = 12;
+ return array[1];
+ }
+
/// CHECK-START: int Main.testExitMerge(boolean) load_store_elimination (before)
/// CHECK: NewInstance
/// CHECK: InstanceFieldSet
@@ -1205,6 +1222,12 @@ public class Main {
assertIntEquals(testAllocationEliminationOfArray2(), 11);
assertIntEquals(testAllocationEliminationOfArray3(2), 4);
assertIntEquals(testAllocationEliminationOfArray4(2), 6);
+ assertIntEquals(testAllocationEliminationOfArray5(2), 12);
+ try {
+ testAllocationEliminationOfArray5(-2);
+ } catch (NegativeArraySizeException e) {
+ System.out.println("Got NegativeArraySizeException.");
+ }
assertIntEquals(testStoreStore().i, 41);
assertIntEquals(testStoreStore().j, 43);
diff --git a/test/675-checker-unverified-method/expected.txt b/test/675-checker-unverified-method/expected.txt
new file mode 100644
index 0000000000..b0aad4deb5
--- /dev/null
+++ b/test/675-checker-unverified-method/expected.txt
@@ -0,0 +1 @@
+passed
diff --git a/test/675-checker-unverified-method/info.txt b/test/675-checker-unverified-method/info.txt
new file mode 100644
index 0000000000..667211a2fa
--- /dev/null
+++ b/test/675-checker-unverified-method/info.txt
@@ -0,0 +1 @@
+Make sure analysis of unverified method is skipped.
diff --git a/test/675-checker-unverified-method/smali/TestCase.smali b/test/675-checker-unverified-method/smali/TestCase.smali
new file mode 100644
index 0000000000..673b3f2708
--- /dev/null
+++ b/test/675-checker-unverified-method/smali/TestCase.smali
@@ -0,0 +1,55 @@
+# Copyright (C) 2018 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.
+
+.class public LTestCase;
+
+.super Ljava/lang/Object;
+
+#
+# Ensure foo() does not analyze unverified bad() always-throws property.
+#
+## CHECK-START: void TestCase.foo(java.lang.Object) inliner (after)
+## CHECK-DAG: InvokeStaticOrDirect method_name:TestCase.bar always_throws:true
+## CHECK-DAG: InvokeStaticOrDirect method_name:TestCase.bad always_throws:false
+.method public static foo(Ljava/lang/Object;)V
+ .registers 1
+ if-nez v0, :Skip1
+ invoke-static {}, LTestCase;->bar()V
+:Skip1
+ if-nez v0, :Skip2
+ invoke-static {}, LTestCase;->bad()Lwont/be/Resolvable;
+:Skip2
+ return-void
+.end method
+
+#
+# Method bar() that verifies (but is never called).
+#
+.method public static bar()V
+ .registers 1
+ new-instance v0, Ljava/lang/RuntimeException;
+ invoke-direct {v0}, Ljava/lang/RuntimeException;-><init>()V
+ throw v0
+.end method
+
+#
+# Method bad() that fails to verify (but is never called).
+#
+.method public static bad()Lwont/be/Resolvable;
+ .registers 1
+ invoke-static {}, LTestCase;->bar()Lwont/be/Resolvable;
+ move-result-object v0
+ throw v0
+.end method
+
diff --git a/test/675-checker-unverified-method/src/Main.java b/test/675-checker-unverified-method/src/Main.java
new file mode 100644
index 0000000000..0cdb2fe84b
--- /dev/null
+++ b/test/675-checker-unverified-method/src/Main.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+/**
+ * Ensure unverified method is not analyzed.
+ */
+public class Main {
+ public static void main(String[] args) throws Exception {
+ Object o = new Object();
+ Class<?> c = Class.forName("TestCase");
+ Object[] arguments = { o };
+ c.getMethod("foo", Object.class).invoke(null, arguments);
+ System.out.println("passed");
+ }
+}
diff --git a/test/956-methodhandles/src/Main.java b/test/956-methodhandles/src/Main.java
index cb06e4263e..1ddef03d62 100644
--- a/test/956-methodhandles/src/Main.java
+++ b/test/956-methodhandles/src/Main.java
@@ -22,6 +22,7 @@ import java.lang.invoke.MethodType;
import java.lang.invoke.WrongMethodTypeException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@@ -79,6 +80,7 @@ public class Main {
testVariableArity();
testVariableArity_MethodHandles_bind();
testRevealDirect();
+ testReflectiveCalls();
}
public static void testfindSpecial_invokeSuperBehaviour() throws Throwable {
@@ -1624,4 +1626,20 @@ public class Main {
assertEquals(field, info.reflectAs(Field.class, MethodHandles.lookup()));
assertEquals(MethodType.methodType(String.class), info.getMethodType());
}
+
+ public static void testReflectiveCalls() throws Throwable {
+ String[] methodNames = { "invoke", "invokeExact" };
+ for (String methodName : methodNames) {
+ Method invokeMethod = MethodHandle.class.getMethod(methodName, Object[].class);
+ MethodHandle instance =
+ MethodHandles.lookup().findVirtual(java.io.PrintStream.class, "println",
+ MethodType.methodType(void.class, String.class));
+ try {
+ invokeMethod.invoke(instance, new Object[] { new Object[] { Integer.valueOf(1) } } );
+ fail();
+ } catch (InvocationTargetException ite) {
+ assertEquals(ite.getCause().getClass(), UnsupportedOperationException.class);
+ }
+ }
+ }
}
diff --git a/tools/external_oj_libjdwp_art_failures.txt b/tools/external_oj_libjdwp_art_failures.txt
index 88ffa6eaf7..828c0aac0f 100644
--- a/tools/external_oj_libjdwp_art_failures.txt
+++ b/tools/external_oj_libjdwp_art_failures.txt
@@ -53,6 +53,19 @@
"org.apache.harmony.jpda.tests.jdwp.VirtualMachine.CapabilitiesNewTest#testCapabilitiesNew001" ]
},
{
+ description: "Test is flaky",
+ result: EXEC_FAILED,
+ bug: 69121056,
+ name: "org.apache.harmony.jpda.tests.jdwp.ObjectReference.IsCollectedTest#testIsCollected001"
+},
+{
+ description: "Test is flaky",
+ result: EXEC_FAILED,
+ bug: 70958370,
+ names: [ "org.apache.harmony.jpda.tests.jdwp.ObjectReference.EnableCollectionTest#testEnableCollection001",
+ "org.apache.harmony.jpda.tests.jdwp.MultiSession.EnableCollectionTest#testEnableCollection001" ]
+},
+{
description: "Test crashes",
result: EXEC_FAILED,
bug: 69591477,
diff --git a/tools/prebuilt_libjdwp_art_failures.txt b/tools/prebuilt_libjdwp_art_failures.txt
index b0475bbdfd..a9d268de0a 100644
--- a/tools/prebuilt_libjdwp_art_failures.txt
+++ b/tools/prebuilt_libjdwp_art_failures.txt
@@ -102,12 +102,25 @@
"org.apache.harmony.jpda.tests.jdwp.VirtualMachine.CapabilitiesNewTest#testCapabilitiesNew001" ]
},
{
+ description: "Test is flaky",
+ result: EXEC_FAILED,
+ bug: 69121056,
+ name: "org.apache.harmony.jpda.tests.jdwp.ObjectReference.IsCollectedTest#testIsCollected001"
+},
+{
description: "Test for ddms extensions that are not implemented for prebuilt-libjdwp",
result: EXEC_FAILED,
bug: 69169846,
name: "org.apache.harmony.jpda.tests.jdwp.DDM.DDMTest#testChunk001"
},
{
+ description: "Test is flakey",
+ result: EXEC_FAILED,
+ bug: 70958370,
+ names: [ "org.apache.harmony.jpda.tests.jdwp.ObjectReference.EnableCollectionTest#testEnableCollection001",
+ "org.apache.harmony.jpda.tests.jdwp.MultiSession.EnableCollectionTest#testEnableCollection001" ]
+},
+{
description: "Test crashes",
result: EXEC_FAILED,
bug: 69591477,