diff options
296 files changed, 2040 insertions, 892 deletions
diff --git a/build/art.go b/build/art.go index b33b565899..9de2b05793 100644 --- a/build/art.go +++ b/build/art.go @@ -170,12 +170,23 @@ func globalDefaults(ctx android.LoadHookContext) { } Cflags []string Asflags []string + Sanitize struct { + Recover []string + } } p := &props{} p.Cflags, p.Asflags = globalFlags(ctx) p.Target.Android.Cflags = deviceFlags(ctx) p.Target.Host.Cflags = hostFlags(ctx) + + if envTrue(ctx, "ART_DEX_FILE_ACCESS_TRACKING") { + p.Cflags = append(p.Cflags, "-DART_DEX_FILE_ACCESS_TRACKING") + p.Sanitize.Recover = []string { + "address", + } + } + ctx.AppendProperties(p) } diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc index 39edd1eb02..a1ee68faeb 100644 --- a/compiler/common_compiler_test.cc +++ b/compiler/common_compiler_test.cc @@ -33,7 +33,7 @@ #include "mirror/object-inl.h" #include "oat_quick_method_header.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils.h" namespace art { diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc index 1573062033..2db99cda3e 100644 --- a/compiler/dex/dex_to_dex_compiler.cc +++ b/compiler/dex/dex_to_dex_compiler.cc @@ -28,7 +28,7 @@ #include "driver/compiler_driver.h" #include "driver/dex_compilation_unit.h" #include "mirror/dex_cache.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace optimizer { diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc index 0338cfde8c..b87cb61ed6 100644 --- a/compiler/dex/verification_results.cc +++ b/compiler/dex/verification_results.cc @@ -17,12 +17,13 @@ #include "verification_results.h" #include "base/logging.h" -#include "base/stl_util.h" #include "base/mutex-inl.h" +#include "base/stl_util.h" #include "driver/compiler_driver.h" #include "driver/compiler_options.h" +#include "runtime.h" #include "thread.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils/atomic_method_ref_map-inl.h" #include "verified_method.h" #include "verifier/method_verifier-inl.h" diff --git a/compiler/driver/compiled_method_storage.cc b/compiler/driver/compiled_method_storage.cc index e6a47ba60f..528b0a215b 100644 --- a/compiler/driver/compiled_method_storage.cc +++ b/compiler/driver/compiled_method_storage.cc @@ -21,7 +21,7 @@ #include "base/logging.h" #include "compiled_method.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils.h" #include "utils/dedupe_set-inl.h" #include "utils/swap_space.h" diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index fc5f847354..0097f55e53 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -1000,7 +1000,8 @@ bool CompilerDriver::ShouldCompileBasedOnProfile(const MethodReference& method_r if (profile_compilation_info_ == nullptr) { return false; } - bool result = profile_compilation_info_->ContainsMethod(method_ref); + // TODO: Revisit compiling all startup methods. b/36457259 + bool result = profile_compilation_info_->IsStartupOrHotMethod(method_ref); if (kDebugProfileGuidedCompilation) { LOG(INFO) << "[ProfileGuidedCompilation] " diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc index 26ea39f205..4b979d8125 100644 --- a/compiler/driver/compiler_driver_test.cc +++ b/compiler/driver/compiler_driver_test.cc @@ -239,8 +239,14 @@ class CompilerDriverProfileTest : public CompilerDriverTest { ProfileCompilationInfo info; for (const std::unique_ptr<const DexFile>& dex_file : dex_files) { - profile_info_.AddMethodIndex(dex_file->GetLocation(), dex_file->GetLocationChecksum(), 1); - profile_info_.AddMethodIndex(dex_file->GetLocation(), dex_file->GetLocationChecksum(), 2); + profile_info_.AddMethodIndex(dex_file->GetLocation(), + dex_file->GetLocationChecksum(), + 1, + dex_file->NumMethodIds()); + profile_info_.AddMethodIndex(dex_file->GetLocation(), + dex_file->GetLocationChecksum(), + 2, + dex_file->NumMethodIds()); } return &profile_info_; } diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc index 28c35e96b4..738f5a2b29 100644 --- a/compiler/elf_writer_quick.cc +++ b/compiler/elf_writer_quick.cc @@ -34,7 +34,7 @@ #include "leb128.h" #include "linker/buffered_output_stream.h" #include "linker/file_output_stream.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_pool.h" #include "utils.h" diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index dce81a4134..c117777508 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -58,7 +58,7 @@ #include "parallel_move_resolver.h" #include "ssa_liveness_analysis.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils/assembler.h" namespace art { @@ -557,6 +557,9 @@ void CodeGenerator::BlockIfInRegister(Location location, bool is_out) const { } void CodeGenerator::AllocateLocations(HInstruction* instruction) { + for (HEnvironment* env = instruction->GetEnvironment(); env != nullptr; env = env->GetParent()) { + env->AllocateLocations(); + } instruction->Accept(GetLocationBuilder()); DCHECK(CheckTypeConsistency(instruction)); LocationSummary* locations = instruction->GetLocations(); diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index ec02fe36d4..fc2f4c1a6f 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -31,6 +31,7 @@ #include "nodes.h" #include "optimizing_compiler_stats.h" #include "read_barrier_option.h" +#include "stack.h" #include "stack_map_stream.h" #include "string_reference.h" #include "type_reference.h" diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc index 7c833cf70c..c0ec58f824 100644 --- a/compiler/optimizing/induction_var_range.cc +++ b/compiler/optimizing/induction_var_range.cc @@ -1132,11 +1132,27 @@ bool InductionVarRange::GenerateLastValuePeriodic(HInductionVarAnalysis::Inducti /*out*/bool* needs_taken_test) const { DCHECK(info != nullptr); DCHECK_EQ(info->induction_class, HInductionVarAnalysis::kPeriodic); - // Count period. + // Count period and detect all-invariants. int64_t period = 1; - for (HInductionVarAnalysis::InductionInfo* p = info; - p->induction_class == HInductionVarAnalysis::kPeriodic; - p = p->op_b, ++period) {} + bool all_invariants = true; + HInductionVarAnalysis::InductionInfo* p = info; + for (; p->induction_class == HInductionVarAnalysis::kPeriodic; p = p->op_b, ++period) { + DCHECK_EQ(p->op_a->induction_class, HInductionVarAnalysis::kInvariant); + if (p->op_a->operation != HInductionVarAnalysis::kFetch) { + all_invariants = false; + } + } + DCHECK_EQ(p->induction_class, HInductionVarAnalysis::kInvariant); + if (p->operation != HInductionVarAnalysis::kFetch) { + all_invariants = false; + } + // Don't rely on FP arithmetic to be precise, unless the full period + // consist of pre-computed expressions only. + if (info->type == Primitive::kPrimFloat || info->type == Primitive::kPrimDouble) { + if (!all_invariants) { + return false; + } + } // Handle any periodic(x, periodic(.., y)) for known maximum index value m. int64_t m = 0; if (IsConstant(trip->op_a, kExact, &m) && m >= 1) { diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index b1d2727e39..b664d41013 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -25,7 +25,7 @@ #include "mirror/dex_cache-inl.h" #include "nodes.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils.h" namespace art { diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc index 9803c9a0e9..1448be927f 100644 --- a/compiler/optimizing/intrinsics_arm.cc +++ b/compiler/optimizing/intrinsics_arm.cc @@ -28,7 +28,7 @@ #include "mirror/reference.h" #include "mirror/string.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils/arm/assembler_arm.h" namespace art { diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index b511c5a18d..c4d7cc8251 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -28,7 +28,7 @@ #include "mirror/reference.h" #include "mirror/string-inl.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils/arm64/assembler_arm64.h" using namespace vixl::aarch64; // NOLINT(build/namespaces) diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc index 1a33b0ee01..19a3eb9634 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.cc +++ b/compiler/optimizing/intrinsics_arm_vixl.cc @@ -26,7 +26,7 @@ #include "mirror/reference.h" #include "mirror/string.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "aarch32/constants-aarch32.h" diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index 57adcc3c2f..fa843a6200 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -31,7 +31,7 @@ #include "mirror/reference.h" #include "mirror/string.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils/x86/assembler_x86.h" #include "utils/x86/constants_x86.h" diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index 773383ef1b..4f4592b3df 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -31,7 +31,7 @@ #include "mirror/reference.h" #include "mirror/string.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils/x86_64/assembler_x86_64.h" #include "utils/x86_64/constants_x86_64.h" diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 544cfda03e..befd0ff97b 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -1790,7 +1790,7 @@ class HEnvironment : public ArenaObject<kArenaAllocEnvironment> { uint32_t dex_pc, HInstruction* holder) : vregs_(number_of_vregs, arena->Adapter(kArenaAllocEnvironmentVRegs)), - locations_(number_of_vregs, arena->Adapter(kArenaAllocEnvironmentLocations)), + locations_(arena->Adapter(kArenaAllocEnvironmentLocations)), parent_(nullptr), method_(method), dex_pc_(dex_pc), @@ -1804,6 +1804,11 @@ class HEnvironment : public ArenaObject<kArenaAllocEnvironment> { to_copy.GetDexPc(), holder) {} + void AllocateLocations() { + DCHECK(locations_.empty()); + locations_.resize(vregs_.size()); + } + void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) { if (parent_ != nullptr) { parent_->SetAndCopyParentChain(allocator, parent); diff --git a/compiler/optimizing/register_allocator_graph_color.cc b/compiler/optimizing/register_allocator_graph_color.cc index 300f4c6239..2fd7b03151 100644 --- a/compiler/optimizing/register_allocator_graph_color.cc +++ b/compiler/optimizing/register_allocator_graph_color.cc @@ -20,7 +20,7 @@ #include "linear_order.h" #include "register_allocation_resolver.h" #include "ssa_liveness_analysis.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/compiler/optimizing/scheduler_arm.h b/compiler/optimizing/scheduler_arm.h index 8d5e4f375b..cb679fcd2d 100644 --- a/compiler/optimizing/scheduler_arm.h +++ b/compiler/optimizing/scheduler_arm.h @@ -17,7 +17,11 @@ #ifndef ART_COMPILER_OPTIMIZING_SCHEDULER_ARM_H_ #define ART_COMPILER_OPTIMIZING_SCHEDULER_ARM_H_ +#ifdef ART_USE_OLD_ARM_BACKEND +#include "code_generator_arm.h" +#else #include "code_generator_arm_vixl.h" +#endif #include "scheduler.h" namespace art { diff --git a/compiler/utils/dedupe_set_test.cc b/compiler/utils/dedupe_set_test.cc index 4c0979e0b7..b390508ed4 100644 --- a/compiler/utils/dedupe_set_test.cc +++ b/compiler/utils/dedupe_set_test.cc @@ -23,7 +23,7 @@ #include "base/array_ref.h" #include "dedupe_set-inl.h" #include "gtest/gtest.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/compiler/utils/swap_space.cc b/compiler/utils/swap_space.cc index a1eb08e041..4f6c915142 100644 --- a/compiler/utils/swap_space.cc +++ b/compiler/utils/swap_space.cc @@ -23,7 +23,7 @@ #include "base/logging.h" #include "base/macros.h" #include "base/mutex.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc index 6420aa8759..b604e8b5f1 100644 --- a/dex2oat/dex2oat_test.cc +++ b/dex2oat/dex2oat_test.cc @@ -28,6 +28,7 @@ #include "base/logging.h" #include "base/macros.h" +#include "base/mutex-inl.h" #include "dex_file-inl.h" #include "dex2oat_environment_test.h" #include "dex2oat_return_codes.h" @@ -38,6 +39,8 @@ namespace art { +static constexpr size_t kMaxMethodIds = 65535; + using android::base::StringPrintf; class Dex2oatTest : public Dex2oatEnvironmentTest { @@ -612,7 +615,7 @@ class Dex2oatLayoutTest : public Dex2oatTest { ProfileCompilationInfo info; std::string profile_key = ProfileCompilationInfo::GetProfileDexFileKey(dex_location); for (size_t i = 0; i < num_classes; ++i) { - info.AddClassIndex(profile_key, checksum, dex::TypeIndex(1 + i)); + info.AddClassIndex(profile_key, checksum, dex::TypeIndex(1 + i), kMaxMethodIds); } bool result = info.Save(profile_test_fd); close(profile_test_fd); diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index 205c0d1384..db227676c2 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -1557,7 +1557,7 @@ void DexLayout::LayoutStringData(const DexFile* dex_file) { (method->GetAccessFlags() & kAccConstructor) != 0 && (method->GetAccessFlags() & kAccStatic) != 0; const bool method_executed = is_clinit || - info_->ContainsMethod(MethodReference(dex_file, method_id->GetIndex())); + info_->IsStartupOrHotMethod(MethodReference(dex_file, method_id->GetIndex())); if (!method_executed) { continue; } @@ -1699,7 +1699,7 @@ int32_t DexLayout::LayoutCodeItems(const DexFile* dex_file, (method->GetAccessFlags() & kAccConstructor) != 0 && (method->GetAccessFlags() & kAccStatic) != 0; const bool is_method_executed = is_clinit || - info_->ContainsMethod(MethodReference(dex_file, method_id->GetIndex())); + info_->IsStartupOrHotMethod(MethodReference(dex_file, method_id->GetIndex())); code_items[is_method_executed ? CodeItemKind::kMethodExecuted : CodeItemKind::kMethodNotExecuted] diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc index 1d09a7f72a..6fe8eeb66e 100644 --- a/dexlayout/dexlayout_test.cc +++ b/dexlayout/dexlayout_test.cc @@ -341,18 +341,30 @@ class DexLayoutTest : public CommonRuntimeTest { if ((i & 3) != 0) { pfi.AddMethodIndex(dex_location, dex_file->GetLocationChecksum(), - i); + i, + dex_file->NumMethodIds()); + ++profile_methods; + } else if ((i & 2) != 0) { + pfi.AddSampledMethod(/*startup*/true, + dex_location, + dex_file->GetLocationChecksum(), + i, + dex_file->NumMethodIds()); ++profile_methods; } } DexCacheResolvedClasses cur_classes(dex_location, dex_location, - dex_file->GetLocationChecksum()); + dex_file->GetLocationChecksum(), + dex_file->NumMethodIds()); // Add every even class too. for (uint32_t i = 0; i < dex_file->NumClassDefs(); i += 1) { - cur_classes.AddClass(dex_file->GetClassDef(i).class_idx_); - ++profile_classes; + if ((i & 2) == 0) { + cur_classes.AddClass(dex_file->GetClassDef(i).class_idx_); + ++profile_classes; + } } + classes.insert(cur_classes); } pfi.AddMethodsAndClasses(pmis, classes); // Write to provided file. diff --git a/imgdiag/imgdiag_test.cc b/imgdiag/imgdiag_test.cc index 0d46b2ea7a..c948d3cbe2 100644 --- a/imgdiag/imgdiag_test.cc +++ b/imgdiag/imgdiag_test.cc @@ -28,6 +28,7 @@ #include "runtime/utils.h" #include "runtime/gc/space/image_space.h" #include "runtime/gc/heap.h" +#include "runtime/runtime.h" #include <sys/types.h> #include <unistd.h> diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index f07e0f9941..a79b408a40 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -63,6 +63,7 @@ #include "safe_map.h" #include "scoped_thread_state_change-inl.h" #include "ScopedLocalRef.h" +#include "stack.h" #include "stack_map.h" #include "string_reference.h" #include "thread_list.h" diff --git a/profman/profile_assistant_test.cc b/profman/profile_assistant_test.cc index 1c328987cb..e87852baf0 100644 --- a/profman/profile_assistant_test.cc +++ b/profman/profile_assistant_test.cc @@ -30,6 +30,8 @@ namespace art { +static constexpr size_t kMaxMethodIds = 65535; + class ProfileAssistantTest : public CommonRuntimeTest { public: void PostRuntimeCreate() OVERRIDE { @@ -56,15 +58,18 @@ class ProfileAssistantTest : public CommonRuntimeTest { GetOfflineProfileMethodInfo(dex_location1, dex_location_checksum1, dex_location2, dex_location_checksum2); if (reverse_dex_write_order) { - ASSERT_TRUE(info->AddMethod(dex_location2, dex_location_checksum2, i, pmi)); - ASSERT_TRUE(info->AddMethod(dex_location1, dex_location_checksum1, i, pmi)); + ASSERT_TRUE(info->AddMethod(dex_location2, dex_location_checksum2, i, kMaxMethodIds, pmi)); + ASSERT_TRUE(info->AddMethod(dex_location1, dex_location_checksum1, i, kMaxMethodIds, pmi)); } else { - ASSERT_TRUE(info->AddMethod(dex_location1, dex_location_checksum1, i, pmi)); - ASSERT_TRUE(info->AddMethod(dex_location2, dex_location_checksum2, i, pmi)); + ASSERT_TRUE(info->AddMethod(dex_location1, dex_location_checksum1, i, kMaxMethodIds, pmi)); + ASSERT_TRUE(info->AddMethod(dex_location2, dex_location_checksum2, i, kMaxMethodIds, pmi)); } } for (uint16_t i = 0; i < number_of_classes; i++) { - ASSERT_TRUE(info->AddClassIndex(dex_location1, dex_location_checksum1, dex::TypeIndex(i))); + ASSERT_TRUE(info->AddClassIndex(dex_location1, + dex_location_checksum1, + dex::TypeIndex(i), + kMaxMethodIds)); } ASSERT_TRUE(info->Save(GetFd(profile))); @@ -84,8 +89,8 @@ class ProfileAssistantTest : public CommonRuntimeTest { const std::string& dex_location2, uint32_t dex_checksum2) { ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap(); ProfileCompilationInfo::OfflineProfileMethodInfo pmi(ic_map); - pmi.dex_references.emplace_back(dex_location1, dex_checksum1); - pmi.dex_references.emplace_back(dex_location2, dex_checksum2); + pmi.dex_references.emplace_back(dex_location1, dex_checksum1, kMaxMethodIds); + pmi.dex_references.emplace_back(dex_location2, dex_checksum2, kMaxMethodIds); // Monomorphic for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) { @@ -520,10 +525,11 @@ TEST_F(ProfileAssistantTest, TestProfileGenerationWithIndexDex) { TEST_F(ProfileAssistantTest, TestProfileCreationAllMatch) { // Class names put here need to be in sorted order. std::vector<std::string> class_names = { + "HLjava/lang/Object;-><init>()V", "Ljava/lang/Comparable;", "Ljava/lang/Math;", "Ljava/lang/Object;", - "Ljava/lang/Object;-><init>()V" + "SPLjava/lang/Comparable;->compareTo(Ljava/lang/Object;)I", }; std::string file_contents; for (std::string& class_name : class_names) { @@ -807,15 +813,21 @@ TEST_F(ProfileAssistantTest, TestProfileCreateWithInvalidData) { // Verify that the start-up classes contain the invalid class. std::set<dex::TypeIndex> classes; - std::set<uint16_t> methods; - ASSERT_TRUE(info.GetClassesAndMethods(*dex_file, &classes, &methods)); + std::set<uint16_t> hot_methods; + std::set<uint16_t> startup_methods; + std::set<uint16_t> post_start_methods; + ASSERT_TRUE(info.GetClassesAndMethods(*dex_file, + &classes, + &hot_methods, + &startup_methods, + &post_start_methods)); ASSERT_EQ(1u, classes.size()); ASSERT_TRUE(classes.find(invalid_class_index) != classes.end()); // Verify that the invalid method is in the profile. - ASSERT_EQ(2u, methods.size()); + ASSERT_EQ(2u, hot_methods.size()); uint16_t invalid_method_index = std::numeric_limits<uint16_t>::max() - 1; - ASSERT_TRUE(methods.find(invalid_method_index) != methods.end()); + ASSERT_TRUE(hot_methods.find(invalid_method_index) != hot_methods.end()); } } // namespace art diff --git a/profman/profman.cc b/profman/profman.cc index afc21057b1..adef0d0332 100644 --- a/profman/profman.cc +++ b/profman/profman.cc @@ -43,6 +43,7 @@ #include "runtime.h" #include "type_reference.h" #include "utils.h" +#include "type_reference.h" #include "zip_archive.h" namespace art { @@ -150,6 +151,9 @@ static const std::string kClassAllMethods = "*"; static constexpr char kProfileParsingInlineChacheSep = '+'; static constexpr char kProfileParsingTypeSep = ','; static constexpr char kProfileParsingFirstCharInSignature = '('; +static constexpr char kMethodFlagStringHot = 'H'; +static constexpr char kMethodFlagStringStartup = 'S'; +static constexpr char kMethodFlagStringPostStartup = 'P'; // TODO(calin): This class has grown too much from its initial design. Split the functionality // into smaller, more contained pieces. @@ -426,18 +430,42 @@ class ProfMan FINAL { } for (const std::unique_ptr<const DexFile>& dex_file : *dex_files) { std::set<dex::TypeIndex> class_types; - std::set<uint16_t> methods; - if (profile_info.GetClassesAndMethods(*dex_file.get(), &class_types, &methods)) { + std::set<uint16_t> hot_methods; + std::set<uint16_t> startup_methods; + std::set<uint16_t> post_startup_methods; + std::set<uint16_t> combined_methods; + if (profile_info.GetClassesAndMethods(*dex_file.get(), + &class_types, + &hot_methods, + &startup_methods, + &post_startup_methods)) { for (const dex::TypeIndex& type_index : class_types) { const DexFile::TypeId& type_id = dex_file->GetTypeId(type_index); out_lines->insert(std::string(dex_file->GetTypeDescriptor(type_id))); } - for (uint16_t dex_method_idx : methods) { + combined_methods = hot_methods; + combined_methods.insert(startup_methods.begin(), startup_methods.end()); + combined_methods.insert(post_startup_methods.begin(), post_startup_methods.end()); + for (uint16_t dex_method_idx : combined_methods) { const DexFile::MethodId& id = dex_file->GetMethodId(dex_method_idx); std::string signature_string(dex_file->GetMethodSignature(id).ToString()); std::string type_string(dex_file->GetTypeDescriptor(dex_file->GetTypeId(id.class_idx_))); std::string method_name(dex_file->GetMethodName(id)); - out_lines->insert(type_string + kMethodSep + method_name + signature_string); + std::string flags_string; + if (hot_methods.find(dex_method_idx) != hot_methods.end()) { + flags_string += kMethodFlagStringHot; + } + if (startup_methods.find(dex_method_idx) != startup_methods.end()) { + flags_string += kMethodFlagStringStartup; + } + if (post_startup_methods.find(dex_method_idx) != post_startup_methods.end()) { + flags_string += kMethodFlagStringPostStartup; + } + out_lines->insert(flags_string + + type_string + + kMethodSep + + method_name + + signature_string); } } } @@ -461,7 +489,7 @@ class ProfMan FINAL { return true; } - int DumpClasses() { + int DumpClassesAndMethods() { // Validate that at least one profile file or reference was specified. if (profile_files_.empty() && profile_files_fd_.empty() && reference_profile_file_.empty() && !FdIsValid(reference_profile_file_fd_)) { @@ -694,11 +722,30 @@ class ProfMan FINAL { /*out*/ProfileCompilationInfo* profile) { std::string klass; std::string method_str; - size_t method_sep_index = line.find(kMethodSep); + bool is_hot = false; + bool is_startup = false; + bool is_post_startup = false; + const size_t method_sep_index = line.find(kMethodSep, 0); if (method_sep_index == std::string::npos) { - klass = line; + klass = line.substr(0); } else { - klass = line.substr(0, method_sep_index); + // The method prefix flags are only valid for method strings. + size_t start_index = 0; + while (start_index < line.size() && line[start_index] != 'L') { + const char c = line[start_index]; + if (c == kMethodFlagStringHot) { + is_hot = true; + } else if (c == kMethodFlagStringStartup) { + is_startup = true; + } else if (c == kMethodFlagStringPostStartup) { + is_post_startup = true; + } else { + LOG(WARNING) << "Invalid flag " << c; + return false; + } + ++start_index; + } + klass = line.substr(start_index, method_sep_index - start_index); method_str = line.substr(method_sep_index + kMethodSep.size()); } @@ -715,7 +762,8 @@ class ProfMan FINAL { const auto& dex_resolved_classes = resolved_class_set.emplace( dex_file->GetLocation(), dex_file->GetBaseLocation(), - dex_file->GetLocationChecksum()); + dex_file->GetLocationChecksum(), + dex_file->NumMethodIds()); dex_resolved_classes.first->AddClass(class_ref.type_index); std::vector<ProfileMethodInfo> methods; if (method_str == kClassAllMethods) { @@ -745,6 +793,9 @@ class ProfMan FINAL { std::string method_spec; std::vector<std::string> inline_cache_elems; + // If none of the flags are set, default to hot. + is_hot = is_hot || (!is_hot && !is_startup && !is_post_startup); + std::vector<std::string> method_elems; bool is_missing_types = false; Split(method_str, kProfileParsingInlineChacheSep, &method_elems); @@ -766,7 +817,6 @@ class ProfMan FINAL { return false; } - std::vector<ProfileMethodInfo> pmi; std::vector<ProfileMethodInfo::ProfileInlineCache> inline_caches; if (is_missing_types || !inline_cache_elems.empty()) { uint32_t dex_pc; @@ -783,8 +833,29 @@ class ProfMan FINAL { } inline_caches.emplace_back(dex_pc, is_missing_types, classes); } - pmi.emplace_back(class_ref.dex_file, method_index, inline_caches); - profile->AddMethodsAndClasses(pmi, std::set<DexCacheResolvedClasses>()); + ProfileMethodInfo pmi(class_ref.dex_file, method_index, inline_caches); + if (is_hot) { + profile->AddMethod(pmi); + } + if (is_startup) { + if (!profile->AddSampledMethod(/*is_startup*/ true, + pmi.dex_file->GetLocation(), + pmi.dex_file->GetLocationChecksum(), + method_index, + pmi.dex_file->NumMethodIds())) { + return false; + } + DCHECK(profile->IsStartupOrHotMethod(MethodReference(pmi.dex_file, method_index))); + } + if (is_post_startup) { + if (!profile->AddSampledMethod(/*is_startup*/ false, + pmi.dex_file->GetLocation(), + pmi.dex_file->GetLocationChecksum(), + method_index, + pmi.dex_file->NumMethodIds())) { + return false; + } + } return true; } @@ -959,7 +1030,7 @@ static int profman(int argc, char** argv) { return profman.DumpProfileInfo(); } if (profman.ShouldOnlyDumpClassesAndMethods()) { - return profman.DumpClasses(); + return profman.DumpClassesAndMethods(); } if (profman.ShouldCreateProfile()) { return profman.CreateProfile(); diff --git a/runtime/Android.bp b/runtime/Android.bp index aa7dc65871..c5508e32d4 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -54,6 +54,7 @@ cc_defaults { "compiler_filter.cc", "debugger.cc", "dex_file.cc", + "dex_file_tracking_registrar.cc", "dex_file_annotations.cc", "dex_file_verifier.cc", "dex_instruction.cc", @@ -123,6 +124,7 @@ cc_defaults { "jni_internal.cc", "jobject_comparator.cc", "linear_alloc.cc", + "managed_stack.cc", "mem_map.cc", "memory_region.cc", "method_handles.cc", diff --git a/runtime/arch/arm/context_arm.cc b/runtime/arch/arm/context_arm.cc index 9cbec1e5bc..817dcf5783 100644 --- a/runtime/arch/arm/context_arm.cc +++ b/runtime/arch/arm/context_arm.cc @@ -18,7 +18,7 @@ #include "base/bit_utils.h" #include "quick/quick_method_frame_info.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace arm { diff --git a/runtime/arch/arm/fault_handler_arm.cc b/runtime/arch/arm/fault_handler_arm.cc index 4c15450ff7..b4bca014f4 100644 --- a/runtime/arch/arm/fault_handler_arm.cc +++ b/runtime/arch/arm/fault_handler_arm.cc @@ -25,7 +25,7 @@ #include "base/logging.h" #include "base/macros.h" #include "globals.h" -#include "thread-inl.h" +#include "thread-current-inl.h" // // ARM specific fault handler functions. diff --git a/runtime/arch/arm64/context_arm64.cc b/runtime/arch/arm64/context_arm64.cc index d5d1ec7f07..a8f034eaf4 100644 --- a/runtime/arch/arm64/context_arm64.cc +++ b/runtime/arch/arm64/context_arm64.cc @@ -20,7 +20,7 @@ #include "base/bit_utils.h" #include "quick/quick_method_frame_info.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace arm64 { diff --git a/runtime/arch/arm64/fault_handler_arm64.cc b/runtime/arch/arm64/fault_handler_arm64.cc index dc4e8f389e..0ead732cdd 100644 --- a/runtime/arch/arm64/fault_handler_arm64.cc +++ b/runtime/arch/arm64/fault_handler_arm64.cc @@ -26,7 +26,7 @@ #include "base/macros.h" #include "globals.h" #include "registers_arm64.h" -#include "thread-inl.h" +#include "thread-current-inl.h" extern "C" void art_quick_throw_stack_overflow(); extern "C" void art_quick_throw_null_pointer_exception_from_signal(); diff --git a/runtime/arch/mips/fault_handler_mips.cc b/runtime/arch/mips/fault_handler_mips.cc index 7072a8a613..25e442c3e6 100644 --- a/runtime/arch/mips/fault_handler_mips.cc +++ b/runtime/arch/mips/fault_handler_mips.cc @@ -24,7 +24,7 @@ #include "globals.h" #include "quick_method_frame_info_mips.h" #include "registers_mips.h" -#include "thread-inl.h" +#include "thread-current-inl.h" extern "C" void art_quick_throw_stack_overflow(); extern "C" void art_quick_throw_null_pointer_exception_from_signal(); diff --git a/runtime/arch/mips64/fault_handler_mips64.cc b/runtime/arch/mips64/fault_handler_mips64.cc index f9a92c834e..69d73b09c2 100644 --- a/runtime/arch/mips64/fault_handler_mips64.cc +++ b/runtime/arch/mips64/fault_handler_mips64.cc @@ -25,7 +25,7 @@ #include "globals.h" #include "quick_method_frame_info_mips64.h" #include "registers_mips64.h" -#include "thread-inl.h" +#include "thread-current-inl.h" extern "C" void art_quick_throw_stack_overflow(); extern "C" void art_quick_throw_null_pointer_exception_from_signal(); diff --git a/runtime/arch/x86/fault_handler_x86.cc b/runtime/arch/x86/fault_handler_x86.cc index 7d8abb8cc5..798c500f18 100644 --- a/runtime/arch/x86/fault_handler_x86.cc +++ b/runtime/arch/x86/fault_handler_x86.cc @@ -26,7 +26,7 @@ #include "base/macros.h" #include "base/safe_copy.h" #include "globals.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #if defined(__APPLE__) #define ucontext __darwin_ucontext diff --git a/runtime/arch/x86/thread_x86.cc b/runtime/arch/x86/thread_x86.cc index 241650eaf4..cc8f1fa00e 100644 --- a/runtime/arch/x86/thread_x86.cc +++ b/runtime/arch/x86/thread_x86.cc @@ -22,7 +22,7 @@ #include "asm_support_x86.h" #include "base/enums.h" #include "base/macros.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" #if defined(__APPLE__) diff --git a/runtime/arch/x86_64/thread_x86_64.cc b/runtime/arch/x86_64/thread_x86_64.cc index 553b6569c8..19d25f6990 100644 --- a/runtime/arch/x86_64/thread_x86_64.cc +++ b/runtime/arch/x86_64/thread_x86_64.cc @@ -18,7 +18,7 @@ #include "asm_support_x86_64.h" #include "base/macros.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" #if defined(__linux__) diff --git a/runtime/art_field-inl.h b/runtime/art_field-inl.h index 98002aed31..a8a58e135e 100644 --- a/runtime/art_field-inl.h +++ b/runtime/art_field-inl.h @@ -28,7 +28,7 @@ #include "mirror/dex_cache-inl.h" #include "mirror/object-inl.h" #include "primitive.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "scoped_thread_state_change-inl.h" #include "well_known_classes.h" diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h index 9d0bfdee5d..8567c004fa 100644 --- a/runtime/art_method-inl.h +++ b/runtime/art_method-inl.h @@ -38,7 +38,7 @@ #include "quick/quick_method_frame_info.h" #include "runtime-inl.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils.h" namespace art { diff --git a/runtime/asm_support.h b/runtime/asm_support.h index fce6da4718..1ce7fd33bb 100644 --- a/runtime/asm_support.h +++ b/runtime/asm_support.h @@ -30,6 +30,7 @@ #include "mirror/string.h" #include "utils/dex_cache_arrays_layout.h" #include "runtime.h" +#include "stack.h" #include "thread.h" #endif diff --git a/runtime/atomic.cc b/runtime/atomic.cc index d5ae570c30..07aceb7cfc 100644 --- a/runtime/atomic.cc +++ b/runtime/atomic.cc @@ -17,7 +17,7 @@ #include "atomic.h" #include "base/mutex.h" #include "base/stl_util.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/atomic.h b/runtime/atomic.h index 45c3165b18..25dd1a3a5e 100644 --- a/runtime/atomic.h +++ b/runtime/atomic.h @@ -257,6 +257,13 @@ class PACKED(sizeof(T)) Atomic : public std::atomic<T> { return this->compare_exchange_strong(expected_value, desired_value, std::memory_order_relaxed); } + // Atomically replace the value with desired value if it matches the expected value. Prior writes + // to other memory locations become visible to the threads that do a consume or an acquire on the + // same location. + bool CompareExchangeStrongRelease(T expected_value, T desired_value) { + return this->compare_exchange_strong(expected_value, desired_value, std::memory_order_release); + } + // The same, except it may fail spuriously. bool CompareExchangeWeakRelaxed(T expected_value, T desired_value) { return this->compare_exchange_weak(expected_value, desired_value, std::memory_order_relaxed); diff --git a/runtime/barrier_test.cc b/runtime/barrier_test.cc index f68a5d42e4..25b6925fd8 100644 --- a/runtime/barrier_test.cc +++ b/runtime/barrier_test.cc @@ -22,7 +22,7 @@ #include "common_runtime_test.h" #include "mirror/object_array-inl.h" #include "thread_pool.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { class CheckWaitTask : public Task { diff --git a/runtime/base/arena_allocator.cc b/runtime/base/arena_allocator.cc index 99c310af8c..54b40f28cf 100644 --- a/runtime/base/arena_allocator.cc +++ b/runtime/base/arena_allocator.cc @@ -26,7 +26,7 @@ #include "logging.h" #include "mem_map.h" #include "mutex.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "systrace.h" namespace art { diff --git a/runtime/base/dumpable-inl.h b/runtime/base/dumpable-inl.h index 2cdf083f01..9d7fc39093 100644 --- a/runtime/base/dumpable-inl.h +++ b/runtime/base/dumpable-inl.h @@ -19,7 +19,7 @@ #include "base/dumpable.h" #include "base/mutex.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/base/logging.cc b/runtime/base/logging.cc index 553928d20a..adfd7d323c 100644 --- a/runtime/base/logging.cc +++ b/runtime/base/logging.cc @@ -21,7 +21,7 @@ #include <sstream> #include "base/mutex.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils.h" // Headers for LogMessage::LogLine. diff --git a/runtime/base/mutex-inl.h b/runtime/base/mutex-inl.h index 08b370ec4e..0ac2399a5d 100644 --- a/runtime/base/mutex-inl.h +++ b/runtime/base/mutex-inl.h @@ -194,6 +194,16 @@ inline uint64_t Mutex::GetExclusiveOwnerTid() const { return exclusive_owner_; } +inline void Mutex::AssertExclusiveHeld(const Thread* self) const { + if (kDebugLocking && (gAborting == 0)) { + CHECK(IsExclusiveHeld(self)) << *this; + } +} + +inline void Mutex::AssertHeld(const Thread* self) const { + AssertExclusiveHeld(self); +} + inline bool ReaderWriterMutex::IsExclusiveHeld(const Thread* self) const { DCHECK(self == nullptr || self == Thread::Current()); bool result = (GetExclusiveOwnerTid() == SafeGetTid(self)); @@ -221,6 +231,16 @@ inline uint64_t ReaderWriterMutex::GetExclusiveOwnerTid() const { #endif } +inline void ReaderWriterMutex::AssertExclusiveHeld(const Thread* self) const { + if (kDebugLocking && (gAborting == 0)) { + CHECK(IsExclusiveHeld(self)) << *this; + } +} + +inline void ReaderWriterMutex::AssertWriterHeld(const Thread* self) const { + AssertExclusiveHeld(self); +} + inline void MutatorMutex::TransitionFromRunnableToSuspended(Thread* self) { AssertSharedHeld(self); RegisterAsUnlocked(self); @@ -231,6 +251,19 @@ inline void MutatorMutex::TransitionFromSuspendedToRunnable(Thread* self) { AssertSharedHeld(self); } +inline ReaderMutexLock::ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) + : self_(self), mu_(mu) { + mu_.SharedLock(self_); +} + +inline ReaderMutexLock::~ReaderMutexLock() { + mu_.SharedUnlock(self_); +} + +// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of +// "ReaderMutexLock mu(lock)". +#define ReaderMutexLock(x) static_assert(0, "ReaderMutexLock declaration missing variable name") + } // namespace art #endif // ART_RUNTIME_BASE_MUTEX_INL_H_ diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h index 03ae63a068..e77d8d749d 100644 --- a/runtime/base/mutex.h +++ b/runtime/base/mutex.h @@ -244,15 +244,11 @@ class LOCKABLE Mutex : public BaseMutex { void Unlock(Thread* self) RELEASE() { ExclusiveUnlock(self); } // Is the current thread the exclusive holder of the Mutex. - bool IsExclusiveHeld(const Thread* self) const; + ALWAYS_INLINE bool IsExclusiveHeld(const Thread* self) const; // Assert that the Mutex is exclusively held by the current thread. - void AssertExclusiveHeld(const Thread* self) ASSERT_CAPABILITY(this) { - if (kDebugLocking && (gAborting == 0)) { - CHECK(IsExclusiveHeld(self)) << *this; - } - } - void AssertHeld(const Thread* self) ASSERT_CAPABILITY(this) { AssertExclusiveHeld(self); } + ALWAYS_INLINE void AssertExclusiveHeld(const Thread* self) const ASSERT_CAPABILITY(this); + ALWAYS_INLINE void AssertHeld(const Thread* self) const ASSERT_CAPABILITY(this); // Assert that the Mutex is not held by the current thread. void AssertNotHeldExclusive(const Thread* self) ASSERT_CAPABILITY(!*this) { @@ -349,15 +345,11 @@ class SHARED_LOCKABLE ReaderWriterMutex : public BaseMutex { void ReaderUnlock(Thread* self) RELEASE_SHARED() { SharedUnlock(self); } // Is the current thread the exclusive holder of the ReaderWriterMutex. - bool IsExclusiveHeld(const Thread* self) const; + ALWAYS_INLINE bool IsExclusiveHeld(const Thread* self) const; // Assert the current thread has exclusive access to the ReaderWriterMutex. - void AssertExclusiveHeld(const Thread* self) ASSERT_CAPABILITY(this) { - if (kDebugLocking && (gAborting == 0)) { - CHECK(IsExclusiveHeld(self)) << *this; - } - } - void AssertWriterHeld(const Thread* self) ASSERT_CAPABILITY(this) { AssertExclusiveHeld(self); } + ALWAYS_INLINE void AssertExclusiveHeld(const Thread* self) const ASSERT_CAPABILITY(this); + ALWAYS_INLINE void AssertWriterHeld(const Thread* self) const ASSERT_CAPABILITY(this); // Assert the current thread doesn't have exclusive access to the ReaderWriterMutex. void AssertNotExclusiveHeld(const Thread* self) ASSERT_CAPABILITY(!this) { @@ -517,23 +509,15 @@ class SCOPED_CAPABILITY MutexLock { // construction and releases it upon destruction. class SCOPED_CAPABILITY ReaderMutexLock { public: - ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) ACQUIRE(mu) ALWAYS_INLINE : - self_(self), mu_(mu) { - mu_.SharedLock(self_); - } + ALWAYS_INLINE ReaderMutexLock(Thread* self, ReaderWriterMutex& mu) ACQUIRE(mu); - ~ReaderMutexLock() RELEASE() ALWAYS_INLINE { - mu_.SharedUnlock(self_); - } + ALWAYS_INLINE ~ReaderMutexLock() RELEASE(); private: Thread* const self_; ReaderWriterMutex& mu_; DISALLOW_COPY_AND_ASSIGN(ReaderMutexLock); }; -// Catch bug where variable name is omitted. "ReaderMutexLock (lock);" instead of -// "ReaderMutexLock mu(lock)". -#define ReaderMutexLock(x) static_assert(0, "ReaderMutexLock declaration missing variable name") // Scoped locker/unlocker for a ReaderWriterMutex that acquires write access to mu upon // construction and releases it upon destruction. diff --git a/runtime/base/mutex_test.cc b/runtime/base/mutex_test.cc index 340550f02e..752e77a7c0 100644 --- a/runtime/base/mutex_test.cc +++ b/runtime/base/mutex_test.cc @@ -14,10 +14,10 @@ * limitations under the License. */ -#include "mutex.h" +#include "mutex-inl.h" #include "common_runtime_test.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc index 06e2526294..aaa24317bb 100644 --- a/runtime/base/timing_logger.cc +++ b/runtime/base/timing_logger.cc @@ -25,7 +25,8 @@ #include "base/systrace.h" #include "base/time_utils.h" #include "gc/heap.h" -#include "thread-inl.h" +#include "runtime.h" +#include "thread-current-inl.h" #include <cmath> #include <iomanip> diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h index a955cb5acb..f6c8fa9659 100644 --- a/runtime/check_reference_map_visitor.h +++ b/runtime/check_reference_map_visitor.h @@ -20,6 +20,7 @@ #include "art_method-inl.h" #include "oat_quick_method_header.h" #include "scoped_thread_state_change-inl.h" +#include "stack.h" #include "stack_map.h" namespace art { diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index c169ac0733..c3a8fc5383 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -8949,7 +8949,8 @@ class GetResolvedClassesVisitor : public ClassVisitor { last_dex_file_ = &dex_file; DexCacheResolvedClasses resolved_classes(dex_file.GetLocation(), dex_file.GetBaseLocation(), - dex_file.GetLocationChecksum()); + dex_file.GetLocationChecksum(), + dex_file.NumMethodIds()); last_resolved_classes_ = result_->find(resolved_classes); if (last_resolved_classes_ == result_->end()) { last_resolved_classes_ = result_->insert(resolved_classes).first; diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index b421810113..684a261cca 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -50,7 +50,7 @@ #include "mirror/string-inl.h" #include "handle_scope-inl.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/class_table-inl.h b/runtime/class_table-inl.h index dfe8949134..35fce4063b 100644 --- a/runtime/class_table-inl.h +++ b/runtime/class_table-inl.h @@ -93,7 +93,7 @@ inline mirror::Class* ClassTable::TableSlot::Read() const { if (kReadBarrierOption != kWithoutReadBarrier && before_ptr != after_ptr) { // If another thread raced and updated the reference, do not store the read barrier updated // one. - data_.CompareExchangeStrongRelaxed(before, Encode(after_ptr, MaskHash(before))); + data_.CompareExchangeStrongRelease(before, Encode(after_ptr, MaskHash(before))); } return after_ptr.Ptr(); } @@ -108,7 +108,7 @@ inline void ClassTable::TableSlot::VisitRoot(const Visitor& visitor) const { if (before_ptr != after_ptr) { // If another thread raced and updated the reference, do not store the read barrier updated // one. - data_.CompareExchangeStrongRelaxed(before, Encode(after_ptr, MaskHash(before))); + data_.CompareExchangeStrongRelease(before, Encode(after_ptr, MaskHash(before))); } } diff --git a/runtime/debugger.cc b/runtime/debugger.cc index d0b50fe820..cfa56a5769 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -38,7 +38,7 @@ #include "gc/scoped_gc_critical_section.h" #include "gc/space/large_object_space.h" #include "gc/space/space-inl.h" -#include "handle_scope.h" +#include "handle_scope-inl.h" #include "jdwp/jdwp_priv.h" #include "jdwp/object_registry.h" #include "jni_internal.h" @@ -56,7 +56,7 @@ #include "scoped_thread_state_change-inl.h" #include "ScopedLocalRef.h" #include "ScopedPrimitiveArray.h" -#include "handle_scope-inl.h" +#include "stack.h" #include "thread_list.h" #include "utf.h" #include "well_known_classes.h" diff --git a/runtime/dex_cache_resolved_classes.h b/runtime/dex_cache_resolved_classes.h index bebdf0dbfe..2278b052ed 100644 --- a/runtime/dex_cache_resolved_classes.h +++ b/runtime/dex_cache_resolved_classes.h @@ -30,10 +30,12 @@ class DexCacheResolvedClasses { public: DexCacheResolvedClasses(const std::string& dex_location, const std::string& base_location, - uint32_t location_checksum) + uint32_t location_checksum, + uint32_t num_method_ids) : dex_location_(dex_location), base_location_(base_location), - location_checksum_(location_checksum) {} + location_checksum_(location_checksum), + num_method_ids_(num_method_ids) {} // Only compare the key elements, ignore the resolved classes. int Compare(const DexCacheResolvedClasses& other) const { @@ -69,10 +71,15 @@ class DexCacheResolvedClasses { return classes_; } + size_t NumMethodIds() const { + return num_method_ids_; + } + private: const std::string dex_location_; const std::string base_location_; const uint32_t location_checksum_; + const uint32_t num_method_ids_; // Array of resolved class def indexes. mutable std::unordered_set<dex::TypeIndex> classes_; }; diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc index 1d4507a9d6..78d5c5f4ba 100644 --- a/runtime/dex_file_test.cc +++ b/runtime/dex_file_test.cc @@ -27,7 +27,7 @@ #include "mem_map.h" #include "os.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils.h" namespace art { diff --git a/runtime/dex_file_tracking_registrar.cc b/runtime/dex_file_tracking_registrar.cc new file mode 100644 index 0000000000..cfbca3d00f --- /dev/null +++ b/runtime/dex_file_tracking_registrar.cc @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 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. + */ + +#include "dex_file_tracking_registrar.h" + +// For dex tracking through poisoning. Note: Requires forcing sanitization. This is the reason for +// the ifdefs and early include. +#ifdef ART_DEX_FILE_ACCESS_TRACKING +#ifndef ART_ENABLE_ADDRESS_SANITIZER +#define ART_ENABLE_ADDRESS_SANITIZER +#endif +#endif +#include "base/memory_tool.h" + +#include "base/logging.h" + +namespace art { +namespace dex { +namespace tracking { + +// If true, poison dex files to track accesses. +static constexpr bool kDexFileAccessTracking = +#ifdef ART_DEX_FILE_ACCESS_TRACKING + true; +#else + false; +#endif + +void RegisterDexFile(const DexFile* const dex_file) { + if (kDexFileAccessTracking && dex_file != nullptr) { + LOG(ERROR) << dex_file->GetLocation() + " @ " << std::hex + << reinterpret_cast<uintptr_t>(dex_file->Begin()); + MEMORY_TOOL_MAKE_NOACCESS(dex_file->Begin(), dex_file->Size()); + } +} + +} // namespace tracking +} // namespace dex +} // namespace art diff --git a/runtime/dex_file_tracking_registrar.h b/runtime/dex_file_tracking_registrar.h new file mode 100644 index 0000000000..7d5d78d6df --- /dev/null +++ b/runtime/dex_file_tracking_registrar.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2017 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_FILE_TRACKING_REGISTRAR_H_ +#define ART_RUNTIME_DEX_FILE_TRACKING_REGISTRAR_H_ + +#include "dex_file.h" + +namespace art { +namespace dex { +namespace tracking { + +void RegisterDexFile(const DexFile* const dex_file); + +} // namespace tracking +} // namespace dex +} // namespace art + +#endif // ART_RUNTIME_DEX_FILE_TRACKING_REGISTRAR_H_ diff --git a/runtime/dex_file_verifier_test.cc b/runtime/dex_file_verifier_test.cc index 068e1223e5..0e58e6d564 100644 --- a/runtime/dex_file_verifier_test.cc +++ b/runtime/dex_file_verifier_test.cc @@ -29,7 +29,7 @@ #include "dex_file_types.h" #include "leb128.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils.h" namespace art { diff --git a/runtime/dex_method_iterator_test.cc b/runtime/dex_method_iterator_test.cc index cd8c39096d..e83829bb46 100644 --- a/runtime/dex_method_iterator_test.cc +++ b/runtime/dex_method_iterator_test.cc @@ -20,7 +20,7 @@ #include "common_runtime_test.h" #include "oat_file.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/entrypoints/jni/jni_entrypoints.cc b/runtime/entrypoints/jni/jni_entrypoints.cc index eeb138b295..dd0819ed8f 100644 --- a/runtime/entrypoints/jni/jni_entrypoints.cc +++ b/runtime/entrypoints/jni/jni_entrypoints.cc @@ -42,12 +42,11 @@ extern "C" const void* artFindNativeMethod(Thread* self) { // otherwise we return the address of the method we found. void* native_code = soa.Vm()->FindCodeForNativeMethod(method); if (native_code == nullptr) { - DCHECK(self->IsExceptionPending()); + self->AssertPendingException(); return nullptr; - } else { - // Register so that future calls don't come here - return method->RegisterNative(native_code, false); } + // Register so that future calls don't come here + return method->RegisterNative(native_code, false); } } // namespace art diff --git a/runtime/entrypoints/quick/callee_save_frame.h b/runtime/entrypoints/quick/callee_save_frame.h index df37f9586f..c94bf4a318 100644 --- a/runtime/entrypoints/quick/callee_save_frame.h +++ b/runtime/entrypoints/quick/callee_save_frame.h @@ -21,7 +21,7 @@ #include "base/enums.h" #include "base/mutex.h" #include "runtime.h" -#include "thread-inl.h" +#include "thread.h" // Specific frame size code is in architecture-specific files. We include this to compile-time // specialize the code. @@ -46,13 +46,6 @@ class ScopedQuickEntrypointChecks { } } - ScopedQuickEntrypointChecks() REQUIRES_SHARED(Locks::mutator_lock_) - : self_(kIsDebugBuild ? Thread::Current() : nullptr), exit_check_(kIsDebugBuild) { - if (kIsDebugBuild) { - TestsOnEntry(); - } - } - ~ScopedQuickEntrypointChecks() REQUIRES_SHARED(Locks::mutator_lock_) { if (exit_check_) { TestsOnExit(); diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc index 81560ccbaf..aa1ebb7ee7 100644 --- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc @@ -21,7 +21,7 @@ #include "instrumentation.h" #include "mirror/object-inl.h" #include "runtime.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index 2b349e39a0..90231e289e 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -18,6 +18,7 @@ #include "base/enums.h" #include "callee_save_frame.h" #include "common_throws.h" +#include "debugger.h" #include "dex_file-inl.h" #include "dex_instruction-inl.h" #include "entrypoints/entrypoint_utils-inl.h" @@ -40,7 +41,7 @@ #include "runtime.h" #include "scoped_thread_state_change-inl.h" #include "stack.h" -#include "debugger.h" +#include "thread-inl.h" #include "well_known_classes.h" namespace art { diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc index 5594f4dfc7..fd0cd5f0b2 100644 --- a/runtime/fault_handler.cc +++ b/runtime/fault_handler.cc @@ -27,7 +27,7 @@ #include "mirror/object_reference.h" #include "oat_quick_method_header.h" #include "sigchain.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "verify_object-inl.h" namespace art { diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc index c416b9cc3d..57c290ea94 100644 --- a/runtime/gc/accounting/mod_union_table.cc +++ b/runtime/gc/accounting/mod_union_table.cc @@ -28,7 +28,7 @@ #include "mirror/object-inl.h" #include "mirror/object-refvisitor-inl.h" #include "space_bitmap-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace gc { diff --git a/runtime/gc/accounting/mod_union_table_test.cc b/runtime/gc/accounting/mod_union_table_test.cc index 48a8742cc8..e5b8ea5609 100644 --- a/runtime/gc/accounting/mod_union_table_test.cc +++ b/runtime/gc/accounting/mod_union_table_test.cc @@ -21,7 +21,7 @@ #include "gc/space/space-inl.h" #include "mirror/array-inl.h" #include "space_bitmap-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" namespace art { diff --git a/runtime/gc/allocator/rosalloc.cc b/runtime/gc/allocator/rosalloc.cc index 35a251fda8..d5d3540b1f 100644 --- a/runtime/gc/allocator/rosalloc.cc +++ b/runtime/gc/allocator/rosalloc.cc @@ -30,7 +30,7 @@ #include "mirror/class-inl.h" #include "mirror/object.h" #include "mirror/object-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" namespace art { diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc index ef843c6650..c0d648117c 100644 --- a/runtime/gc/collector/concurrent_copying.cc +++ b/runtime/gc/collector/concurrent_copying.cc @@ -359,7 +359,7 @@ class ConcurrentCopying::ThreadFlipVisitor : public Closure, public RootVisitor ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_); // We can use the non-CAS VisitRoots functions below because we update thread-local GC roots // only. - thread->VisitRoots(this); + thread->VisitRoots(this, kVisitRootFlagAllRoots); concurrent_copying_->GetBarrier().Pass(self); } @@ -2086,8 +2086,11 @@ inline void ConcurrentCopying::Process(mirror::Object* obj, MemberOffset offset) // It was updated by the mutator. break; } - } while (!obj->CasFieldWeakRelaxedObjectWithoutWriteBarrier< - false, false, kVerifyNone>(offset, expected_ref, new_ref)); + // Use release cas to make sure threads reading the reference see contents of copied objects. + } while (!obj->CasFieldWeakReleaseObjectWithoutWriteBarrier<false, false, kVerifyNone>( + offset, + expected_ref, + new_ref)); } // Process some roots. diff --git a/runtime/gc/collector/garbage_collector.cc b/runtime/gc/collector/garbage_collector.cc index 1e4196b1ac..c5a341fc80 100644 --- a/runtime/gc/collector/garbage_collector.cc +++ b/runtime/gc/collector/garbage_collector.cc @@ -31,7 +31,8 @@ #include "gc/heap.h" #include "gc/space/large_object_space.h" #include "gc/space/space-inl.h" -#include "thread-inl.h" +#include "runtime.h" +#include "thread-current-inl.h" #include "thread_list.h" #include "utils.h" diff --git a/runtime/gc/collector/immune_spaces_test.cc b/runtime/gc/collector/immune_spaces_test.cc index acb4f575c8..9823708606 100644 --- a/runtime/gc/collector/immune_spaces_test.cc +++ b/runtime/gc/collector/immune_spaces_test.cc @@ -21,7 +21,7 @@ #include "gc/space/image_space.h" #include "gc/space/space-inl.h" #include "oat_file.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace mirror { diff --git a/runtime/gc/collector/mark_compact.cc b/runtime/gc/collector/mark_compact.cc index 9d3d950a0f..aef98dee58 100644 --- a/runtime/gc/collector/mark_compact.cc +++ b/runtime/gc/collector/mark_compact.cc @@ -32,7 +32,7 @@ #include "mirror/object-refvisitor-inl.h" #include "runtime.h" #include "stack.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" namespace art { diff --git a/runtime/gc/collector/mark_sweep.cc b/runtime/gc/collector/mark_sweep.cc index f591cf09ca..fb82b4d270 100644 --- a/runtime/gc/collector/mark_sweep.cc +++ b/runtime/gc/collector/mark_sweep.cc @@ -42,7 +42,7 @@ #include "mirror/object-inl.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" namespace art { @@ -1141,7 +1141,7 @@ class MarkSweep::CheckpointMarkThreadRoots : public Closure, public RootVisitor Thread* const self = Thread::Current(); CHECK(thread == self || thread->IsSuspended() || thread->GetState() == kWaitingPerformingGc) << thread->GetState() << " thread " << thread << " self " << self; - thread->VisitRoots(this); + thread->VisitRoots(this, kVisitRootFlagAllRoots); if (revoke_ros_alloc_thread_local_buffers_at_checkpoint_) { ScopedTrace trace2("RevokeRosAllocThreadLocalBuffers"); mark_sweep_->GetHeap()->RevokeRosAllocThreadLocalBuffers(thread); diff --git a/runtime/gc/collector/partial_mark_sweep.cc b/runtime/gc/collector/partial_mark_sweep.cc index 984779484e..f6ca867e69 100644 --- a/runtime/gc/collector/partial_mark_sweep.cc +++ b/runtime/gc/collector/partial_mark_sweep.cc @@ -19,7 +19,7 @@ #include "gc/heap.h" #include "gc/space/space.h" #include "partial_mark_sweep.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace gc { diff --git a/runtime/gc/collector/sticky_mark_sweep.cc b/runtime/gc/collector/sticky_mark_sweep.cc index 428e387c21..98fdfac17b 100644 --- a/runtime/gc/collector/sticky_mark_sweep.cc +++ b/runtime/gc/collector/sticky_mark_sweep.cc @@ -21,7 +21,8 @@ #include "gc/heap.h" #include "gc/space/large_object_space.h" #include "gc/space/space-inl.h" -#include "thread-inl.h" +#include "runtime.h" +#include "thread-current-inl.h" namespace art { namespace gc { diff --git a/runtime/gc/scoped_gc_critical_section.cc b/runtime/gc/scoped_gc_critical_section.cc index f937d2c778..2976dd0252 100644 --- a/runtime/gc/scoped_gc_critical_section.cc +++ b/runtime/gc/scoped_gc_critical_section.cc @@ -19,7 +19,7 @@ #include "gc/collector_type.h" #include "gc/heap.h" #include "runtime.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace gc { diff --git a/runtime/gc/space/large_object_space.cc b/runtime/gc/space/large_object_space.cc index 0f856b8ecc..4597a96ce2 100644 --- a/runtime/gc/space/large_object_space.cc +++ b/runtime/gc/space/large_object_space.cc @@ -31,7 +31,7 @@ #include "os.h" #include "scoped_thread_state_change-inl.h" #include "space-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace gc { diff --git a/runtime/gc/space/region_space-inl.h b/runtime/gc/space/region_space-inl.h index 61161602ce..fc24fc2974 100644 --- a/runtime/gc/space/region_space-inl.h +++ b/runtime/gc/space/region_space-inl.h @@ -18,7 +18,7 @@ #define ART_RUNTIME_GC_SPACE_REGION_SPACE_INL_H_ #include "region_space.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace gc { diff --git a/runtime/gc/space/space.cc b/runtime/gc/space/space.cc index 4a078b8f49..74ce273abf 100644 --- a/runtime/gc/space/space.cc +++ b/runtime/gc/space/space.cc @@ -21,7 +21,7 @@ #include "gc/accounting/space_bitmap-inl.h" #include "gc/heap.h" #include "runtime.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace gc { diff --git a/runtime/gc/space/zygote_space.cc b/runtime/gc/space/zygote_space.cc index bbfcb31ab1..fddb3f2dd2 100644 --- a/runtime/gc/space/zygote_space.cc +++ b/runtime/gc/space/zygote_space.cc @@ -16,10 +16,12 @@ #include "zygote_space.h" +#include "base/mutex-inl.h" #include "gc/accounting/card_table-inl.h" #include "gc/accounting/space_bitmap-inl.h" #include "gc/heap.h" -#include "thread-inl.h" +#include "runtime.h" +#include "thread-current-inl.h" #include "utils.h" namespace art { diff --git a/runtime/gc/task_processor_test.cc b/runtime/gc/task_processor_test.cc index f1d26d9a41..5a75b37b67 100644 --- a/runtime/gc/task_processor_test.cc +++ b/runtime/gc/task_processor_test.cc @@ -18,7 +18,7 @@ #include "common_runtime_test.h" #include "task_processor.h" #include "thread_pool.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace gc { diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h index 492d4b4bd9..d091e7f371 100644 --- a/runtime/handle_scope-inl.h +++ b/runtime/handle_scope-inl.h @@ -22,7 +22,7 @@ #include "base/mutex.h" #include "handle.h" #include "obj_ptr-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "verify_object.h" namespace art { diff --git a/runtime/imtable_test.cc b/runtime/imtable_test.cc index 17149dfe44..d482183d86 100644 --- a/runtime/imtable_test.cc +++ b/runtime/imtable_test.cc @@ -29,7 +29,7 @@ #include "mirror/class_loader.h" #include "handle_scope-inl.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/indirect_reference_table.cc b/runtime/indirect_reference_table.cc index c852d5af3a..cff3ea7ecd 100644 --- a/runtime/indirect_reference_table.cc +++ b/runtime/indirect_reference_table.cc @@ -34,6 +34,9 @@ namespace art { static constexpr bool kDumpStackOnNonLocalReference = false; static constexpr bool kDebugIRT = false; +// Maximum table size we allow. +static constexpr size_t kMaxTableSizeInBytes = 128 * MB; + const char* GetIndirectRefKindString(const IndirectRefKind& kind) { switch (kind) { case kHandleScopeOrInvalid: @@ -71,6 +74,9 @@ IndirectReferenceTable::IndirectReferenceTable(size_t max_count, CHECK(error_msg != nullptr); CHECK_NE(desired_kind, kHandleScopeOrInvalid); + // Overflow and maximum check. + CHECK_LE(max_count, kMaxTableSizeInBytes / sizeof(IrtEntry)); + const size_t table_bytes = max_count * sizeof(IrtEntry); table_mem_map_.reset(MemMap::MapAnonymous("indirect ref table", nullptr, table_bytes, PROT_READ | PROT_WRITE, false, false, error_msg)); @@ -203,6 +209,13 @@ static inline void CheckHoleCount(IrtEntry* table, bool IndirectReferenceTable::Resize(size_t new_size, std::string* error_msg) { CHECK_GT(new_size, max_entries_); + constexpr size_t kMaxEntries = kMaxTableSizeInBytes / sizeof(IrtEntry); + if (new_size > kMaxEntries) { + *error_msg = android::base::StringPrintf("Requested size exceeds maximum: %zu", new_size); + return false; + } + // Note: the above check also ensures that there is no overflow below. + const size_t table_bytes = new_size * sizeof(IrtEntry); std::unique_ptr<MemMap> new_map(MemMap::MapAnonymous("indirect ref table", nullptr, @@ -247,6 +260,14 @@ IndirectRef IndirectReferenceTable::Add(IRTSegmentState previous_state, } // Try to double space. + if (std::numeric_limits<size_t>::max() / 2 < max_entries_) { + LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow " + << "(max=" << max_entries_ << ")" << std::endl + << MutatorLockedDumpable<IndirectReferenceTable>(*this) + << " Resizing failed: exceeds size_t"; + UNREACHABLE(); + } + std::string error_msg; if (!Resize(max_entries_ * 2, &error_msg)) { LOG(FATAL) << "JNI ERROR (app bug): " << kind_ << " table overflow " @@ -453,4 +474,38 @@ void IndirectReferenceTable::SetSegmentState(IRTSegmentState new_state) { segment_state_ = new_state; } +bool IndirectReferenceTable::EnsureFreeCapacity(size_t free_capacity, std::string* error_msg) { + size_t top_index = segment_state_.top_index; + if (top_index < max_entries_ && top_index + free_capacity <= max_entries_) { + return true; + } + + // We're only gonna do a simple best-effort here, ensuring the asked-for capacity at the end. + if (resizable_ == ResizableCapacity::kNo) { + *error_msg = "Table is not resizable"; + return false; + } + + // Try to increase the table size. + + // Would this overflow? + if (std::numeric_limits<size_t>::max() - free_capacity < top_index) { + *error_msg = "Cannot resize table, overflow."; + return false; + } + + if (!Resize(top_index + free_capacity, error_msg)) { + LOG(WARNING) << "JNI ERROR: Unable to reserve space in EnsureFreeCapacity (" << free_capacity + << "): " << std::endl + << MutatorLockedDumpable<IndirectReferenceTable>(*this) + << " Resizing failed: " << *error_msg; + return false; + } + return true; +} + +size_t IndirectReferenceTable::FreeCapacity() { + return max_entries_ - segment_state_.top_index; +} + } // namespace art diff --git a/runtime/indirect_reference_table.h b/runtime/indirect_reference_table.h index 7e452a270a..79d620126c 100644 --- a/runtime/indirect_reference_table.h +++ b/runtime/indirect_reference_table.h @@ -285,6 +285,13 @@ class IndirectReferenceTable { return segment_state_.top_index; } + // Ensure that at least free_capacity elements are available, or return false. + bool EnsureFreeCapacity(size_t free_capacity, std::string* error_msg) + REQUIRES_SHARED(Locks::mutator_lock_); + // See implementation of EnsureFreeCapacity. We'll only state here how much is trivially free, + // without recovering holes. Thus this is a conservative estimate. + size_t FreeCapacity() REQUIRES_SHARED(Locks::mutator_lock_); + // Note IrtIterator does not have a read barrier as it's used to visit roots. IrtIterator begin() { return IrtIterator(table_, 0, Capacity()); diff --git a/runtime/instrumentation_test.cc b/runtime/instrumentation_test.cc index 7f9f04f435..9926ee7386 100644 --- a/runtime/instrumentation_test.cc +++ b/runtime/instrumentation_test.cc @@ -27,7 +27,7 @@ #include "runtime.h" #include "scoped_thread_state_change-inl.h" #include "thread_list.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace instrumentation { diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc index d2f5232de1..4bc0f2fa12 100644 --- a/runtime/interpreter/interpreter.cc +++ b/runtime/interpreter/interpreter.cc @@ -22,15 +22,16 @@ #include "interpreter_common.h" #include "interpreter_mterp_impl.h" #include "interpreter_switch_impl.h" +#include "jit/jit.h" +#include "jit/jit_code_cache.h" #include "jvalue-inl.h" #include "mirror/string-inl.h" +#include "mterp/mterp.h" #include "scoped_thread_state_change-inl.h" #include "ScopedLocalRef.h" #include "stack.h" +#include "thread-inl.h" #include "unstarted_runtime.h" -#include "mterp/mterp.h" -#include "jit/jit.h" -#include "jit/jit_code_cache.h" namespace art { namespace interpreter { diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc index 084cb4218f..d06ac23d3c 100644 --- a/runtime/interpreter/interpreter_common.cc +++ b/runtime/interpreter/interpreter_common.cc @@ -32,6 +32,7 @@ #include "reflection.h" #include "reflection-inl.h" #include "stack.h" +#include "thread-inl.h" #include "well_known_classes.h" namespace art { diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc index 96934bc0ca..152cce4c60 100644 --- a/runtime/interpreter/unstarted_runtime.cc +++ b/runtime/interpreter/unstarted_runtime.cc @@ -50,7 +50,7 @@ #include "mirror/string-inl.h" #include "nth_caller_visitor.h" #include "reflection.h" -#include "thread.h" +#include "thread-inl.h" #include "transaction.h" #include "well_known_classes.h" #include "zip_archive.h" diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc index bd0f8420aa..41376335a5 100644 --- a/runtime/java_vm_ext.cc +++ b/runtime/java_vm_ext.cc @@ -22,7 +22,7 @@ #include "art_method-inl.h" #include "base/dumpable.h" -#include "base/mutex.h" +#include "base/mutex-inl.h" #include "base/stl_util.h" #include "base/systrace.h" #include "check_jni.h" @@ -145,19 +145,24 @@ class SharedLibrary { return needs_native_bridge_; } - void* FindSymbol(const std::string& symbol_name, const char* shorty = nullptr) { + // No mutator lock since dlsym may block for a while if another thread is doing dlopen. + void* FindSymbol(const std::string& symbol_name, const char* shorty = nullptr) + REQUIRES(!Locks::mutator_lock_) { return NeedsNativeBridge() ? FindSymbolWithNativeBridge(symbol_name.c_str(), shorty) : FindSymbolWithoutNativeBridge(symbol_name.c_str()); } - void* FindSymbolWithoutNativeBridge(const std::string& symbol_name) { + // No mutator lock since dlsym may block for a while if another thread is doing dlopen. + void* FindSymbolWithoutNativeBridge(const std::string& symbol_name) + REQUIRES(!Locks::mutator_lock_) { CHECK(!NeedsNativeBridge()); return dlsym(handle_, symbol_name.c_str()); } - void* FindSymbolWithNativeBridge(const std::string& symbol_name, const char* shorty) { + void* FindSymbolWithNativeBridge(const std::string& symbol_name, const char* shorty) + REQUIRES(!Locks::mutator_lock_) { CHECK(NeedsNativeBridge()); uint32_t len = 0; @@ -236,8 +241,8 @@ class Libraries { } // See section 11.3 "Linking Native Methods" of the JNI spec. - void* FindNativeMethod(ArtMethod* m, std::string& detail) - REQUIRES(Locks::jni_libraries_lock_) + void* FindNativeMethod(Thread* self, ArtMethod* m, std::string& detail) + REQUIRES(!Locks::jni_libraries_lock_) REQUIRES_SHARED(Locks::mutator_lock_) { std::string jni_short_name(m->JniShortName()); std::string jni_long_name(m->JniLongName()); @@ -246,6 +251,34 @@ class Libraries { void* const declaring_class_loader_allocator = Runtime::Current()->GetClassLinker()->GetAllocatorForClassLoader(declaring_class_loader); CHECK(declaring_class_loader_allocator != nullptr); + // TODO: Avoid calling GetShorty here to prevent dirtying dex pages? + const char* shorty = m->GetShorty(); + { + // Go to suspended since dlsym may block for a long time if other threads are using dlopen. + ScopedThreadSuspension sts(self, kNative); + void* native_code = FindNativeMethodInternal(self, + declaring_class_loader_allocator, + shorty, + jni_short_name, + jni_long_name); + if (native_code != nullptr) { + return native_code; + } + } + detail += "No implementation found for "; + detail += m->PrettyMethod(); + detail += " (tried " + jni_short_name + " and " + jni_long_name + ")"; + return nullptr; + } + + void* FindNativeMethodInternal(Thread* self, + void* declaring_class_loader_allocator, + const char* shorty, + const std::string& jni_short_name, + const std::string& jni_long_name) + REQUIRES(!Locks::jni_libraries_lock_) + REQUIRES(!Locks::mutator_lock_) { + MutexLock mu(self, *Locks::jni_libraries_lock_); for (const auto& lib : libraries_) { SharedLibrary* const library = lib.second; // Use the allocator address for class loader equality to avoid unnecessary weak root decode. @@ -254,22 +287,17 @@ class Libraries { continue; } // Try the short name then the long name... - const char* shorty = library->NeedsNativeBridge() - ? m->GetShorty() - : nullptr; - void* fn = library->FindSymbol(jni_short_name, shorty); + const char* arg_shorty = library->NeedsNativeBridge() ? shorty : nullptr; + void* fn = library->FindSymbol(jni_short_name, arg_shorty); if (fn == nullptr) { - fn = library->FindSymbol(jni_long_name, shorty); + fn = library->FindSymbol(jni_long_name, arg_shorty); } if (fn != nullptr) { - VLOG(jni) << "[Found native code for " << m->PrettyMethod() + VLOG(jni) << "[Found native code for " << jni_long_name << " in \"" << library->GetPath() << "\"]"; return fn; } } - detail += "No implementation found for "; - detail += m->PrettyMethod(); - detail += " (tried " + jni_short_name + " and " + jni_long_name + ")"; return nullptr; } @@ -277,18 +305,17 @@ class Libraries { void UnloadNativeLibraries() REQUIRES(!Locks::jni_libraries_lock_) REQUIRES_SHARED(Locks::mutator_lock_) { - ScopedObjectAccessUnchecked soa(Thread::Current()); + Thread* const self = Thread::Current(); std::vector<SharedLibrary*> unload_libraries; { - MutexLock mu(soa.Self(), *Locks::jni_libraries_lock_); + MutexLock mu(self, *Locks::jni_libraries_lock_); for (auto it = libraries_.begin(); it != libraries_.end(); ) { SharedLibrary* const library = it->second; // If class loader is null then it was unloaded, call JNI_OnUnload. const jweak class_loader = library->GetClassLoader(); // If class_loader is a null jobject then it is the boot class loader. We should not unload // the native libraries of the boot class loader. - if (class_loader != nullptr && - soa.Self()->IsJWeakCleared(class_loader)) { + if (class_loader != nullptr && self->IsJWeakCleared(class_loader)) { unload_libraries.push_back(library); it = libraries_.erase(it); } else { @@ -296,6 +323,7 @@ class Libraries { } } } + ScopedThreadSuspension sts(self, kNative); // Do this without holding the jni libraries lock to prevent possible deadlocks. typedef void (*JNI_OnUnloadFn)(JavaVM*, void*); for (auto library : unload_libraries) { @@ -305,7 +333,7 @@ class Libraries { } else { VLOG(jni) << "[JNI_OnUnload found for \"" << library->GetPath() << "\"]: Calling..."; JNI_OnUnloadFn jni_on_unload = reinterpret_cast<JNI_OnUnloadFn>(sym); - jni_on_unload(soa.Vm(), nullptr); + jni_on_unload(self->GetJniEnv()->vm, nullptr); } delete library; } @@ -956,12 +984,8 @@ void* JavaVMExt::FindCodeForNativeMethod(ArtMethod* m) { // If this is a static method, it could be called before the class has been initialized. CHECK(c->IsInitializing()) << c->GetStatus() << " " << m->PrettyMethod(); std::string detail; - void* native_method; - Thread* self = Thread::Current(); - { - MutexLock mu(self, *Locks::jni_libraries_lock_); - native_method = libraries_->FindNativeMethod(m, detail); - } + Thread* const self = Thread::Current(); + void* native_method = libraries_->FindNativeMethod(self, m, detail); if (native_method == nullptr) { // Lookup JNI native methods from native TI Agent libraries. See runtime/ti/agent.h for more // information. Agent libraries are searched for native methods after all jni libraries. diff --git a/runtime/jdwp/jdwp_adb.cc b/runtime/jdwp/jdwp_adb.cc index 0aa04c10ca..ede4f9edb7 100644 --- a/runtime/jdwp/jdwp_adb.cc +++ b/runtime/jdwp/jdwp_adb.cc @@ -24,7 +24,7 @@ #include "base/logging.h" #include "jdwp/jdwp_priv.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #ifdef ART_TARGET_ANDROID #include "cutils/sockets.h" diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc index e8a9904dc6..618332b7ef 100644 --- a/runtime/jdwp/jdwp_handler.cc +++ b/runtime/jdwp/jdwp_handler.cc @@ -33,7 +33,7 @@ #include "jdwp/jdwp_priv.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils.h" namespace art { diff --git a/runtime/jit/debugger_interface.cc b/runtime/jit/debugger_interface.cc index ae0004426d..135d9b1f51 100644 --- a/runtime/jit/debugger_interface.cc +++ b/runtime/jit/debugger_interface.cc @@ -18,7 +18,7 @@ #include "base/logging.h" #include "base/mutex.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread.h" #include <unordered_map> diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc index ae474da7c0..969a5708c4 100644 --- a/runtime/jit/jit.cc +++ b/runtime/jit/jit.cc @@ -32,7 +32,9 @@ #include "profile_saver.h" #include "runtime.h" #include "runtime_options.h" +#include "stack.h" #include "stack_map.h" +#include "thread-inl.h" #include "thread_list.h" #include "utils.h" diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc index fdac24e5a0..388a51751e 100644 --- a/runtime/jit/jit_code_cache.cc +++ b/runtime/jit/jit_code_cache.cc @@ -34,7 +34,9 @@ #include "linear_alloc.h" #include "mem_map.h" #include "oat_file-inl.h" +#include "oat_quick_method_header.h" #include "scoped_thread_state_change-inl.h" +#include "stack.h" #include "thread_list.h" namespace art { diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h index 612d06ba1c..eea2771500 100644 --- a/runtime/jit/jit_code_cache.h +++ b/runtime/jit/jit_code_cache.h @@ -39,6 +39,7 @@ namespace art { class ArtMethod; class LinearAlloc; class InlineCache; +class OatQuickMethodHeader; class ProfilingInfo; namespace jit { diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc index 86c15e6227..9c039e2270 100644 --- a/runtime/jit/profile_compilation_info.cc +++ b/runtime/jit/profile_compilation_info.cc @@ -49,7 +49,7 @@ namespace art { const uint8_t ProfileCompilationInfo::kProfileMagic[] = { 'p', 'r', 'o', '\0' }; // Last profile version: Instead of method index, put the difference with the last // method's index. -const uint8_t ProfileCompilationInfo::kProfileVersion[] = { '0', '0', '7', '\0' }; +const uint8_t ProfileCompilationInfo::kProfileVersion[] = { '0', '0', '8', '\0' }; static constexpr uint16_t kMaxDexFileKeyLength = PATH_MAX; @@ -132,6 +132,33 @@ std::string ProfileCompilationInfo::GetProfileDexFileKey(const std::string& dex_ } } +bool ProfileCompilationInfo::AddSampledMethod(bool startup, + const std::string& dex_location, + uint32_t checksum, + uint16_t method_idx, + uint32_t num_method_ids) { + DexFileData* data = GetOrAddDexFileData(GetProfileDexFileKey(dex_location), + checksum, + num_method_ids); + if (data == nullptr) { + return false; + } + data->AddSampledMethod(startup, method_idx); + return true; +} + +bool ProfileCompilationInfo::AddSampledMethods(bool startup, + std::vector<MethodReference>& methods) { + for (const MethodReference& ref : methods) { + DexFileData* data = GetOrAddDexFileData(ref.dex_file); + if (data == nullptr) { + return false; + } + data->AddSampledMethod(startup, ref.dex_method_index); + } + return true; +} + bool ProfileCompilationInfo::AddMethodsAndClasses( const std::vector<ProfileMethodInfo>& methods, const std::set<DexCacheResolvedClasses>& resolved_classes) { @@ -252,7 +279,7 @@ static void AddUintToBuffer(std::vector<uint8_t>* buffer, T value) { static constexpr size_t kLineHeaderSize = 2 * sizeof(uint16_t) + // class_set.size + dex_location.size - 2 * sizeof(uint32_t); // method_map.size + checksum + 3 * sizeof(uint32_t); // method_map.size + checksum + num_method_ids /** * Serialization format: @@ -297,7 +324,8 @@ bool ProfileCompilationInfo::Save(int fd) { required_capacity += kLineHeaderSize + dex_data.profile_key.size() + sizeof(uint16_t) * dex_data.class_set.size() + - methods_region_size; + methods_region_size + + dex_data.bitmap_storage.size(); } if (required_capacity > kProfileSizeErrorThresholdInBytes) { LOG(ERROR) << "Profile data size exceeds " @@ -335,10 +363,12 @@ bool ProfileCompilationInfo::Save(int fd) { DCHECK_LE(dex_data.profile_key.size(), std::numeric_limits<uint16_t>::max()); DCHECK_LE(dex_data.class_set.size(), std::numeric_limits<uint16_t>::max()); + // Write profile line header. AddUintToBuffer(&buffer, static_cast<uint16_t>(dex_data.profile_key.size())); AddUintToBuffer(&buffer, static_cast<uint16_t>(dex_data.class_set.size())); AddUintToBuffer(&buffer, methods_region_size); // uint32_t AddUintToBuffer(&buffer, dex_data.checksum); // uint32_t + AddUintToBuffer(&buffer, dex_data.num_method_ids); // uint32_t AddStringToBuffer(&buffer, dex_data.profile_key); @@ -362,6 +392,10 @@ bool ProfileCompilationInfo::Save(int fd) { last_class_index = class_id.index_; AddUintToBuffer(&buffer, diff_with_last_class_index); } + + buffer.insert(buffer.end(), + dex_data.bitmap_storage.begin(), + dex_data.bitmap_storage.end()); } uint32_t output_size = 0; @@ -476,7 +510,8 @@ void ProfileCompilationInfo::GroupClassesByDex( ProfileCompilationInfo::DexFileData* ProfileCompilationInfo::GetOrAddDexFileData( const std::string& profile_key, - uint32_t checksum) { + uint32_t checksum, + uint32_t num_method_ids) { const auto profile_index_it = profile_key_map_.FindOrAdd(profile_key, profile_key_map_.size()); if (profile_key_map_.size() > std::numeric_limits<uint8_t>::max()) { // Allow only 255 dex files to be profiled. This allows us to save bytes @@ -492,7 +527,11 @@ ProfileCompilationInfo::DexFileData* ProfileCompilationInfo::GetOrAddDexFileData if (info_.size() <= profile_index) { // This is a new addition. Add it to the info_ array. DexFileData* dex_file_data = new (&arena_) DexFileData( - &arena_, profile_key, checksum, profile_index); + &arena_, + profile_key, + checksum, + profile_index, + num_method_ids); info_.push_back(dex_file_data); } DexFileData* result = info_[profile_index]; @@ -500,6 +539,7 @@ ProfileCompilationInfo::DexFileData* ProfileCompilationInfo::GetOrAddDexFileData // This should always be the case since since the cache map is managed by ProfileCompilationInfo. DCHECK_EQ(profile_key, result->profile_key); DCHECK_EQ(profile_index, result->profile_index); + DCHECK_EQ(num_method_ids, result->num_method_ids); // Check that the checksum matches. // This may different if for example the dex file was updated and @@ -528,7 +568,7 @@ const ProfileCompilationInfo::DexFileData* ProfileCompilationInfo::FindDexData( bool ProfileCompilationInfo::AddResolvedClasses(const DexCacheResolvedClasses& classes) { const std::string dex_location = GetProfileDexFileKey(classes.GetDexLocation()); const uint32_t checksum = classes.GetLocationChecksum(); - DexFileData* const data = GetOrAddDexFileData(dex_location, checksum); + DexFileData* const data = GetOrAddDexFileData(dex_location, checksum, classes.NumMethodIds()); if (data == nullptr) { return false; } @@ -538,15 +578,23 @@ bool ProfileCompilationInfo::AddResolvedClasses(const DexCacheResolvedClasses& c bool ProfileCompilationInfo::AddMethodIndex(const std::string& dex_location, uint32_t dex_checksum, - uint16_t method_index) { - return AddMethod(dex_location, dex_checksum, method_index, OfflineProfileMethodInfo(nullptr)); + uint16_t method_index, + uint32_t num_method_ids) { + return AddMethod(dex_location, + dex_checksum, + method_index, + num_method_ids, + OfflineProfileMethodInfo(nullptr)); } bool ProfileCompilationInfo::AddMethod(const std::string& dex_location, uint32_t dex_checksum, uint16_t method_index, + uint32_t num_method_ids, const OfflineProfileMethodInfo& pmi) { - DexFileData* const data = GetOrAddDexFileData(GetProfileDexFileKey(dex_location), dex_checksum); + DexFileData* const data = GetOrAddDexFileData(GetProfileDexFileKey(dex_location), + dex_checksum, + num_method_ids); if (data == nullptr) { // checksum mismatch return false; } @@ -579,7 +627,8 @@ bool ProfileCompilationInfo::AddMethod(const std::string& dex_location, const DexReference& dex_ref = pmi.dex_references[class_ref.dex_profile_index]; DexFileData* class_dex_data = GetOrAddDexFileData( GetProfileDexFileKey(dex_ref.dex_location), - dex_ref.dex_checksum); + dex_ref.dex_checksum, + dex_ref.num_method_ids); if (class_dex_data == nullptr) { // checksum mismatch return false; } @@ -590,9 +639,7 @@ bool ProfileCompilationInfo::AddMethod(const std::string& dex_location, } bool ProfileCompilationInfo::AddMethod(const ProfileMethodInfo& pmi) { - DexFileData* const data = GetOrAddDexFileData( - GetProfileDexFileKey(pmi.dex_file->GetLocation()), - pmi.dex_file->GetLocationChecksum()); + DexFileData* const data = GetOrAddDexFileData(pmi.dex_file); if (data == nullptr) { // checksum mismatch return false; } @@ -604,9 +651,7 @@ bool ProfileCompilationInfo::AddMethod(const ProfileMethodInfo& pmi) { continue; } for (const TypeReference& class_ref : cache.classes) { - DexFileData* class_dex_data = GetOrAddDexFileData( - GetProfileDexFileKey(class_ref.dex_file->GetLocation()), - class_ref.dex_file->GetLocationChecksum()); + DexFileData* class_dex_data = GetOrAddDexFileData(class_ref.dex_file); if (class_dex_data == nullptr) { // checksum mismatch return false; } @@ -623,8 +668,9 @@ bool ProfileCompilationInfo::AddMethod(const ProfileMethodInfo& pmi) { bool ProfileCompilationInfo::AddClassIndex(const std::string& dex_location, uint32_t checksum, - dex::TypeIndex type_idx) { - DexFileData* const data = GetOrAddDexFileData(dex_location, checksum); + dex::TypeIndex type_idx, + uint32_t num_method_ids) { + DexFileData* const data = GetOrAddDexFileData(dex_location, checksum, num_method_ids); if (data == nullptr) { return false; } @@ -694,7 +740,9 @@ bool ProfileCompilationInfo::ReadMethods(SafeBuffer& buffer, - line_header.method_region_size_bytes; uint16_t last_method_index = 0; while (buffer.CountUnreadBytes() > expected_unread_bytes_after_operation) { - DexFileData* const data = GetOrAddDexFileData(line_header.dex_location, line_header.checksum); + DexFileData* const data = GetOrAddDexFileData(line_header.dex_location, + line_header.checksum, + line_header.num_method_ids); uint16_t diff_with_last_method_index; READ_UINT(uint16_t, buffer, diff_with_last_method_index, error); uint16_t method_index = last_method_index + diff_with_last_method_index; @@ -729,7 +777,8 @@ bool ProfileCompilationInfo::ReadClasses(SafeBuffer& buffer, last_class_index = type_index; if (!AddClassIndex(line_header.dex_location, line_header.checksum, - dex::TypeIndex(type_index))) { + dex::TypeIndex(type_index), + line_header.num_method_ids)) { return false; } } @@ -863,6 +912,7 @@ bool ProfileCompilationInfo::ReadProfileLineHeaderElements(SafeBuffer& buffer, READ_UINT(uint16_t, buffer, line_header->class_set_size, error); READ_UINT(uint32_t, buffer, line_header->method_region_size_bytes, error); READ_UINT(uint32_t, buffer, line_header->checksum, error); + READ_UINT(uint32_t, buffer, line_header->num_method_ids, error); return true; } @@ -902,7 +952,10 @@ ProfileCompilationInfo::ProfileLoadSatus ProfileCompilationInfo::ReadProfileLine uint8_t number_of_dex_files, const ProfileLineHeader& line_header, /*out*/std::string* error) { - if (GetOrAddDexFileData(line_header.dex_location, line_header.checksum) == nullptr) { + DexFileData* data = GetOrAddDexFileData(line_header.dex_location, + line_header.checksum, + line_header.num_method_ids); + if (data == nullptr) { *error = "Error when reading profile file line header: checksum mismatch for " + line_header.dex_location; return kProfileLoadBadData; @@ -915,6 +968,16 @@ ProfileCompilationInfo::ProfileLoadSatus ProfileCompilationInfo::ReadProfileLine if (!ReadClasses(buffer, line_header, error)) { return kProfileLoadBadData; } + + const size_t bytes = data->bitmap_storage.size(); + if (buffer.CountUnreadBytes() < bytes) { + *error += "Profile EOF reached prematurely for ReadProfileHeaderDexLocation"; + return kProfileLoadBadData; + } + const uint8_t* base_ptr = buffer.GetCurrentPtr(); + std::copy_n(base_ptr, bytes, &data->bitmap_storage[0]); + buffer.Advance(bytes); + // Read method bitmap. return kProfileLoadSuccess; } @@ -932,6 +995,15 @@ bool ProfileCompilationInfo::Load(int fd) { } } +void ProfileCompilationInfo::DexFileData::CreateBitmap() { + const size_t num_bits = num_method_ids * kMethodBitCount; + bitmap_storage.resize(RoundUp(num_bits, kBitsPerByte) / kBitsPerByte); + if (!bitmap_storage.empty()) { + method_bitmap = + BitMemoryRegion(MemoryRegion(&bitmap_storage[0], bitmap_storage.size()), 0, num_bits); + } +} + // TODO(calin): fail fast if the dex checksums don't match. ProfileCompilationInfo::ProfileLoadSatus ProfileCompilationInfo::LoadInternal( int fd, std::string* error) { @@ -1110,7 +1182,8 @@ bool ProfileCompilationInfo::MergeWith(const ProfileCompilationInfo& other) { SafeMap<uint8_t, uint8_t> dex_profile_index_remap; for (const DexFileData* other_dex_data : other.info_) { const DexFileData* dex_data = GetOrAddDexFileData(other_dex_data->profile_key, - other_dex_data->checksum); + other_dex_data->checksum, + other_dex_data->num_method_ids); if (dex_data == nullptr) { return false; // Could happen if we exceed the number of allowed dex files. } @@ -1147,6 +1220,9 @@ bool ProfileCompilationInfo::MergeWith(const ProfileCompilationInfo& other) { } } } + + // Merge the bitmaps. + dex_data->MergeBitmap(*other_dex_data); } return true; } @@ -1159,6 +1235,27 @@ static bool ChecksumMatch(const DexFile& dex_file, uint32_t checksum) { return ChecksumMatch(dex_file.GetLocationChecksum(), checksum); } +bool ProfileCompilationInfo::IsStartupOrHotMethod(const MethodReference& method_ref) const { + return IsStartupOrHotMethod(method_ref.dex_file->GetLocation(), + method_ref.dex_file->GetLocationChecksum(), + method_ref.dex_method_index); +} + +bool ProfileCompilationInfo::IsStartupOrHotMethod(const std::string& dex_location, + uint32_t dex_checksum, + uint16_t dex_method_index) const { + const DexFileData* dex_data = FindDexData(GetProfileDexFileKey(dex_location)); + if (dex_data == nullptr || !ChecksumMatch(dex_checksum, dex_data->checksum)) { + return false; + } + if (dex_data->HasSampledMethod(/*startup*/ true, dex_method_index)) { + return true; + } + const MethodMap& methods = dex_data->method_map; + const auto method_it = methods.find(dex_method_index); + return method_it != methods.end(); +} + bool ProfileCompilationInfo::ContainsMethod(const MethodReference& method_ref) const { return FindMethod(method_ref.dex_file->GetLocation(), method_ref.dex_file->GetLocationChecksum(), @@ -1196,6 +1293,7 @@ std::unique_ptr<ProfileCompilationInfo::OfflineProfileMethodInfo> ProfileCompila for (const DexFileData* dex_data : info_) { pmi->dex_references[dex_data->profile_index].dex_location = dex_data->profile_key; pmi->dex_references[dex_data->profile_index].dex_checksum = dex_data->checksum; + pmi->dex_references[dex_data->profile_index].num_method_ids = dex_data->num_method_ids; } return pmi; @@ -1314,9 +1412,12 @@ std::string ProfileCompilationInfo::DumpInfo(const std::vector<const DexFile*>* return os.str(); } -bool ProfileCompilationInfo::GetClassesAndMethods(const DexFile& dex_file, - std::set<dex::TypeIndex>* class_set, - std::set<uint16_t>* method_set) const { +bool ProfileCompilationInfo::GetClassesAndMethods( + const DexFile& dex_file, + /*out*/std::set<dex::TypeIndex>* class_set, + /*out*/std::set<uint16_t>* hot_method_set, + /*out*/std::set<uint16_t>* startup_method_set, + /*out*/std::set<uint16_t>* post_startup_method_method_set) const { std::set<std::string> ret; std::string profile_key = GetProfileDexFileKey(dex_file.GetLocation()); const DexFileData* dex_data = FindDexData(profile_key); @@ -1324,7 +1425,15 @@ bool ProfileCompilationInfo::GetClassesAndMethods(const DexFile& dex_file, return false; } for (const auto& it : dex_data->method_map) { - method_set->insert(it.first); + hot_method_set->insert(it.first); + } + for (uint32_t method_idx = 0; method_idx < dex_data->num_method_ids; ++method_idx) { + if (dex_data->HasSampledMethod(/*startup*/ true, method_idx)) { + startup_method_set->insert(method_idx); + } + if (dex_data->HasSampledMethod(/*startup*/ false, method_idx)) { + post_startup_method_method_set->insert(method_idx); + } } for (const dex::TypeIndex& type_index : dex_data->class_set) { class_set->insert(type_index); @@ -1366,7 +1475,10 @@ std::set<DexCacheResolvedClasses> ProfileCompilationInfo::GetResolvedClasses( << ", profile checksum=" << dex_data->checksum; return std::set<DexCacheResolvedClasses>(); } - DexCacheResolvedClasses classes(dex_location, dex_location, dex_data->checksum); + DexCacheResolvedClasses classes(dex_location, + dex_location, + dex_data->checksum, + dex_data->num_method_ids); classes.AddClasses(dex_data->class_set.begin(), dex_data->class_set.end()); ret.insert(classes); } @@ -1383,8 +1495,8 @@ bool ProfileCompilationInfo::GenerateTestProfile(int fd, const std::string base_dex_location = "base.apk"; ProfileCompilationInfo info; // The limits are defined by the dex specification. - uint16_t max_method = std::numeric_limits<uint16_t>::max(); - uint16_t max_classes = std::numeric_limits<uint16_t>::max(); + const uint16_t max_method = std::numeric_limits<uint16_t>::max(); + const uint16_t max_classes = std::numeric_limits<uint16_t>::max(); uint16_t number_of_methods = max_method * method_ratio / 100; uint16_t number_of_classes = max_classes * class_ratio / 100; @@ -1404,7 +1516,7 @@ bool ProfileCompilationInfo::GenerateTestProfile(int fd, if (m < (number_of_methods / kFavorSplit)) { method_idx %= kFavorFirstN; } - info.AddMethodIndex(profile_key, 0, method_idx); + info.AddMethodIndex(profile_key, 0, method_idx, max_method); } for (uint16_t c = 0; c < number_of_classes; c++) { @@ -1412,7 +1524,7 @@ bool ProfileCompilationInfo::GenerateTestProfile(int fd, if (c < (number_of_classes / kFavorSplit)) { type_idx %= kFavorFirstN; } - info.AddClassIndex(profile_key, 0, dex::TypeIndex(type_idx)); + info.AddClassIndex(profile_key, 0, dex::TypeIndex(type_idx), max_method); } } return info.Save(fd); @@ -1431,13 +1543,16 @@ bool ProfileCompilationInfo::GenerateTestProfile( for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { // Randomly add a class from the dex file (with 50% chance). if (std::rand() % 2 != 0) { - info.AddClassIndex(location, checksum, dex::TypeIndex(dex_file->GetClassDef(i).class_idx_)); + info.AddClassIndex(location, + checksum, + dex::TypeIndex(dex_file->GetClassDef(i).class_idx_), + dex_file->NumMethodIds()); } } for (uint32_t i = 0; i < dex_file->NumMethodIds(); ++i) { // Randomly add a method from the dex file (with 50% chance). if (std::rand() % 2 != 0) { - info.AddMethodIndex(location, checksum, i); + info.AddMethodIndex(location, checksum, i, dex_file->NumMethodIds()); } } } diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h index ca5b28a809..2b89a41dd8 100644 --- a/runtime/jit/profile_compilation_info.h +++ b/runtime/jit/profile_compilation_info.h @@ -23,6 +23,7 @@ #include "atomic.h" #include "base/arena_object.h" #include "base/arena_containers.h" +#include "bit_memory_region.h" #include "dex_cache_resolved_classes.h" #include "dex_file.h" #include "dex_file_types.h" @@ -54,7 +55,9 @@ struct ProfileMethodInfo { ProfileMethodInfo(const DexFile* dex, uint32_t method_index, const std::vector<ProfileInlineCache>& caches) - : dex_file(dex), dex_method_index(method_index), inline_caches(caches) {} + : dex_file(dex), + dex_method_index(method_index), + inline_caches(caches) {} const DexFile* dex_file; const uint32_t dex_method_index; @@ -79,13 +82,15 @@ class ProfileCompilationInfo { // A dex location together with its checksum. struct DexReference { - DexReference() : dex_checksum(0) {} + DexReference() : dex_checksum(0), num_method_ids(0) {} - DexReference(const std::string& location, uint32_t checksum) - : dex_location(location), dex_checksum(checksum) {} + DexReference(const std::string& location, uint32_t checksum, uint32_t num_methods) + : dex_location(location), dex_checksum(checksum), num_method_ids(num_methods) {} bool operator==(const DexReference& other) const { - return dex_checksum == other.dex_checksum && dex_location == other.dex_location; + return dex_checksum == other.dex_checksum && + dex_location == other.dex_location && + num_method_ids == other.num_method_ids; } bool MatchesDex(const DexFile* dex_file) const { @@ -95,6 +100,7 @@ class ProfileCompilationInfo { std::string dex_location; uint32_t dex_checksum; + uint32_t num_method_ids; }; // Encodes a class reference in the profile. @@ -191,6 +197,24 @@ class ProfileCompilationInfo { bool AddMethodsAndClasses(const std::vector<ProfileMethodInfo>& methods, const std::set<DexCacheResolvedClasses>& resolved_classes); + // Add a method index to the profile (without inline caches). + bool AddMethodIndex(const std::string& dex_location, + uint32_t checksum, + uint16_t method_idx, + uint32_t num_method_ids); + + // Add a method to the profile using its online representation (containing runtime structures). + bool AddMethod(const ProfileMethodInfo& pmi); + + // Add methods that have samples but are are not necessarily hot. These are partitioned into two + // possibly interesecting sets startup and post startup. + bool AddSampledMethods(bool startup, std::vector<MethodReference>& methods); + bool AddSampledMethod(bool startup, + const std::string& dex_location, + uint32_t checksum, + uint16_t method_idx, + uint32_t num_method_ids); + // Load profile information from the given file descriptor. // If the current profile is non-empty the load will fail. bool Load(int fd); @@ -216,6 +240,12 @@ class ProfileCompilationInfo { // Return the number of resolved classes that were profiled. uint32_t GetNumberOfResolvedClasses() const; + // Return true if the method reference is a hot or startup method in the profiling info. + bool IsStartupOrHotMethod(const MethodReference& method_ref) const; + bool IsStartupOrHotMethod(const std::string& dex_location, + uint32_t dex_checksum, + uint16_t dex_method_index) const; + // Return true if the method reference is present in the profiling info. bool ContainsMethod(const MethodReference& method_ref) const; @@ -244,7 +274,9 @@ class ProfileCompilationInfo { // file is register and has a matching checksum, false otherwise. bool GetClassesAndMethods(const DexFile& dex_file, /*out*/std::set<dex::TypeIndex>* class_set, - /*out*/std::set<uint16_t>* method_set) const; + /*out*/std::set<uint16_t>* hot_method_set, + /*out*/std::set<uint16_t>* startup_method_set, + /*out*/std::set<uint16_t>* post_startup_method_method_set) const; // Perform an equality test with the `other` profile information. bool Equals(const ProfileCompilationInfo& other); @@ -301,13 +333,31 @@ class ProfileCompilationInfo { DexFileData(ArenaAllocator* arena, const std::string& key, uint32_t location_checksum, - uint16_t index) + uint16_t index, + uint32_t num_methods) : arena_(arena), profile_key(key), profile_index(index), checksum(location_checksum), method_map(std::less<uint16_t>(), arena->Adapter(kArenaAllocProfile)), - class_set(std::less<dex::TypeIndex>(), arena->Adapter(kArenaAllocProfile)) {} + class_set(std::less<dex::TypeIndex>(), arena->Adapter(kArenaAllocProfile)), + num_method_ids(num_methods), + bitmap_storage(arena->Adapter(kArenaAllocProfile)) { + CreateBitmap(); + } + + bool operator==(const DexFileData& other) const { + return checksum == other.checksum && method_map == other.method_map; + } + + // Mark a method as executed at least once. + void AddSampledMethod(bool startup, size_t index) { + method_bitmap.StoreBit(MethodBitIndex(startup, index), true); + } + + bool HasSampledMethod(bool startup, size_t index) const { + return method_bitmap.LoadBit(MethodBitIndex(startup, index)); + } // The arena used to allocate new inline cache maps. ArenaAllocator* arena_; @@ -322,32 +372,64 @@ class ProfileCompilationInfo { // The classes which have been profiled. Note that these don't necessarily include // all the classes that can be found in the inline caches reference. ArenaSet<dex::TypeIndex> class_set; - - bool operator==(const DexFileData& other) const { - return checksum == other.checksum && method_map == other.method_map; - } - // Find the inline caches of the the given method index. Add an empty entry if // no previous data is found. InlineCacheMap* FindOrAddMethod(uint16_t method_index); + // Num method ids. + uint32_t num_method_ids; + ArenaVector<uint8_t> bitmap_storage; + BitMemoryRegion method_bitmap; + + void CreateBitmap(); + + void MergeBitmap(const DexFileData& other) { + DCHECK_EQ(bitmap_storage.size(), other.bitmap_storage.size()); + for (size_t i = 0; i < bitmap_storage.size(); ++i) { + bitmap_storage[i] |= other.bitmap_storage[i]; + } + } + + private: + enum Bits { + kMethodBitStartup, + kMethodBitAfterStartup, + kMethodBitCount, + }; + + size_t MethodBitIndex(bool startup, size_t index) const { + DCHECK_LT(index, num_method_ids); + if (!startup) { + index += num_method_ids; + } + return index; + } }; // Return the profile data for the given profile key or null if the dex location // already exists but has a different checksum - DexFileData* GetOrAddDexFileData(const std::string& profile_key, uint32_t checksum); + DexFileData* GetOrAddDexFileData(const std::string& profile_key, + uint32_t checksum, + uint32_t num_method_ids); - // Add a method to the profile using its online representation (containing runtime structures). - bool AddMethod(const ProfileMethodInfo& pmi); + DexFileData* GetOrAddDexFileData(const DexFile* dex_file) { + return GetOrAddDexFileData(GetProfileDexFileKey(dex_file->GetLocation()), + dex_file->GetLocationChecksum(), + dex_file->NumMethodIds()); + } // Add a method to the profile using its offline representation. // This is mostly used to facilitate testing. bool AddMethod(const std::string& dex_location, uint32_t dex_checksum, uint16_t method_index, + uint32_t num_method_ids, const OfflineProfileMethodInfo& pmi); // Add a class index to the profile. - bool AddClassIndex(const std::string& dex_location, uint32_t checksum, dex::TypeIndex type_idx); + bool AddClassIndex(const std::string& dex_location, + uint32_t checksum, + dex::TypeIndex type_idx, + uint32_t num_method_ids); // Add all classes from the given dex cache to the the profile. bool AddResolvedClasses(const DexCacheResolvedClasses& classes); @@ -392,6 +474,7 @@ class ProfileCompilationInfo { uint16_t class_set_size; uint32_t method_region_size_bytes; uint32_t checksum; + uint32_t num_method_ids; }; // A helper structure to make sure we don't read past our buffers in the loops. diff --git a/runtime/jit/profile_compilation_info_test.cc b/runtime/jit/profile_compilation_info_test.cc index 1cfa3552b9..615149feb3 100644 --- a/runtime/jit/profile_compilation_info_test.cc +++ b/runtime/jit/profile_compilation_info_test.cc @@ -32,6 +32,8 @@ namespace art { +static constexpr size_t kMaxMethodIds = 65535; + class ProfileCompilationInfoTest : public CommonRuntimeTest { public: void PostRuntimeCreate() OVERRIDE { @@ -61,7 +63,7 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { uint32_t checksum, uint16_t method_index, ProfileCompilationInfo* info) { - return info->AddMethodIndex(dex_location, checksum, method_index); + return info->AddMethodIndex(dex_location, checksum, method_index, kMaxMethodIds); } bool AddMethod(const std::string& dex_location, @@ -69,14 +71,14 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { uint16_t method_index, const ProfileCompilationInfo::OfflineProfileMethodInfo& pmi, ProfileCompilationInfo* info) { - return info->AddMethod(dex_location, checksum, method_index, pmi); + return info->AddMethod(dex_location, checksum, method_index, kMaxMethodIds, pmi); } bool AddClass(const std::string& dex_location, uint32_t checksum, uint16_t class_index, ProfileCompilationInfo* info) { - return info->AddMethodIndex(dex_location, checksum, class_index); + return info->AddMethodIndex(dex_location, checksum, class_index, kMaxMethodIds); } uint32_t GetFd(const ScratchFile& file) { @@ -149,7 +151,9 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { std::vector<TypeReference> classes; caches.emplace_back(dex_pc, /*is_missing_types*/true, classes); } - ProfileMethodInfo pmi(method->GetDexFile(), method->GetDexMethodIndex(), caches); + ProfileMethodInfo pmi(method->GetDexFile(), + method->GetDexMethodIndex(), + caches); profile_methods.push_back(pmi); profile_methods_map->Put(method, pmi); } @@ -191,7 +195,8 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { const std::string& dex_key = ProfileCompilationInfo::GetProfileDexFileKey( class_ref.dex_file->GetLocation()); offline_pmi.dex_references.emplace_back(dex_key, - class_ref.dex_file->GetLocationChecksum()); + class_ref.dex_file->GetLocationChecksum(), + class_ref.dex_file->NumMethodIds()); } } } @@ -201,6 +206,7 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { // Creates an offline profile used for testing inline caches. ProfileCompilationInfo::OfflineProfileMethodInfo GetOfflineProfileMethodInfo() { ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap(); + // Monomorphic for (uint16_t dex_pc = 0; dex_pc < 11; dex_pc++) { ProfileCompilationInfo::DexPcData dex_pc_data(arena_.get()); @@ -231,9 +237,9 @@ class ProfileCompilationInfoTest : public CommonRuntimeTest { ProfileCompilationInfo::OfflineProfileMethodInfo pmi(ic_map); - pmi.dex_references.emplace_back("dex_location1", /* checksum */1); - pmi.dex_references.emplace_back("dex_location2", /* checksum */2); - pmi.dex_references.emplace_back("dex_location3", /* checksum */3); + pmi.dex_references.emplace_back("dex_location1", /* checksum */1, kMaxMethodIds); + pmi.dex_references.emplace_back("dex_location2", /* checksum */2, kMaxMethodIds); + pmi.dex_references.emplace_back("dex_location3", /* checksum */3, kMaxMethodIds); return pmi; } @@ -694,8 +700,8 @@ TEST_F(ProfileCompilationInfoTest, MergeInlineCacheTriggerReindex) { ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap(); ProfileCompilationInfo::OfflineProfileMethodInfo pmi(ic_map); - pmi.dex_references.emplace_back("dex_location1", /* checksum */ 1); - pmi.dex_references.emplace_back("dex_location2", /* checksum */ 2); + pmi.dex_references.emplace_back("dex_location1", /* checksum */ 1, kMaxMethodIds); + pmi.dex_references.emplace_back("dex_location2", /* checksum */ 2, kMaxMethodIds); for (uint16_t dex_pc = 1; dex_pc < 5; dex_pc++) { ProfileCompilationInfo::DexPcData dex_pc_data(arena_.get()); dex_pc_data.AddClass(0, dex::TypeIndex(0)); @@ -705,8 +711,8 @@ TEST_F(ProfileCompilationInfoTest, MergeInlineCacheTriggerReindex) { ProfileCompilationInfo::InlineCacheMap* ic_map_reindexed = CreateInlineCacheMap(); ProfileCompilationInfo::OfflineProfileMethodInfo pmi_reindexed(ic_map_reindexed); - pmi_reindexed.dex_references.emplace_back("dex_location2", /* checksum */ 2); - pmi_reindexed.dex_references.emplace_back("dex_location1", /* checksum */ 1); + pmi_reindexed.dex_references.emplace_back("dex_location2", /* checksum */ 2, kMaxMethodIds); + pmi_reindexed.dex_references.emplace_back("dex_location1", /* checksum */ 1, kMaxMethodIds); for (uint16_t dex_pc = 1; dex_pc < 5; dex_pc++) { ProfileCompilationInfo::DexPcData dex_pc_data(arena_.get()); dex_pc_data.AddClass(1, dex::TypeIndex(0)); @@ -761,7 +767,7 @@ TEST_F(ProfileCompilationInfoTest, MegamorphicInlineCachesMerge) { // Create a megamorphic inline cache. ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap(); ProfileCompilationInfo::OfflineProfileMethodInfo pmi(ic_map); - pmi.dex_references.emplace_back("dex_location1", /* checksum */ 1); + pmi.dex_references.emplace_back("dex_location1", /* checksum */ 1, kMaxMethodIds); ProfileCompilationInfo::DexPcData dex_pc_data(arena_.get()); dex_pc_data.SetIsMegamorphic(); ic_map->Put(/*dex_pc*/ 0, dex_pc_data); @@ -791,7 +797,7 @@ TEST_F(ProfileCompilationInfoTest, MissingTypesInlineCachesMerge) { // Create an inline cache with missing types ProfileCompilationInfo::InlineCacheMap* ic_map = CreateInlineCacheMap(); ProfileCompilationInfo::OfflineProfileMethodInfo pmi(ic_map); - pmi.dex_references.emplace_back("dex_location1", /* checksum */ 1); + pmi.dex_references.emplace_back("dex_location1", /* checksum */ 1, kMaxMethodIds); ProfileCompilationInfo::DexPcData dex_pc_data(arena_.get()); dex_pc_data.SetIsMissingTypes(); ic_map->Put(/*dex_pc*/ 0, dex_pc_data); @@ -839,4 +845,48 @@ TEST_F(ProfileCompilationInfoTest, LoadShouldClearExistingDataFromProfiles) { // This should fail since the test_info already contains data and the load would overwrite it. ASSERT_FALSE(test_info.Load(GetFd(profile))); } + +TEST_F(ProfileCompilationInfoTest, SampledMethodsTest) { + ProfileCompilationInfo test_info; + static constexpr size_t kNumMethods = 1000; + static constexpr size_t kChecksum1 = 1234; + static constexpr size_t kChecksum2 = 4321; + static const std::string kDex1 = "dex1"; + static const std::string kDex2 = "dex2"; + test_info.AddSampledMethod(true, kDex1, kChecksum1, 1, kNumMethods); + test_info.AddSampledMethod(true, kDex1, kChecksum1, 5, kNumMethods); + test_info.AddSampledMethod(false, kDex2, kChecksum2, 1, kNumMethods); + test_info.AddSampledMethod(false, kDex2, kChecksum2, 5, kNumMethods); + auto run_test = [](const ProfileCompilationInfo& info) { + EXPECT_FALSE(info.IsStartupOrHotMethod(kDex1, kChecksum1, 0)); + EXPECT_TRUE(info.IsStartupOrHotMethod(kDex1, kChecksum1, 1)); + EXPECT_FALSE(info.IsStartupOrHotMethod(kDex1, kChecksum1, 3)); + EXPECT_TRUE(info.IsStartupOrHotMethod(kDex1, kChecksum1, 5)); + EXPECT_FALSE(info.IsStartupOrHotMethod(kDex1, kChecksum1, 6)); + EXPECT_FALSE(info.IsStartupOrHotMethod(kDex2, kChecksum2, 5)); + EXPECT_FALSE(info.IsStartupOrHotMethod(kDex2, kChecksum2, 5)); + }; + run_test(test_info); + + // Save the profile. + ScratchFile profile; + ASSERT_TRUE(test_info.Save(GetFd(profile))); + ASSERT_EQ(0, profile.GetFile()->Flush()); + ASSERT_TRUE(profile.GetFile()->ResetOffset()); + + // Load the profile and make sure we can read the data and it matches what we expect. + ProfileCompilationInfo loaded_info; + ASSERT_TRUE(loaded_info.Load(GetFd(profile))); + run_test(loaded_info); + + // Test that the bitmap gets merged properly. + EXPECT_FALSE(test_info.IsStartupOrHotMethod(kDex1, kChecksum1, 11)); + { + ProfileCompilationInfo merge_info; + merge_info.AddSampledMethod(true, kDex1, kChecksum1, 11, kNumMethods); + test_info.MergeWith(merge_info); + } + EXPECT_TRUE(test_info.IsStartupOrHotMethod(kDex1, kChecksum1, 11)); +} + } // namespace art diff --git a/runtime/jit/profile_saver.cc b/runtime/jit/profile_saver.cc index bc829cf9a7..c96ca88874 100644 --- a/runtime/jit/profile_saver.cc +++ b/runtime/jit/profile_saver.cc @@ -183,8 +183,11 @@ void ProfileSaver::NotifyJitActivityInternal() { // Excludes native methods and classes in the boot image. class GetMethodsVisitor : public ClassVisitor { public: - GetMethodsVisitor(std::vector<MethodReference>* methods, uint32_t startup_method_samples) - : methods_(methods), + GetMethodsVisitor(std::vector<MethodReference>* hot_methods, + std::vector<MethodReference>* startup_methods, + uint32_t startup_method_samples) + : hot_methods_(hot_methods), + startup_methods_(startup_methods), startup_method_samples_(startup_method_samples) {} virtual bool operator()(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) { @@ -192,22 +195,26 @@ class GetMethodsVisitor : public ClassVisitor { return true; } for (ArtMethod& method : klass->GetMethods(kRuntimePointerSize)) { - if (!method.IsNative()) { - if (method.GetCounter() >= startup_method_samples_ || - method.GetProfilingInfo(kRuntimePointerSize) != nullptr || + if (!method.IsNative() && !method.IsProxyMethod()) { + const uint16_t counter = method.GetCounter(); + MethodReference ref(method.GetDexFile(), method.GetDexMethodIndex()); + if (method.GetProfilingInfo(kRuntimePointerSize) != nullptr || (method.GetAccessFlags() & kAccPreviouslyWarm) != 0) { - // Have samples, add to profile. - const DexFile* dex_file = - method.GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetDexFile(); - methods_->push_back(MethodReference(dex_file, method.GetDexMethodIndex())); + hot_methods_->push_back(ref); + startup_methods_->push_back(ref); + } else if (counter >= startup_method_samples_) { + startup_methods_->push_back(ref); } + } else { + CHECK_EQ(method.GetCounter(), 0u); } } return true; } private: - std::vector<MethodReference>* const methods_; + std::vector<MethodReference>* const hot_methods_; + std::vector<MethodReference>* const startup_methods_; uint32_t startup_method_samples_; }; @@ -218,7 +225,8 @@ void ProfileSaver::FetchAndCacheResolvedClassesAndMethods() { ResolveTrackedLocations(); Thread* const self = Thread::Current(); - std::vector<MethodReference> methods; + std::vector<MethodReference> hot_methods; + std::vector<MethodReference> startup_methods; std::set<DexCacheResolvedClasses> resolved_classes; { ScopedObjectAccess soa(self); @@ -231,10 +239,13 @@ void ProfileSaver::FetchAndCacheResolvedClassesAndMethods() { { ScopedTrace trace2("Get hot methods"); - GetMethodsVisitor visitor(&methods, options_.GetStartupMethodSamples()); + GetMethodsVisitor visitor(&hot_methods, + &startup_methods, + options_.GetStartupMethodSamples()); class_linker->VisitClasses(&visitor); - VLOG(profiler) << "Methods with samples greater than " - << options_.GetStartupMethodSamples() << " = " << methods.size(); + VLOG(profiler) << "Profile saver recorded " << hot_methods.size() << " hot methods and " + << startup_methods.size() << " startup methods with threshold " + << options_.GetStartupMethodSamples(); } } MutexLock mu(self, *Locks::profiler_lock_); @@ -245,11 +256,18 @@ void ProfileSaver::FetchAndCacheResolvedClassesAndMethods() { const std::string& filename = it.first; const std::set<std::string>& locations = it.second; std::vector<ProfileMethodInfo> profile_methods_for_location; - for (const MethodReference& ref : methods) { + for (const MethodReference& ref : hot_methods) { if (locations.find(ref.dex_file->GetBaseLocation()) != locations.end()) { profile_methods_for_location.emplace_back(ref.dex_file, ref.dex_method_index); } } + std::vector<MethodReference> startup_methods_for_locations; + for (const MethodReference& ref : startup_methods) { + if (locations.find(ref.dex_file->GetBaseLocation()) != locations.end()) { + startup_methods_for_locations.push_back(ref); + } + } + for (const DexCacheResolvedClasses& classes : resolved_classes) { if (locations.find(classes.GetBaseLocation()) != locations.end()) { VLOG(profiler) << "Added " << classes.GetClasses().size() << " classes for location " @@ -265,8 +283,8 @@ void ProfileSaver::FetchAndCacheResolvedClassesAndMethods() { new ProfileCompilationInfo(Runtime::Current()->GetArenaPool())); ProfileCompilationInfo* cached_info = info_it->second; - cached_info->AddMethodsAndClasses(profile_methods_for_location, - resolved_classes_for_location); + cached_info->AddMethodsAndClasses(profile_methods_for_location, resolved_classes_for_location); + cached_info->AddSampledMethods(/*startup*/ true, startup_methods_for_locations); total_number_of_profile_entries_cached += resolved_classes_for_location.size(); } max_number_of_profile_entries_cached_ = std::max( @@ -317,8 +335,7 @@ bool ProfileSaver::ProcessProfilingInfo(bool force_save, /*out*/uint16_t* number uint64_t last_save_number_of_methods = info.GetNumberOfMethods(); uint64_t last_save_number_of_classes = info.GetNumberOfResolvedClasses(); - info.AddMethodsAndClasses(profile_methods, - std::set<DexCacheResolvedClasses>()); + info.AddMethodsAndClasses(profile_methods, std::set<DexCacheResolvedClasses>()); auto profile_cache_it = profile_cache_.find(filename); if (profile_cache_it != profile_cache_.end()) { info.MergeWith(*(profile_cache_it->second)); diff --git a/runtime/jni_env_ext.cc b/runtime/jni_env_ext.cc index 0148a1c3b0..3ff94f995d 100644 --- a/runtime/jni_env_ext.cc +++ b/runtime/jni_env_ext.cc @@ -28,7 +28,7 @@ #include "lock_word.h" #include "mirror/object-inl.h" #include "nth_caller_visitor.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" namespace art { @@ -123,8 +123,8 @@ void JNIEnvExt::DumpReferenceTables(std::ostream& os) { monitors.Dump(os); } -void JNIEnvExt::PushFrame(int capacity ATTRIBUTE_UNUSED) { - // TODO: take 'capacity' into account. +void JNIEnvExt::PushFrame(int capacity) { + DCHECK_GE(locals.FreeCapacity(), static_cast<size_t>(capacity)); stacked_local_ref_cookies.push_back(local_ref_cookie); local_ref_cookie = locals.GetSegmentState(); } diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 0fde41bd4f..6be0953727 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -106,10 +106,9 @@ static void ThrowNoSuchMethodError(ScopedObjectAccess& soa, static void ReportInvalidJNINativeMethod(const ScopedObjectAccess& soa, ObjPtr<mirror::Class> c, const char* kind, - jint idx, - bool return_errors) + jint idx) REQUIRES_SHARED(Locks::mutator_lock_) { - LOG(return_errors ? ::android::base::ERROR : ::android::base::FATAL) + LOG(ERROR) << "Failed to register native method in " << c->PrettyDescriptor() << " in " << c->GetDexCache()->GetLocation()->ToModifiedUtf8() << ": " << kind << " is null at index " << idx; @@ -2145,13 +2144,10 @@ class JNI { buf); } - static jint RegisterNatives(JNIEnv* env, jclass java_class, const JNINativeMethod* methods, + static jint RegisterNatives(JNIEnv* env, + jclass java_class, + const JNINativeMethod* methods, jint method_count) { - return RegisterNativeMethods(env, java_class, methods, method_count, true); - } - - static jint RegisterNativeMethods(JNIEnv* env, jclass java_class, const JNINativeMethod* methods, - jint method_count, bool return_errors) { if (UNLIKELY(method_count < 0)) { JavaVmExtFromEnv(env)->JniAbortF("RegisterNatives", "negative method count: %d", method_count); @@ -2172,13 +2168,13 @@ class JNI { const char* sig = methods[i].signature; const void* fnPtr = methods[i].fnPtr; if (UNLIKELY(name == nullptr)) { - ReportInvalidJNINativeMethod(soa, c.Get(), "method name", i, return_errors); + ReportInvalidJNINativeMethod(soa, c.Get(), "method name", i); return JNI_ERR; } else if (UNLIKELY(sig == nullptr)) { - ReportInvalidJNINativeMethod(soa, c.Get(), "method signature", i, return_errors); + ReportInvalidJNINativeMethod(soa, c.Get(), "method signature", i); return JNI_ERR; } else if (UNLIKELY(fnPtr == nullptr)) { - ReportInvalidJNINativeMethod(soa, c.Get(), "native function", i, return_errors); + ReportInvalidJNINativeMethod(soa, c.Get(), "native function", i); return JNI_ERR; } bool is_fast = false; @@ -2244,19 +2240,15 @@ class JNI { } if (m == nullptr) { - c->DumpClass( - LOG_STREAM(return_errors - ? ::android::base::ERROR - : ::android::base::FATAL_WITHOUT_ABORT), - mirror::Class::kDumpClassFullDetail); - LOG(return_errors ? ::android::base::ERROR : ::android::base::FATAL) + c->DumpClass(LOG_STREAM(ERROR), mirror::Class::kDumpClassFullDetail); + LOG(ERROR) << "Failed to register native method " << c->PrettyDescriptor() << "." << name << sig << " in " << c->GetDexCache()->GetLocation()->ToModifiedUtf8(); ThrowNoSuchMethodError(soa, c.Get(), name, sig, "static or non-static"); return JNI_ERR; } else if (!m->IsNative()) { - LOG(return_errors ? ::android::base::ERROR : ::android::base::FATAL) + LOG(ERROR) << "Failed to register non-native method " << c->PrettyDescriptor() << "." << name << sig << " as native"; @@ -2407,18 +2399,18 @@ class JNI { static jint EnsureLocalCapacityInternal(ScopedObjectAccess& soa, jint desired_capacity, const char* caller) REQUIRES_SHARED(Locks::mutator_lock_) { - // TODO: we should try to expand the table if necessary. - if (desired_capacity < 0 || desired_capacity > static_cast<jint>(kLocalsInitial)) { + if (desired_capacity < 0) { LOG(ERROR) << "Invalid capacity given to " << caller << ": " << desired_capacity; return JNI_ERR; } - // TODO: this isn't quite right, since "capacity" includes holes. - const size_t capacity = soa.Env()->locals.Capacity(); - bool okay = (static_cast<jint>(kLocalsInitial - capacity) >= desired_capacity); - if (!okay) { - soa.Self()->ThrowOutOfMemoryError(caller); + + std::string error_msg; + if (!soa.Env()->locals.EnsureFreeCapacity(static_cast<size_t>(desired_capacity), &error_msg)) { + std::string caller_error = android::base::StringPrintf("%s: %s", caller, error_msg.c_str()); + soa.Self()->ThrowOutOfMemoryError(caller_error.c_str()); + return JNI_ERR; } - return okay ? JNI_OK : JNI_ERR; + return JNI_OK; } template<typename JniT, typename ArtT> @@ -3051,16 +3043,6 @@ const JNINativeInterface* GetRuntimeShutdownNativeInterface() { return reinterpret_cast<JNINativeInterface*>(&gJniSleepForeverStub); } -void RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINativeMethod* methods, - jint method_count) { - ScopedLocalRef<jclass> c(env, env->FindClass(jni_class_name)); - if (c.get() == nullptr) { - LOG(FATAL) << "Couldn't find class: " << jni_class_name; - } - jint jni_result = env->RegisterNatives(c.get(), methods, method_count); - CHECK_EQ(JNI_OK, jni_result); -} - } // namespace art std::ostream& operator<<(std::ostream& os, const jobjectRefType& rhs) { diff --git a/runtime/jni_internal.h b/runtime/jni_internal.h index 24bee6fb1d..2c90b3ba78 100644 --- a/runtime/jni_internal.h +++ b/runtime/jni_internal.h @@ -22,9 +22,6 @@ #include "base/macros.h" -#define REGISTER_NATIVE_METHODS(jni_class_name) \ - RegisterNativeMethods(env, jni_class_name, gMethods, arraysize(gMethods)) - namespace art { class ArtField; @@ -33,11 +30,6 @@ class ArtMethod; const JNINativeInterface* GetJniNativeInterface(); const JNINativeInterface* GetRuntimeShutdownNativeInterface(); -// Similar to RegisterNatives except its passed a descriptor for a class name and failures are -// fatal. -void RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINativeMethod* methods, - jint method_count); - int ThrowNewException(JNIEnv* env, jclass exception_class, const char* msg, jobject cause); namespace jni { diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc index 08d1eeb95d..e1e4f9c7d6 100644 --- a/runtime/jni_internal_test.cc +++ b/runtime/jni_internal_test.cc @@ -1908,9 +1908,6 @@ TEST_F(JniInternalTest, PushLocalFrame_10395422) { // Negative capacities are not allowed. ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(-1)); - - // And it's okay to have an upper limit. Ours is currently 512. - ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(8192)); } TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) { @@ -1962,6 +1959,28 @@ TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) { check_jni_abort_catcher.Check("use of deleted local reference"); } +TEST_F(JniInternalTest, PushLocalFrame_LimitAndOverflow) { + // Try a very large value that should fail. + ASSERT_NE(JNI_OK, env_->PushLocalFrame(std::numeric_limits<jint>::max())); + ASSERT_TRUE(env_->ExceptionCheck()); + env_->ExceptionClear(); + + // On 32-bit, also check for some overflow conditions. +#ifndef __LP64__ + ASSERT_EQ(JNI_OK, env_->PushLocalFrame(10)); + ASSERT_NE(JNI_OK, env_->PushLocalFrame(std::numeric_limits<jint>::max() - 10)); + ASSERT_TRUE(env_->ExceptionCheck()); + env_->ExceptionClear(); + EXPECT_EQ(env_->PopLocalFrame(nullptr), nullptr); +#endif +} + +TEST_F(JniInternalTest, PushLocalFrame_b62223672) { + // The 512 entry limit has been lifted, try a larger value. + ASSERT_EQ(JNI_OK, env_->PushLocalFrame(1024)); + EXPECT_EQ(env_->PopLocalFrame(nullptr), nullptr); +} + TEST_F(JniInternalTest, NewGlobalRef_nullptr) { EXPECT_EQ(env_->NewGlobalRef(nullptr), nullptr); } diff --git a/runtime/linear_alloc.cc b/runtime/linear_alloc.cc index e9db9b8b4c..3f01fc329a 100644 --- a/runtime/linear_alloc.cc +++ b/runtime/linear_alloc.cc @@ -16,7 +16,7 @@ #include "linear_alloc.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/managed_stack-inl.h b/runtime/managed_stack-inl.h new file mode 100644 index 0000000000..f3f31cf8e8 --- /dev/null +++ b/runtime/managed_stack-inl.h @@ -0,0 +1,48 @@ +/* + * 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_MANAGED_STACK_INL_H_ +#define ART_RUNTIME_MANAGED_STACK_INL_H_ + +#include "managed_stack.h" + +#include <cstring> +#include <stdint.h> +#include <string> + +#include "stack.h" + +namespace art { + +inline ShadowFrame* ManagedStack::PushShadowFrame(ShadowFrame* new_top_frame) { + DCHECK(top_quick_frame_ == nullptr); + ShadowFrame* old_frame = top_shadow_frame_; + top_shadow_frame_ = new_top_frame; + new_top_frame->SetLink(old_frame); + return old_frame; +} + +inline ShadowFrame* ManagedStack::PopShadowFrame() { + DCHECK(top_quick_frame_ == nullptr); + CHECK(top_shadow_frame_ != nullptr); + ShadowFrame* frame = top_shadow_frame_; + top_shadow_frame_ = frame->GetLink(); + return frame; +} + +} // namespace art + +#endif // ART_RUNTIME_MANAGED_STACK_INL_H_ diff --git a/runtime/managed_stack.cc b/runtime/managed_stack.cc new file mode 100644 index 0000000000..be609c325d --- /dev/null +++ b/runtime/managed_stack.cc @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#include "managed_stack-inl.h" + +#include "android-base/stringprintf.h" + +#include "art_method.h" +#include "mirror/object.h" +#include "stack_reference.h" + +namespace art { + +size_t ManagedStack::NumJniShadowFrameReferences() const { + size_t count = 0; + for (const ManagedStack* current_fragment = this; current_fragment != nullptr; + current_fragment = current_fragment->GetLink()) { + for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_; + current_frame != nullptr; + current_frame = current_frame->GetLink()) { + if (current_frame->GetMethod()->IsNative()) { + // The JNI ShadowFrame only contains references. (For indirect reference.) + count += current_frame->NumberOfVRegs(); + } + } + } + return count; +} + +bool ManagedStack::ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const { + for (const ManagedStack* current_fragment = this; current_fragment != nullptr; + current_fragment = current_fragment->GetLink()) { + for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_; + current_frame != nullptr; + current_frame = current_frame->GetLink()) { + if (current_frame->Contains(shadow_frame_entry)) { + return true; + } + } + } + return false; +} + +} // namespace art diff --git a/runtime/managed_stack.h b/runtime/managed_stack.h new file mode 100644 index 0000000000..8337f968ac --- /dev/null +++ b/runtime/managed_stack.h @@ -0,0 +1,107 @@ +/* + * 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_MANAGED_STACK_H_ +#define ART_RUNTIME_MANAGED_STACK_H_ + +#include <cstring> +#include <stdint.h> +#include <string> + +#include "base/logging.h" +#include "base/macros.h" +#include "base/mutex.h" + +namespace art { + +namespace mirror { +class Object; +} // namespace mirror + +class ArtMethod; +class ShadowFrame; +template <typename T> class StackReference; + +// The managed stack is used to record fragments of managed code stacks. Managed code stacks +// may either be shadow frames or lists of frames using fixed frame sizes. Transition records are +// necessary for transitions between code using different frame layouts and transitions into native +// code. +class PACKED(4) ManagedStack { + public: + ManagedStack() + : top_quick_frame_(nullptr), link_(nullptr), top_shadow_frame_(nullptr) {} + + void PushManagedStackFragment(ManagedStack* fragment) { + // Copy this top fragment into given fragment. + memcpy(fragment, this, sizeof(ManagedStack)); + // Clear this fragment, which has become the top. + memset(this, 0, sizeof(ManagedStack)); + // Link our top fragment onto the given fragment. + link_ = fragment; + } + + void PopManagedStackFragment(const ManagedStack& fragment) { + DCHECK(&fragment == link_); + // Copy this given fragment back to the top. + memcpy(this, &fragment, sizeof(ManagedStack)); + } + + ManagedStack* GetLink() const { + return link_; + } + + ArtMethod** GetTopQuickFrame() const { + return top_quick_frame_; + } + + void SetTopQuickFrame(ArtMethod** top) { + DCHECK(top_shadow_frame_ == nullptr); + top_quick_frame_ = top; + } + + static size_t TopQuickFrameOffset() { + return OFFSETOF_MEMBER(ManagedStack, top_quick_frame_); + } + + ALWAYS_INLINE ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame); + ALWAYS_INLINE ShadowFrame* PopShadowFrame(); + + ShadowFrame* GetTopShadowFrame() const { + return top_shadow_frame_; + } + + void SetTopShadowFrame(ShadowFrame* top) { + DCHECK(top_quick_frame_ == nullptr); + top_shadow_frame_ = top; + } + + static size_t TopShadowFrameOffset() { + return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_); + } + + size_t NumJniShadowFrameReferences() const REQUIRES_SHARED(Locks::mutator_lock_); + + bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const; + + private: + ArtMethod** top_quick_frame_; + ManagedStack* link_; + ShadowFrame* top_shadow_frame_; +}; + +} // namespace art + +#endif // ART_RUNTIME_MANAGED_STACK_H_ diff --git a/runtime/method_handles.h b/runtime/method_handles.h index e8a2dce42e..e02e62052c 100644 --- a/runtime/method_handles.h +++ b/runtime/method_handles.h @@ -23,6 +23,7 @@ #include "handle.h" #include "jvalue.h" #include "mirror/class.h" +#include "stack.h" namespace art { diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h index baed5f167c..d3fc95ff2d 100644 --- a/runtime/mirror/object-inl.h +++ b/runtime/mirror/object-inl.h @@ -899,6 +899,36 @@ inline bool Object::CasFieldWeakRelaxedObjectWithoutWriteBarrier( return success; } +template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> +inline bool Object::CasFieldWeakReleaseObjectWithoutWriteBarrier( + MemberOffset field_offset, + ObjPtr<Object> old_value, + ObjPtr<Object> new_value) { + if (kCheckTransaction) { + DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); + } + if (kVerifyFlags & kVerifyThis) { + VerifyObject(this); + } + if (kVerifyFlags & kVerifyWrites) { + VerifyObject(new_value); + } + if (kVerifyFlags & kVerifyReads) { + VerifyObject(old_value); + } + if (kTransactionActive) { + Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); + } + HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value)); + HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value)); + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); + + bool success = atomic_addr->CompareExchangeWeakRelease(old_ref.reference_, + new_ref.reference_); + return success; +} + template<bool kIsStatic, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, diff --git a/runtime/mirror/object-readbarrier-inl.h b/runtime/mirror/object-readbarrier-inl.h index 58e7c20667..69365af7fd 100644 --- a/runtime/mirror/object-readbarrier-inl.h +++ b/runtime/mirror/object-readbarrier-inl.h @@ -221,6 +221,36 @@ inline bool Object::CasFieldStrongRelaxedObjectWithoutWriteBarrier( return success; } +template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> +inline bool Object::CasFieldStrongReleaseObjectWithoutWriteBarrier( + MemberOffset field_offset, + ObjPtr<Object> old_value, + ObjPtr<Object> new_value) { + if (kCheckTransaction) { + DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); + } + if (kVerifyFlags & kVerifyThis) { + VerifyObject(this); + } + if (kVerifyFlags & kVerifyWrites) { + VerifyObject(new_value); + } + if (kVerifyFlags & kVerifyReads) { + VerifyObject(old_value); + } + if (kTransactionActive) { + Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); + } + HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value)); + HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value)); + uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); + Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); + + bool success = atomic_addr->CompareExchangeStrongRelease(old_ref.reference_, + new_ref.reference_); + return success; +} + } // namespace mirror } // namespace art diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h index 35a1b733e1..9cf42522d1 100644 --- a/runtime/mirror/object.h +++ b/runtime/mirror/object.h @@ -350,10 +350,25 @@ class MANAGED LOCKABLE Object { template<bool kTransactionActive, bool kCheckTransaction = true, VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + bool CasFieldWeakReleaseObjectWithoutWriteBarrier(MemberOffset field_offset, + ObjPtr<Object> old_value, + ObjPtr<Object> new_value) + REQUIRES_SHARED(Locks::mutator_lock_); + + template<bool kTransactionActive, + bool kCheckTransaction = true, + VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool CasFieldStrongRelaxedObjectWithoutWriteBarrier(MemberOffset field_offset, ObjPtr<Object> old_value, ObjPtr<Object> new_value) REQUIRES_SHARED(Locks::mutator_lock_); + template<bool kTransactionActive, + bool kCheckTransaction = true, + VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> + bool CasFieldStrongReleaseObjectWithoutWriteBarrier(MemberOffset field_offset, + ObjPtr<Object> old_value, + ObjPtr<Object> new_value) + REQUIRES_SHARED(Locks::mutator_lock_); template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> HeapReference<Object>* GetFieldObjectReferenceAddr(MemberOffset field_offset); diff --git a/runtime/mirror/reference-inl.h b/runtime/mirror/reference-inl.h index a449b41087..f8de6e6d90 100644 --- a/runtime/mirror/reference-inl.h +++ b/runtime/mirror/reference-inl.h @@ -20,6 +20,7 @@ #include "reference.h" #include "obj_ptr-inl.h" +#include "runtime.h" namespace art { namespace mirror { diff --git a/runtime/monitor.cc b/runtime/monitor.cc index bb33047895..f94edcde94 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -32,6 +32,7 @@ #include "mirror/class-inl.h" #include "mirror/object-inl.h" #include "scoped_thread_state_change-inl.h" +#include "stack.h" #include "thread.h" #include "thread_list.h" #include "verifier/method_verifier.h" @@ -437,17 +438,11 @@ void Monitor::Lock(Thread* self) { << " in " << ArtMethod::PrettyMethod(m) << " for " << PrettyDuration(MsToNs(wait_ms)); } - const char* owners_filename; - int32_t owners_line_number; - TranslateLocation(owners_method, - owners_dex_pc, - &owners_filename, - &owners_line_number); LogContentionEvent(self, wait_ms, sample_percent, - owners_filename, - owners_line_number); + owners_method, + owners_dex_pc); } } } diff --git a/runtime/monitor.h b/runtime/monitor.h index e80d31cdd5..6dc706f8b8 100644 --- a/runtime/monitor.h +++ b/runtime/monitor.h @@ -181,8 +181,11 @@ class Monitor { REQUIRES_SHARED(Locks::mutator_lock_) NO_THREAD_SAFETY_ANALYSIS; // For m->Install(self) - void LogContentionEvent(Thread* self, uint32_t wait_ms, uint32_t sample_percent, - const char* owner_filename, int32_t owner_line_number) + void LogContentionEvent(Thread* self, + uint32_t wait_ms, + uint32_t sample_percent, + ArtMethod* owner_method, + uint32_t owner_dex_pc) REQUIRES_SHARED(Locks::mutator_lock_); static void FailedUnlock(mirror::Object* obj, diff --git a/runtime/monitor_android.cc b/runtime/monitor_android.cc index 1dd60f8d78..7ba36529fc 100644 --- a/runtime/monitor_android.cc +++ b/runtime/monitor_android.cc @@ -22,89 +22,79 @@ #include <sys/types.h> #include <log/log.h> +#include <log/log_event_list.h> #define EVENT_LOG_TAG_dvm_lock_sample 20003 namespace art { -static void Set4LE(uint8_t* buf, uint32_t val) { - *buf++ = (uint8_t)(val); - *buf++ = (uint8_t)(val >> 8); - *buf++ = (uint8_t)(val >> 16); - *buf = (uint8_t)(val >> 24); -} +void Monitor::LogContentionEvent(Thread* self, + uint32_t wait_ms, + uint32_t sample_percent, + ArtMethod* owner_method, + uint32_t owner_dex_pc) { + android_log_event_list ctx(EVENT_LOG_TAG_dvm_lock_sample); -static char* EventLogWriteInt(char* dst, int value) { - *dst++ = EVENT_TYPE_INT; - Set4LE(reinterpret_cast<uint8_t*>(dst), value); - return dst + 4; -} + const char* owner_filename; + int32_t owner_line_number; + TranslateLocation(owner_method, owner_dex_pc, &owner_filename, &owner_line_number); -static char* EventLogWriteString(char* dst, const char* value, size_t len) { - *dst++ = EVENT_TYPE_STRING; - len = len < 32 ? len : 32; - Set4LE(reinterpret_cast<uint8_t*>(dst), len); - dst += 4; - memcpy(dst, value, len); - return dst + len; -} + // Emit the process name, <= 37 bytes. + { + int fd = open("/proc/self/cmdline", O_RDONLY); + char procName[33]; + memset(procName, 0, sizeof(procName)); + read(fd, procName, sizeof(procName) - 1); + close(fd); + ctx << procName; + } + + // Emit the sensitive thread ("main thread") status. We follow tradition that this corresponds + // to a C++ bool's value, but be explicit. + constexpr uint32_t kIsSensitive = 1u; + constexpr uint32_t kIsNotSensitive = 0u; + ctx << (Thread::IsSensitiveThread() ? kIsSensitive : kIsNotSensitive); + + // Emit self thread name string. + { + std::string thread_name; + self->GetThreadName(thread_name); + ctx << thread_name; + } -void Monitor::LogContentionEvent(Thread* self, uint32_t wait_ms, uint32_t sample_percent, - const char* owner_filename, int32_t owner_line_number) { - // Emit the event list length, 1 byte. - char eventBuffer[174]; - char* cp = eventBuffer; - *cp++ = 9; + // Emit the wait time. + ctx << wait_ms; - // Emit the process name, <= 37 bytes. - int fd = open("/proc/self/cmdline", O_RDONLY); - char procName[33]; - memset(procName, 0, sizeof(procName)); - read(fd, procName, sizeof(procName) - 1); - close(fd); - size_t len = strlen(procName); - cp = EventLogWriteString(cp, procName, len); - - // Emit the sensitive thread ("main thread") status, 5 bytes. - cp = EventLogWriteInt(cp, Thread::IsSensitiveThread()); - - // Emit self thread name string, <= 37 bytes. - std::string thread_name; - self->GetThreadName(thread_name); - cp = EventLogWriteString(cp, thread_name.c_str(), thread_name.size()); - - // Emit the wait time, 5 bytes. - cp = EventLogWriteInt(cp, wait_ms); - - // Emit the source code file name, <= 37 bytes. - uint32_t pc; - ArtMethod* m = self->GetCurrentMethod(&pc); - const char* filename; - int32_t line_number; - TranslateLocation(m, pc, &filename, &line_number); - cp = EventLogWriteString(cp, filename, strlen(filename)); - - // Emit the source code line number, 5 bytes. - cp = EventLogWriteInt(cp, line_number); - - // Emit the lock owner source code file name, <= 37 bytes. + const char* filename = nullptr; + { + uint32_t pc; + ArtMethod* m = self->GetCurrentMethod(&pc); + int32_t line_number; + TranslateLocation(m, pc, &filename, &line_number); + + // Emit the source code file name. + ctx << filename; + + // Emit the source code line number. + ctx << line_number; + } + + // Emit the lock owner source code file name. if (owner_filename == nullptr) { owner_filename = ""; } else if (strcmp(filename, owner_filename) == 0) { // Common case, so save on log space. owner_filename = "-"; } - cp = EventLogWriteString(cp, owner_filename, strlen(owner_filename)); + ctx << owner_filename; - // Emit the source code line number, 5 bytes. - cp = EventLogWriteInt(cp, owner_line_number); + // Emit the source code line number. + ctx << owner_line_number; - // Emit the sample percentage, 5 bytes. - cp = EventLogWriteInt(cp, sample_percent); + // Emit the sample percentage. + ctx << sample_percent; - CHECK_LE((size_t)(cp - eventBuffer), sizeof(eventBuffer)); - android_btWriteLog(EVENT_LOG_TAG_dvm_lock_sample, EVENT_TYPE_LIST, eventBuffer, - (size_t)(cp - eventBuffer)); + ctx << LOG_ID_EVENTS; } } // namespace art diff --git a/runtime/monitor_linux.cc b/runtime/monitor_linux.cc index 1c77ac0eb3..667866149b 100644 --- a/runtime/monitor_linux.cc +++ b/runtime/monitor_linux.cc @@ -18,7 +18,7 @@ namespace art { -void Monitor::LogContentionEvent(Thread*, uint32_t, uint32_t, const char*, int32_t) { +void Monitor::LogContentionEvent(Thread*, uint32_t, uint32_t, ArtMethod*, uint32_t) { } } // namespace art diff --git a/runtime/monitor_pool.cc b/runtime/monitor_pool.cc index 0f4e2387cc..48e9a6b47d 100644 --- a/runtime/monitor_pool.cc +++ b/runtime/monitor_pool.cc @@ -18,7 +18,7 @@ #include "base/logging.h" #include "base/mutex-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "monitor.h" namespace art { diff --git a/runtime/monitor_pool_test.cc b/runtime/monitor_pool_test.cc index a111c6c16a..5463877b83 100644 --- a/runtime/monitor_pool_test.cc +++ b/runtime/monitor_pool_test.cc @@ -18,7 +18,7 @@ #include "common_runtime_test.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index 870402d301..ad009668bf 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -31,6 +31,7 @@ #include "mirror/class_loader.h" #include "mirror/object-inl.h" #include "mirror/string.h" +#include "native_util.h" #include "oat_file.h" #include "oat_file_assistant.h" #include "oat_file_manager.h" diff --git a/runtime/native/dalvik_system_VMDebug.cc b/runtime/native/dalvik_system_VMDebug.cc index bb8233b9e8..e1eae21df9 100644 --- a/runtime/native/dalvik_system_VMDebug.cc +++ b/runtime/native/dalvik_system_VMDebug.cc @@ -39,6 +39,7 @@ #include "jni_internal.h" #include "mirror/class.h" #include "mirror/object_array-inl.h" +#include "native_util.h" #include "ScopedLocalRef.h" #include "ScopedUtfChars.h" #include "scoped_fast_native_object_access-inl.h" diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 18b871cca3..fed9c1cf5b 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -52,6 +52,7 @@ extern "C" void android_set_application_target_sdk_version(uint32_t version); #include "mirror/class-inl.h" #include "mirror/dex_cache-inl.h" #include "mirror/object-inl.h" +#include "native_util.h" #include "runtime.h" #include "scoped_fast_native_object_access-inl.h" #include "scoped_thread_state_change-inl.h" diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc index 6c41d515de..e86e64ed6a 100644 --- a/runtime/native/dalvik_system_VMStack.cc +++ b/runtime/native/dalvik_system_VMStack.cc @@ -25,6 +25,7 @@ #include "mirror/class-inl.h" #include "mirror/class_loader.h" #include "mirror/object-inl.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" #include "scoped_thread_state_change-inl.h" #include "thread_list.h" diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc index 4c6f53081a..31aeba06f9 100644 --- a/runtime/native/dalvik_system_ZygoteHooks.cc +++ b/runtime/native/dalvik_system_ZygoteHooks.cc @@ -28,10 +28,12 @@ #include "jit/jit.h" #include "jni_internal.h" #include "JNIHelp.h" +#include "native_util.h" #include "non_debuggable_classes.h" #include "scoped_thread_state_change-inl.h" #include "ScopedUtfChars.h" -#include "thread-inl.h" +#include "stack.h" +#include "thread-current-inl.h" #include "thread_list.h" #include "trace.h" diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index 9e07a5c1a4..d3377be393 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -36,6 +36,7 @@ #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" #include "mirror/string-inl.h" +#include "native_util.h" #include "obj_ptr-inl.h" #include "reflection.h" #include "scoped_thread_state_change-inl.h" diff --git a/runtime/native/java_lang_Object.cc b/runtime/native/java_lang_Object.cc index c9841d1b23..d52bf0490b 100644 --- a/runtime/native/java_lang_Object.cc +++ b/runtime/native/java_lang_Object.cc @@ -20,6 +20,7 @@ #include "jni_internal.h" #include "mirror/object-inl.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" namespace art { diff --git a/runtime/native/java_lang_String.cc b/runtime/native/java_lang_String.cc index 4928c01c96..ac0d6337b2 100644 --- a/runtime/native/java_lang_String.cc +++ b/runtime/native/java_lang_String.cc @@ -24,6 +24,7 @@ #include "mirror/object-inl.h" #include "mirror/string.h" #include "mirror/string-inl.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" #include "scoped_thread_state_change-inl.h" #include "ScopedLocalRef.h" diff --git a/runtime/native/java_lang_StringFactory.cc b/runtime/native/java_lang_StringFactory.cc index c1292ef6c4..9c2e91843e 100644 --- a/runtime/native/java_lang_StringFactory.cc +++ b/runtime/native/java_lang_StringFactory.cc @@ -22,6 +22,7 @@ #include "jni_internal.h" #include "mirror/object-inl.h" #include "mirror/string.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" #include "scoped_thread_state_change-inl.h" #include "ScopedLocalRef.h" diff --git a/runtime/native/java_lang_System.cc b/runtime/native/java_lang_System.cc index 264b427460..0e5d740cab 100644 --- a/runtime/native/java_lang_System.cc +++ b/runtime/native/java_lang_System.cc @@ -26,6 +26,7 @@ #include "mirror/class-inl.h" #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" namespace art { diff --git a/runtime/native/java_lang_Thread.cc b/runtime/native/java_lang_Thread.cc index f3254c4b18..e4d1705d28 100644 --- a/runtime/native/java_lang_Thread.cc +++ b/runtime/native/java_lang_Thread.cc @@ -22,6 +22,7 @@ #include "jni_internal.h" #include "monitor.h" #include "mirror/object.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" #include "scoped_thread_state_change-inl.h" #include "ScopedUtfChars.h" diff --git a/runtime/native/java_lang_Throwable.cc b/runtime/native/java_lang_Throwable.cc index b69fbef8d8..03b7f9dfba 100644 --- a/runtime/native/java_lang_Throwable.cc +++ b/runtime/native/java_lang_Throwable.cc @@ -19,6 +19,7 @@ #include "nativehelper/jni_macros.h" #include "jni_internal.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" #include "thread.h" diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc index 55955e7c57..fc50d5584d 100644 --- a/runtime/native/java_lang_VMClassLoader.cc +++ b/runtime/native/java_lang_VMClassLoader.cc @@ -22,6 +22,7 @@ #include "jni_internal.h" #include "mirror/class_loader.h" #include "mirror/object-inl.h" +#include "native_util.h" #include "obj_ptr.h" #include "scoped_fast_native_object_access-inl.h" #include "ScopedLocalRef.h" diff --git a/runtime/native/java_lang_Void.cc b/runtime/native/java_lang_Void.cc index b0d63ef222..af83dd1a79 100644 --- a/runtime/native/java_lang_Void.cc +++ b/runtime/native/java_lang_Void.cc @@ -20,6 +20,7 @@ #include "class_linker-inl.h" #include "jni_internal.h" +#include "native_util.h" #include "runtime.h" #include "scoped_fast_native_object_access-inl.h" diff --git a/runtime/native/java_lang_invoke_MethodHandleImpl.cc b/runtime/native/java_lang_invoke_MethodHandleImpl.cc index 63168cec24..2e3b4d41ef 100644 --- a/runtime/native/java_lang_invoke_MethodHandleImpl.cc +++ b/runtime/native/java_lang_invoke_MethodHandleImpl.cc @@ -24,6 +24,7 @@ #include "mirror/field.h" #include "mirror/method.h" #include "mirror/method_handle_impl.h" +#include "native_util.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" diff --git a/runtime/native/java_lang_ref_FinalizerReference.cc b/runtime/native/java_lang_ref_FinalizerReference.cc index c75837aa96..72af5f7ea7 100644 --- a/runtime/native/java_lang_ref_FinalizerReference.cc +++ b/runtime/native/java_lang_ref_FinalizerReference.cc @@ -23,6 +23,7 @@ #include "jni_internal.h" #include "mirror/object-inl.h" #include "mirror/reference-inl.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" namespace art { diff --git a/runtime/native/java_lang_ref_Reference.cc b/runtime/native/java_lang_ref_Reference.cc index 606e656f3c..524a18ca20 100644 --- a/runtime/native/java_lang_ref_Reference.cc +++ b/runtime/native/java_lang_ref_Reference.cc @@ -23,6 +23,7 @@ #include "jni_internal.h" #include "mirror/object-inl.h" #include "mirror/reference-inl.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" namespace art { diff --git a/runtime/native/java_lang_reflect_Array.cc b/runtime/native/java_lang_reflect_Array.cc index 96623950aa..5be317147b 100644 --- a/runtime/native/java_lang_reflect_Array.cc +++ b/runtime/native/java_lang_reflect_Array.cc @@ -21,11 +21,12 @@ #include "class_linker-inl.h" #include "common_throws.h" #include "dex_file-inl.h" +#include "handle_scope-inl.h" #include "jni_internal.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" -#include "handle_scope-inl.h" namespace art { diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc index d1953adacf..242e87afa9 100644 --- a/runtime/native/java_lang_reflect_Constructor.cc +++ b/runtime/native/java_lang_reflect_Constructor.cc @@ -27,6 +27,7 @@ #include "mirror/class-inl.h" #include "mirror/method.h" #include "mirror/object-inl.h" +#include "native_util.h" #include "reflection.h" #include "scoped_fast_native_object_access-inl.h" #include "well_known_classes.h" diff --git a/runtime/native/java_lang_reflect_Executable.cc b/runtime/native/java_lang_reflect_Executable.cc index 256a3d04de..2aad12d3b8 100644 --- a/runtime/native/java_lang_reflect_Executable.cc +++ b/runtime/native/java_lang_reflect_Executable.cc @@ -27,6 +27,7 @@ #include "mirror/method.h" #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" +#include "native_util.h" #include "reflection.h" #include "scoped_fast_native_object_access-inl.h" #include "well_known_classes.h" diff --git a/runtime/native/java_lang_reflect_Field.cc b/runtime/native/java_lang_reflect_Field.cc index e38bcd691a..f19004dab5 100644 --- a/runtime/native/java_lang_reflect_Field.cc +++ b/runtime/native/java_lang_reflect_Field.cc @@ -28,6 +28,7 @@ #include "jni_internal.h" #include "mirror/class-inl.h" #include "mirror/field.h" +#include "native_util.h" #include "reflection-inl.h" #include "scoped_fast_native_object_access-inl.h" #include "utils.h" diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc index c9e8dba551..cbbb6a8ea3 100644 --- a/runtime/native/java_lang_reflect_Method.cc +++ b/runtime/native/java_lang_reflect_Method.cc @@ -27,6 +27,7 @@ #include "mirror/class-inl.h" #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" +#include "native_util.h" #include "reflection.h" #include "scoped_fast_native_object_access-inl.h" #include "well_known_classes.h" diff --git a/runtime/native/java_lang_reflect_Parameter.cc b/runtime/native/java_lang_reflect_Parameter.cc index 92a7ac9836..c4ab5d69fc 100644 --- a/runtime/native/java_lang_reflect_Parameter.cc +++ b/runtime/native/java_lang_reflect_Parameter.cc @@ -24,6 +24,7 @@ #include "dex_file-inl.h" #include "dex_file_annotations.h" #include "jni_internal.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" #include "utils.h" diff --git a/runtime/native/java_lang_reflect_Proxy.cc b/runtime/native/java_lang_reflect_Proxy.cc index 518aaa7317..691ed28b0b 100644 --- a/runtime/native/java_lang_reflect_Proxy.cc +++ b/runtime/native/java_lang_reflect_Proxy.cc @@ -23,6 +23,7 @@ #include "mirror/class_loader.h" #include "mirror/object_array.h" #include "mirror/string.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" #include "verify_object.h" diff --git a/runtime/native/java_util_concurrent_atomic_AtomicLong.cc b/runtime/native/java_util_concurrent_atomic_AtomicLong.cc index 101f386ff8..bd4b0fec70 100644 --- a/runtime/native/java_util_concurrent_atomic_AtomicLong.cc +++ b/runtime/native/java_util_concurrent_atomic_AtomicLong.cc @@ -21,6 +21,7 @@ #include "arch/instruction_set.h" #include "atomic.h" #include "jni_internal.h" +#include "native_util.h" namespace art { diff --git a/runtime/native/libcore_util_CharsetUtils.cc b/runtime/native/libcore_util_CharsetUtils.cc index c388ea1438..38634e6d0c 100644 --- a/runtime/native/libcore_util_CharsetUtils.cc +++ b/runtime/native/libcore_util_CharsetUtils.cc @@ -23,6 +23,7 @@ #include "jni_internal.h" #include "mirror/string.h" #include "mirror/string-inl.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" #include "ScopedPrimitiveArray.h" #include "unicode/utf16.h" diff --git a/runtime/native/native_util.h b/runtime/native/native_util.h new file mode 100644 index 0000000000..98384e0178 --- /dev/null +++ b/runtime/native/native_util.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2017 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_NATIVE_NATIVE_UTIL_H_ +#define ART_RUNTIME_NATIVE_NATIVE_UTIL_H_ + +#include <jni.h> + +#include "android-base/logging.h" +#include "base/macros.h" +#include "ScopedLocalRef.h" + +namespace art { + +ALWAYS_INLINE inline void RegisterNativeMethodsInternal(JNIEnv* env, + const char* jni_class_name, + const JNINativeMethod* methods, + jint method_count) { + ScopedLocalRef<jclass> c(env, env->FindClass(jni_class_name)); + if (c.get() == nullptr) { + LOG(FATAL) << "Couldn't find class: " << jni_class_name; + } + jint jni_result = env->RegisterNatives(c.get(), methods, method_count); + CHECK_EQ(JNI_OK, jni_result); +} + +#define REGISTER_NATIVE_METHODS(jni_class_name) \ + RegisterNativeMethodsInternal(env, (jni_class_name), gMethods, arraysize(gMethods)) + +} // namespace art + +#endif // ART_RUNTIME_NATIVE_NATIVE_UTIL_H_ diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc index a860977c4c..925b90931c 100644 --- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc +++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmServer.cc @@ -21,6 +21,7 @@ #include "base/logging.h" #include "debugger.h" #include "jni_internal.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" #include "ScopedPrimitiveArray.h" diff --git a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc index 71c5b50216..0a254aca54 100644 --- a/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc +++ b/runtime/native/org_apache_harmony_dalvik_ddmc_DdmVmInternal.cc @@ -23,6 +23,7 @@ #include "debugger.h" #include "gc/heap.h" #include "jni_internal.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" #include "ScopedLocalRef.h" #include "ScopedPrimitiveArray.h" diff --git a/runtime/native/sun_misc_Unsafe.cc b/runtime/native/sun_misc_Unsafe.cc index b42cedfaf0..e78c9da5e5 100644 --- a/runtime/native/sun_misc_Unsafe.cc +++ b/runtime/native/sun_misc_Unsafe.cc @@ -29,9 +29,9 @@ #include "mirror/array.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" +#include "native_util.h" #include "scoped_fast_native_object_access-inl.h" - namespace art { static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, diff --git a/runtime/native_stack_dump.cc b/runtime/native_stack_dump.cc index cbc502487f..cbff0bb2f2 100644 --- a/runtime/native_stack_dump.cc +++ b/runtime/native_stack_dump.cc @@ -45,7 +45,7 @@ #include "base/unix_file/fd_file.h" #include "oat_quick_method_header.h" #include "os.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils.h" #endif diff --git a/runtime/non_debuggable_classes.cc b/runtime/non_debuggable_classes.cc index 829ea65876..9cc7e60fa8 100644 --- a/runtime/non_debuggable_classes.cc +++ b/runtime/non_debuggable_classes.cc @@ -21,7 +21,7 @@ #include "mirror/class-inl.h" #include "obj_ptr-inl.h" #include "ScopedLocalRef.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/oat_file.h b/runtime/oat_file.h index 06c76b5464..a6d2eba354 100644 --- a/runtime/oat_file.h +++ b/runtime/oat_file.h @@ -39,9 +39,10 @@ class BitVector; class ElfFile; template <class MirrorType> class GcRoot; class MemMap; -class OatMethodOffsets; -class OatHeader; class OatDexFile; +class OatHeader; +class OatMethodOffsets; +class OatQuickMethodHeader; class VdexFile; namespace gc { diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index b2b86ee289..c2029165ad 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -28,7 +28,7 @@ #include "oat_file_manager.h" #include "os.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "utils.h" namespace art { diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc index c1cf800e5d..630945a829 100644 --- a/runtime/oat_file_manager.cc +++ b/runtime/oat_file_manager.cc @@ -29,6 +29,7 @@ #include "base/systrace.h" #include "class_linker.h" #include "dex_file-inl.h" +#include "dex_file_tracking_registrar.h" #include "gc/scoped_gc_critical_section.h" #include "gc/space/image_space.h" #include "handle_scope-inl.h" @@ -38,7 +39,7 @@ #include "oat_file_assistant.h" #include "obj_ptr-inl.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" #include "well_known_classes.h" @@ -737,6 +738,11 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat( // Successfully added image space to heap, release the map so that it does not get // freed. image_space.release(); + + // Register for tracking. + for (const auto& dex_file : dex_files) { + dex::tracking::RegisterDexFile(dex_file.get()); + } } else { LOG(INFO) << "Failed to add image file " << temp_error_msg; dex_files.clear(); @@ -756,6 +762,11 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat( if (!added_image_space) { DCHECK(dex_files.empty()); dex_files = oat_file_assistant.LoadDexFiles(*source_oat_file, dex_location); + + // Register for tracking. + for (const auto& dex_file : dex_files) { + dex::tracking::RegisterDexFile(dex_file.get()); + } } if (dex_files.empty()) { error_msgs->push_back("Failed to open dex files from " + source_oat_file->GetLocation()); diff --git a/runtime/obj_ptr-inl.h b/runtime/obj_ptr-inl.h index f2921daeaa..3d9b3c6cf7 100644 --- a/runtime/obj_ptr-inl.h +++ b/runtime/obj_ptr-inl.h @@ -18,7 +18,7 @@ #define ART_RUNTIME_OBJ_PTR_INL_H_ #include "obj_ptr.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc index 9be486e269..45773fdfbf 100644 --- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc +++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc @@ -46,7 +46,7 @@ #include "object_tagging.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" #include "ti_class.h" #include "ti_dump.h" diff --git a/runtime/openjdkjvmti/events.cc b/runtime/openjdkjvmti/events.cc index 0ec92b7c60..320c59c810 100644 --- a/runtime/openjdkjvmti/events.cc +++ b/runtime/openjdkjvmti/events.cc @@ -44,7 +44,7 @@ #include "runtime.h" #include "ScopedLocalRef.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace openjdkjvmti { diff --git a/runtime/openjdkjvmti/jvmti_weak_table.h b/runtime/openjdkjvmti/jvmti_weak_table.h index be6edefae2..01c24b1917 100644 --- a/runtime/openjdkjvmti/jvmti_weak_table.h +++ b/runtime/openjdkjvmti/jvmti_weak_table.h @@ -41,7 +41,7 @@ #include "globals.h" #include "jvmti.h" #include "mirror/object.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace openjdkjvmti { diff --git a/runtime/openjdkjvmti/ti_class.cc b/runtime/openjdkjvmti/ti_class.cc index dd90a71240..0aa93dfb57 100644 --- a/runtime/openjdkjvmti/ti_class.cc +++ b/runtime/openjdkjvmti/ti_class.cc @@ -63,7 +63,7 @@ #include "runtime_callbacks.h" #include "ScopedLocalRef.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" #include "ti_class_loader.h" #include "ti_phase.h" diff --git a/runtime/openjdkjvmti/ti_dump.cc b/runtime/openjdkjvmti/ti_dump.cc index d9e3ef1bcf..7a1e53f6e5 100644 --- a/runtime/openjdkjvmti/ti_dump.cc +++ b/runtime/openjdkjvmti/ti_dump.cc @@ -39,7 +39,7 @@ #include "events-inl.h" #include "runtime_callbacks.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" namespace openjdkjvmti { diff --git a/runtime/openjdkjvmti/ti_field.cc b/runtime/openjdkjvmti/ti_field.cc index 1e5fbda35b..342d8be2b0 100644 --- a/runtime/openjdkjvmti/ti_field.cc +++ b/runtime/openjdkjvmti/ti_field.cc @@ -39,7 +39,7 @@ #include "mirror/object_array-inl.h" #include "modifiers.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace openjdkjvmti { diff --git a/runtime/openjdkjvmti/ti_heap.cc b/runtime/openjdkjvmti/ti_heap.cc index 99774c67b5..319b1c2a9c 100644 --- a/runtime/openjdkjvmti/ti_heap.cc +++ b/runtime/openjdkjvmti/ti_heap.cc @@ -35,6 +35,7 @@ #include "primitive.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" +#include "stack.h" #include "thread-inl.h" #include "thread_list.h" diff --git a/runtime/openjdkjvmti/ti_jni.cc b/runtime/openjdkjvmti/ti_jni.cc index 88f0395ba5..dd2dda118a 100644 --- a/runtime/openjdkjvmti/ti_jni.cc +++ b/runtime/openjdkjvmti/ti_jni.cc @@ -38,7 +38,7 @@ #include "java_vm_ext.h" #include "jni_env_ext.h" #include "runtime.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace openjdkjvmti { diff --git a/runtime/openjdkjvmti/ti_method.cc b/runtime/openjdkjvmti/ti_method.cc index f7e53474aa..beb639e208 100644 --- a/runtime/openjdkjvmti/ti_method.cc +++ b/runtime/openjdkjvmti/ti_method.cc @@ -42,7 +42,7 @@ #include "runtime_callbacks.h" #include "scoped_thread_state_change-inl.h" #include "ScopedLocalRef.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" #include "ti_phase.h" diff --git a/runtime/openjdkjvmti/ti_monitor.cc b/runtime/openjdkjvmti/ti_monitor.cc index 645faea41b..61bf533eb7 100644 --- a/runtime/openjdkjvmti/ti_monitor.cc +++ b/runtime/openjdkjvmti/ti_monitor.cc @@ -39,7 +39,7 @@ #include "art_jvmti.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace openjdkjvmti { diff --git a/runtime/openjdkjvmti/ti_object.cc b/runtime/openjdkjvmti/ti_object.cc index bf84499035..2506acac3a 100644 --- a/runtime/openjdkjvmti/ti_object.cc +++ b/runtime/openjdkjvmti/ti_object.cc @@ -34,7 +34,7 @@ #include "art_jvmti.h" #include "mirror/object-inl.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace openjdkjvmti { diff --git a/runtime/openjdkjvmti/ti_phase.cc b/runtime/openjdkjvmti/ti_phase.cc index 941cf7b73b..3c8bdc61d0 100644 --- a/runtime/openjdkjvmti/ti_phase.cc +++ b/runtime/openjdkjvmti/ti_phase.cc @@ -38,7 +38,7 @@ #include "runtime_callbacks.h" #include "ScopedLocalRef.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" #include "ti_thread.h" diff --git a/runtime/openjdkjvmti/ti_properties.cc b/runtime/openjdkjvmti/ti_properties.cc index 8ee5366140..e399b484ec 100644 --- a/runtime/openjdkjvmti/ti_properties.cc +++ b/runtime/openjdkjvmti/ti_properties.cc @@ -40,7 +40,7 @@ #include "art_jvmti.h" #include "runtime.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "ti_phase.h" #include "well_known_classes.h" diff --git a/runtime/openjdkjvmti/ti_search.cc b/runtime/openjdkjvmti/ti_search.cc index ec139f2004..6e0196edc3 100644 --- a/runtime/openjdkjvmti/ti_search.cc +++ b/runtime/openjdkjvmti/ti_search.cc @@ -49,7 +49,7 @@ #include "scoped_thread_state_change-inl.h" #include "ScopedLocalRef.h" #include "ti_phase.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" #include "well_known_classes.h" diff --git a/runtime/openjdkjvmti/ti_stack.cc b/runtime/openjdkjvmti/ti_stack.cc index 1ddf04feb4..22da2d2f65 100644 --- a/runtime/openjdkjvmti/ti_stack.cc +++ b/runtime/openjdkjvmti/ti_stack.cc @@ -52,7 +52,7 @@ #include "scoped_thread_state_change-inl.h" #include "ScopedLocalRef.h" #include "stack.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" #include "thread_pool.h" #include "well_known_classes.h" diff --git a/runtime/openjdkjvmti/ti_thread.cc b/runtime/openjdkjvmti/ti_thread.cc index 3dfa63313d..2cc2a26c3b 100644 --- a/runtime/openjdkjvmti/ti_thread.cc +++ b/runtime/openjdkjvmti/ti_thread.cc @@ -49,7 +49,7 @@ #include "runtime_callbacks.h" #include "ScopedLocalRef.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" #include "well_known_classes.h" diff --git a/runtime/openjdkjvmti/ti_threadgroup.cc b/runtime/openjdkjvmti/ti_threadgroup.cc index dd7be113d6..c0597ad0cc 100644 --- a/runtime/openjdkjvmti/ti_threadgroup.cc +++ b/runtime/openjdkjvmti/ti_threadgroup.cc @@ -45,7 +45,7 @@ #include "object_lock.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" #include "well_known_classes.h" diff --git a/runtime/read_barrier-inl.h b/runtime/read_barrier-inl.h index db774909dd..2d06e54f78 100644 --- a/runtime/read_barrier-inl.h +++ b/runtime/read_barrier-inl.h @@ -63,7 +63,7 @@ inline MirrorType* ReadBarrier::Barrier( // If kAlwaysUpdateField is true, update the field atomically. This may fail if mutator // updates before us, but it's OK. if (kAlwaysUpdateField && ref != old_ref) { - obj->CasFieldStrongRelaxedObjectWithoutWriteBarrier<false, false>( + obj->CasFieldStrongReleaseObjectWithoutWriteBarrier<false, false>( offset, old_ref, ref); } } @@ -81,7 +81,7 @@ inline MirrorType* ReadBarrier::Barrier( ref = reinterpret_cast<MirrorType*>(Mark(old_ref)); // Update the field atomically. This may fail if mutator updates before us, but it's ok. if (ref != old_ref) { - obj->CasFieldStrongRelaxedObjectWithoutWriteBarrier<false, false>( + obj->CasFieldStrongReleaseObjectWithoutWriteBarrier<false, false>( offset, old_ref, ref); } } diff --git a/runtime/reference_table_test.cc b/runtime/reference_table_test.cc index e809ecf1f6..260be8f41f 100644 --- a/runtime/reference_table_test.cc +++ b/runtime/reference_table_test.cc @@ -29,7 +29,7 @@ #include "primitive.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/runtime_common.cc b/runtime/runtime_common.cc index 5511fb7b6d..940e4611f6 100644 --- a/runtime/runtime_common.cc +++ b/runtime/runtime_common.cc @@ -29,7 +29,8 @@ #include "base/macros.h" #include "base/mutex.h" #include "native_stack_dump.h" -#include "thread-inl.h" +#include "runtime.h" +#include "thread-current-inl.h" #include "thread_list.h" namespace art { diff --git a/runtime/safe_map.h b/runtime/safe_map.h index e638fdb504..b54f587715 100644 --- a/runtime/safe_map.h +++ b/runtime/safe_map.h @@ -46,6 +46,7 @@ class SafeMap { SafeMap() = default; SafeMap(const SafeMap&) = default; + SafeMap(SafeMap&&) = default; explicit SafeMap(const key_compare& cmp, const allocator_type& allocator = allocator_type()) : map_(cmp, allocator) { } @@ -151,6 +152,11 @@ class SafeMap { return map_ == rhs.map_; } + template <class... Args> + std::pair<iterator, bool> emplace(Args&&... args) { + return map_.emplace(std::forward<Args>(args)...); + } + private: ::std::map<K, V, Comparator, Allocator> map_; }; diff --git a/runtime/scoped_thread_state_change-inl.h b/runtime/scoped_thread_state_change-inl.h index ed6e349de4..aa96871145 100644 --- a/runtime/scoped_thread_state_change-inl.h +++ b/runtime/scoped_thread_state_change-inl.h @@ -22,6 +22,7 @@ #include "base/casts.h" #include "jni_env_ext-inl.h" #include "obj_ptr-inl.h" +#include "runtime.h" #include "thread-inl.h" namespace art { diff --git a/runtime/stack.cc b/runtime/stack.cc index 5c6eead34b..8fcac1ea7f 100644 --- a/runtime/stack.cc +++ b/runtime/stack.cc @@ -29,6 +29,7 @@ #include "jit/jit.h" #include "jit/jit_code_cache.h" #include "linear_alloc.h" +#include "managed_stack.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" @@ -68,34 +69,6 @@ mirror::Object* ShadowFrame::GetThisObject(uint16_t num_ins) const { } } -size_t ManagedStack::NumJniShadowFrameReferences() const { - size_t count = 0; - for (const ManagedStack* current_fragment = this; current_fragment != nullptr; - current_fragment = current_fragment->GetLink()) { - for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_; current_frame != nullptr; - current_frame = current_frame->GetLink()) { - if (current_frame->GetMethod()->IsNative()) { - // The JNI ShadowFrame only contains references. (For indirect reference.) - count += current_frame->NumberOfVRegs(); - } - } - } - return count; -} - -bool ManagedStack::ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const { - for (const ManagedStack* current_fragment = this; current_fragment != nullptr; - current_fragment = current_fragment->GetLink()) { - for (ShadowFrame* current_frame = current_fragment->top_shadow_frame_; current_frame != nullptr; - current_frame = current_frame->GetLink()) { - if (current_frame->Contains(shadow_frame_entry)) { - return true; - } - } - } - return false; -} - StackVisitor::StackVisitor(Thread* thread, Context* context, StackWalkKind walk_kind, diff --git a/runtime/stack.h b/runtime/stack.h index bdaa4c3ca2..8c74a8c405 100644 --- a/runtime/stack.h +++ b/runtime/stack.h @@ -512,86 +512,6 @@ class JavaFrameRootInfo FINAL : public RootInfo { const size_t vreg_; }; -// The managed stack is used to record fragments of managed code stacks. Managed code stacks -// may either be shadow frames or lists of frames using fixed frame sizes. Transition records are -// necessary for transitions between code using different frame layouts and transitions into native -// code. -class PACKED(4) ManagedStack { - public: - ManagedStack() - : top_quick_frame_(nullptr), link_(nullptr), top_shadow_frame_(nullptr) {} - - void PushManagedStackFragment(ManagedStack* fragment) { - // Copy this top fragment into given fragment. - memcpy(fragment, this, sizeof(ManagedStack)); - // Clear this fragment, which has become the top. - memset(this, 0, sizeof(ManagedStack)); - // Link our top fragment onto the given fragment. - link_ = fragment; - } - - void PopManagedStackFragment(const ManagedStack& fragment) { - DCHECK(&fragment == link_); - // Copy this given fragment back to the top. - memcpy(this, &fragment, sizeof(ManagedStack)); - } - - ManagedStack* GetLink() const { - return link_; - } - - ArtMethod** GetTopQuickFrame() const { - return top_quick_frame_; - } - - void SetTopQuickFrame(ArtMethod** top) { - DCHECK(top_shadow_frame_ == nullptr); - top_quick_frame_ = top; - } - - static size_t TopQuickFrameOffset() { - return OFFSETOF_MEMBER(ManagedStack, top_quick_frame_); - } - - ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame) { - DCHECK(top_quick_frame_ == nullptr); - ShadowFrame* old_frame = top_shadow_frame_; - top_shadow_frame_ = new_top_frame; - new_top_frame->SetLink(old_frame); - return old_frame; - } - - ShadowFrame* PopShadowFrame() { - DCHECK(top_quick_frame_ == nullptr); - CHECK(top_shadow_frame_ != nullptr); - ShadowFrame* frame = top_shadow_frame_; - top_shadow_frame_ = frame->GetLink(); - return frame; - } - - ShadowFrame* GetTopShadowFrame() const { - return top_shadow_frame_; - } - - void SetTopShadowFrame(ShadowFrame* top) { - DCHECK(top_quick_frame_ == nullptr); - top_shadow_frame_ = top; - } - - static size_t TopShadowFrameOffset() { - return OFFSETOF_MEMBER(ManagedStack, top_shadow_frame_); - } - - size_t NumJniShadowFrameReferences() const REQUIRES_SHARED(Locks::mutator_lock_); - - bool ShadowFramesContain(StackReference<mirror::Object>* shadow_frame_entry) const; - - private: - ArtMethod** top_quick_frame_; - ManagedStack* link_; - ShadowFrame* top_shadow_frame_; -}; - class StackVisitor { public: // This enum defines a flag to control whether inlined frames are included diff --git a/runtime/thread-current-inl.h b/runtime/thread-current-inl.h new file mode 100644 index 0000000000..9241b1f875 --- /dev/null +++ b/runtime/thread-current-inl.h @@ -0,0 +1,47 @@ +/* + * 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_THREAD_CURRENT_INL_H_ +#define ART_RUNTIME_THREAD_CURRENT_INL_H_ + +#include "thread.h" + +#ifdef ART_TARGET_ANDROID +#include <bionic_tls.h> // Access to our own TLS slot. +#endif + +#include <pthread.h> + +namespace art { + +inline Thread* Thread::Current() { + // We rely on Thread::Current returning null for a detached thread, so it's not obvious + // that we can replace this with a direct %fs access on x86. + if (!is_started_) { + return nullptr; + } else { +#ifdef ART_TARGET_ANDROID + void* thread = __get_tls()[TLS_SLOT_ART_THREAD_SELF]; +#else + void* thread = pthread_getspecific(Thread::pthread_key_self_); +#endif + return reinterpret_cast<Thread*>(thread); + } +} + +} // namespace art + +#endif // ART_RUNTIME_THREAD_CURRENT_INL_H_ diff --git a/runtime/thread-inl.h b/runtime/thread-inl.h index 5c65da6d41..7da15d9f4c 100644 --- a/runtime/thread-inl.h +++ b/runtime/thread-inl.h @@ -19,18 +19,13 @@ #include "thread.h" -#ifdef ART_TARGET_ANDROID -#include <bionic_tls.h> // Access to our own TLS slot. -#endif - -#include <pthread.h> - #include "base/casts.h" #include "base/mutex-inl.h" #include "base/time_utils.h" #include "jni_env_ext.h" +#include "managed_stack-inl.h" #include "obj_ptr.h" -#include "runtime.h" +#include "thread-current-inl.h" #include "thread_pool.h" namespace art { @@ -41,21 +36,6 @@ static inline Thread* ThreadForEnv(JNIEnv* env) { return full_env->self; } -inline Thread* Thread::Current() { - // We rely on Thread::Current returning null for a detached thread, so it's not obvious - // that we can replace this with a direct %fs access on x86. - if (!is_started_) { - return nullptr; - } else { -#ifdef ART_TARGET_ANDROID - void* thread = __get_tls()[TLS_SLOT_ART_THREAD_SELF]; -#else - void* thread = pthread_getspecific(Thread::pthread_key_self_); -#endif - return reinterpret_cast<Thread*>(thread); - } -} - inline void Thread::AllowThreadSuspension() { DCHECK_EQ(Thread::Current(), this); if (UNLIKELY(TestAllFlags())) { @@ -295,12 +275,6 @@ inline ThreadState Thread::TransitionFromSuspendedToRunnable() { return static_cast<ThreadState>(old_state); } -inline void Thread::VerifyStack() { - if (kVerifyStack) { - VerifyStackImpl(); - } -} - inline mirror::Object* Thread::AllocTlab(size_t bytes) { DCHECK_GE(TlabSize(), bytes); ++tlsPtr_.thread_local_objects; @@ -384,6 +358,14 @@ inline bool Thread::ModifySuspendCount(Thread* self, } } +inline ShadowFrame* Thread::PushShadowFrame(ShadowFrame* new_top_frame) { + return tlsPtr_.managed_stack.PushShadowFrame(new_top_frame); +} + +inline ShadowFrame* Thread::PopShadowFrame() { + return tlsPtr_.managed_stack.PopShadowFrame(); +} + } // namespace art #endif // ART_RUNTIME_THREAD_INL_H_ diff --git a/runtime/thread.cc b/runtime/thread.cc index c849a126ae..789f571253 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -55,6 +55,7 @@ #include "gc/allocator/rosalloc.h" #include "gc/heap.h" #include "gc/space/space-inl.h" +#include "gc_root.h" #include "handle_scope-inl.h" #include "indirect_reference_table-inl.h" #include "java_vm_ext.h" @@ -2160,7 +2161,7 @@ Thread::~Thread() { TearDownAlternateSignalStack(); } -void Thread::HandleUncaughtExceptions(ScopedObjectAccess& soa) { +void Thread::HandleUncaughtExceptions(ScopedObjectAccessAlreadyRunnable& soa) { if (!IsExceptionPending()) { return; } @@ -2180,7 +2181,7 @@ void Thread::HandleUncaughtExceptions(ScopedObjectAccess& soa) { tlsPtr_.jni_env->ExceptionClear(); } -void Thread::RemoveFromThreadGroup(ScopedObjectAccess& soa) { +void Thread::RemoveFromThreadGroup(ScopedObjectAccessAlreadyRunnable& soa) { // this.group.removeThread(this); // group can be null if we're in the compiler or a test. ObjPtr<mirror::Object> ogroup = jni::DecodeArtField(WellKnownClasses::java_lang_Thread_group) diff --git a/runtime/thread.h b/runtime/thread.h index a60fd58ca0..e85ee0d2f3 100644 --- a/runtime/thread.h +++ b/runtime/thread.h @@ -33,15 +33,13 @@ #include "base/mutex.h" #include "entrypoints/jni/jni_entrypoints.h" #include "entrypoints/quick/quick_entrypoints.h" -#include "gc_root.h" #include "globals.h" #include "handle_scope.h" #include "instrumentation.h" #include "jvalue.h" -#include "object_callbacks.h" +#include "managed_stack.h" #include "offsets.h" #include "runtime_stats.h" -#include "stack.h" #include "thread_state.h" class BacktraceMap; @@ -87,12 +85,14 @@ class FrameIdToShadowFrame; class JavaVMExt; struct JNIEnvExt; class Monitor; +class RootVisitor; class ScopedObjectAccessAlreadyRunnable; class ShadowFrame; class SingleStepControl; class StackedShadowFrameRecord; class Thread; class ThreadList; +enum VisitRootFlags : uint8_t; // Thread priorities. These must match the Thread.MIN_PRIORITY, // Thread.NORM_PRIORITY, and Thread.MAX_PRIORITY constants. @@ -149,6 +149,7 @@ static constexpr size_t kNumRosAllocThreadLocalSizeBracketsInThread = 16; class Thread { public: static const size_t kStackOverflowImplicitCheckSize; + static constexpr bool kVerifyStack = kIsDebugBuild; // Creates a new native thread corresponding to the given managed peer. // Used to implement Thread.start. @@ -560,10 +561,14 @@ class Thread { return tlsPtr_.frame_id_to_shadow_frame != nullptr; } - void VisitRoots(RootVisitor* visitor, VisitRootFlags flags = kVisitRootFlagAllRoots) + void VisitRoots(RootVisitor* visitor, VisitRootFlags flags) REQUIRES_SHARED(Locks::mutator_lock_); - ALWAYS_INLINE void VerifyStack() REQUIRES_SHARED(Locks::mutator_lock_); + void VerifyStack() REQUIRES_SHARED(Locks::mutator_lock_) { + if (kVerifyStack) { + VerifyStackImpl(); + } + } // // Offsets of various members of native Thread class, used by compiled code. @@ -793,13 +798,8 @@ class Thread { tlsPtr_.managed_stack.PopManagedStackFragment(fragment); } - ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame) { - return tlsPtr_.managed_stack.PushShadowFrame(new_top_frame); - } - - ShadowFrame* PopShadowFrame() { - return tlsPtr_.managed_stack.PopShadowFrame(); - } + ALWAYS_INLINE ShadowFrame* PushShadowFrame(ShadowFrame* new_top_frame); + ALWAYS_INLINE ShadowFrame* PopShadowFrame(); template<PointerSize pointer_size> static ThreadOffset<pointer_size> TopShadowFrameOffset() { @@ -1250,9 +1250,10 @@ class Thread { static void* CreateCallback(void* arg); - void HandleUncaughtExceptions(ScopedObjectAccess& soa) + void HandleUncaughtExceptions(ScopedObjectAccessAlreadyRunnable& soa) + REQUIRES_SHARED(Locks::mutator_lock_); + void RemoveFromThreadGroup(ScopedObjectAccessAlreadyRunnable& soa) REQUIRES_SHARED(Locks::mutator_lock_); - void RemoveFromThreadGroup(ScopedObjectAccess& soa) REQUIRES_SHARED(Locks::mutator_lock_); // Initialize a thread. // diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc index ca8f7b648c..5094189dfc 100644 --- a/runtime/thread_list.cc +++ b/runtime/thread_list.cc @@ -37,6 +37,7 @@ #include "gc/gc_pause_listener.h" #include "gc/heap.h" #include "gc/reference_processor.h" +#include "gc_root.h" #include "jni_internal.h" #include "lock_word.h" #include "monitor.h" @@ -757,7 +758,7 @@ void ThreadList::SuspendAllInternal(Thread* self, // EAGAIN and EINTR both indicate a spurious failure, try again from the beginning. if ((errno != EAGAIN) && (errno != EINTR)) { if (errno == ETIMEDOUT) { - LOG(::android::base::FATAL) + LOG(kIsDebugBuild ? ::android::base::FATAL : ::android::base::ERROR) << "Timed out waiting for threads to suspend, waited for " << PrettyDuration(NanoTime() - start_time); } else { @@ -1509,7 +1510,7 @@ void ThreadList::VisitRootsForSuspendedThreads(RootVisitor* visitor) { // Visit roots without holding thread_list_lock_ and thread_suspend_count_lock_ to prevent lock // order violations. for (Thread* thread : threads_to_visit) { - thread->VisitRoots(visitor); + thread->VisitRoots(visitor, kVisitRootFlagAllRoots); } // Restore suspend counts. diff --git a/runtime/thread_list.h b/runtime/thread_list.h index 0ce1d78382..92702c6498 100644 --- a/runtime/thread_list.h +++ b/runtime/thread_list.h @@ -22,9 +22,7 @@ #include "base/mutex.h" #include "base/time_utils.h" #include "base/value_object.h" -#include "gc_root.h" #include "jni.h" -#include "object_callbacks.h" #include <bitset> #include <list> @@ -38,8 +36,10 @@ namespace gc { class GcPauseListener; } // namespace gc class Closure; +class RootVisitor; class Thread; class TimingLogger; +enum VisitRootFlags : uint8_t; class ThreadList { public: diff --git a/runtime/thread_pool.cc b/runtime/thread_pool.cc index e051e7647f..8349f33028 100644 --- a/runtime/thread_pool.cc +++ b/runtime/thread_pool.cc @@ -30,7 +30,7 @@ #include "base/stl_util.h" #include "base/time_utils.h" #include "runtime.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/runtime/trace.cc b/runtime/trace.cc index 3a9975a4e2..3550d56bd8 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -41,6 +41,7 @@ #include "os.h" #include "scoped_thread_state_change-inl.h" #include "ScopedLocalRef.h" +#include "stack.h" #include "thread.h" #include "thread_list.h" #include "utils.h" diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 7490611cb6..12f791c1f1 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -50,6 +50,7 @@ #include "register_line-inl.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" +#include "stack.h" #include "utils.h" #include "verifier_deps.h" #include "verifier_compiler_binding.h" @@ -883,10 +884,13 @@ bool MethodVerifier::Verify() { InstructionFlags()); // Run through the instructions and see if the width checks out. bool result = ComputeWidthsAndCountOps(); + bool allow_runtime_only_instructions = !Runtime::Current()->IsAotCompiler() || verify_to_dump_; // Flag instructions guarded by a "try" block and check exception handlers. result = result && ScanTryCatchBlocks(); // Perform static instruction verification. - result = result && VerifyInstructions(); + result = result && (allow_runtime_only_instructions + ? VerifyInstructions<true>() + : VerifyInstructions<false>()); // Perform code-flow analysis and return. result = result && VerifyCodeFlow(); @@ -1102,6 +1106,7 @@ bool MethodVerifier::ScanTryCatchBlocks() { return true; } +template <bool kAllowRuntimeOnlyInstructions> bool MethodVerifier::VerifyInstructions() { const Instruction* inst = Instruction::At(code_item_->insns_); @@ -1110,9 +1115,8 @@ bool MethodVerifier::VerifyInstructions() { GetInstructionFlags(0).SetCompileTimeInfoPoint(); uint32_t insns_size = code_item_->insns_size_in_code_units_; - bool allow_runtime_only_instructions = !Runtime::Current()->IsAotCompiler() || verify_to_dump_; for (uint32_t dex_pc = 0; dex_pc < insns_size;) { - if (!VerifyInstruction(inst, dex_pc, allow_runtime_only_instructions)) { + if (!VerifyInstruction<kAllowRuntimeOnlyInstructions>(inst, dex_pc)) { DCHECK_NE(failures_.size(), 0U); return false; } @@ -1139,9 +1143,8 @@ bool MethodVerifier::VerifyInstructions() { return true; } -bool MethodVerifier::VerifyInstruction(const Instruction* inst, - uint32_t code_offset, - bool allow_runtime_only_instructions) { +template <bool kAllowRuntimeOnlyInstructions> +bool MethodVerifier::VerifyInstruction(const Instruction* inst, uint32_t code_offset) { if (Instruction::kHaveExperimentalInstructions && UNLIKELY(inst->IsExperimental())) { // Experimental instructions don't yet have verifier support implementation. // While it is possible to use them by themselves, when we try to use stable instructions @@ -1250,7 +1253,7 @@ bool MethodVerifier::VerifyInstruction(const Instruction* inst, result = false; break; } - if (!allow_runtime_only_instructions && inst->GetVerifyIsRuntimeOnly()) { + if (!kAllowRuntimeOnlyInstructions && inst->GetVerifyIsRuntimeOnly()) { Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "opcode only expected at runtime " << inst->Name(); result = false; } diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 9ef98f70e4..cb208f44a5 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -360,6 +360,7 @@ class MethodVerifier { * * Walks through instructions in a method calling VerifyInstruction on each. */ + template <bool kAllowRuntimeOnlyInstructions> bool VerifyInstructions(); /* @@ -395,9 +396,8 @@ class MethodVerifier { * - (earlier) for each exception handler, the handler must start at a valid * instruction */ - bool VerifyInstruction(const Instruction* inst, - uint32_t code_offset, - bool allow_runtime_only_instructions); + template <bool kAllowRuntimeOnlyInstructions> + bool VerifyInstruction(const Instruction* inst, uint32_t code_offset); /* Ensure that the register index is valid for this code item. */ bool CheckRegisterIndex(uint32_t idx); diff --git a/runtime/verifier/reg_type_test.cc b/runtime/verifier/reg_type_test.cc index 49dac26bb4..b0ea6c857c 100644 --- a/runtime/verifier/reg_type_test.cc +++ b/runtime/verifier/reg_type_test.cc @@ -25,7 +25,7 @@ #include "reg_type_cache-inl.h" #include "reg_type-inl.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace verifier { diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h index 70ce0c4a29..43eb948c64 100644 --- a/runtime/verifier/verifier_deps.h +++ b/runtime/verifier/verifier_deps.h @@ -23,6 +23,7 @@ #include "base/array_ref.h" #include "base/mutex.h" +#include "dex_file_types.h" #include "handle.h" #include "method_resolution_kind.h" #include "obj_ptr.h" diff --git a/runtime/verify_object.h b/runtime/verify_object.h index 519f7f5f5a..e4c01d0f78 100644 --- a/runtime/verify_object.h +++ b/runtime/verify_object.h @@ -48,7 +48,6 @@ enum VerifyObjectFlags { kVerifyAll = kVerifyThis | kVerifyReads | kVerifyWrites, }; -static constexpr bool kVerifyStack = kIsDebugBuild; static constexpr VerifyObjectFlags kDefaultVerifyFlags = kVerifyNone; static constexpr VerifyObjectMode kVerifyObjectSupport = kDefaultVerifyFlags != 0 ? kVerifyObjectModeFast : kVerifyObjectModeDisabled; diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc index 5aef062728..24f194b5ee 100644 --- a/runtime/well_known_classes.cc +++ b/runtime/well_known_classes.cc @@ -30,7 +30,7 @@ #include "obj_ptr-inl.h" #include "ScopedLocalRef.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/test/003-omnibus-opcodes/src/Main.java b/test/003-omnibus-opcodes/src/Main.java index a30ec15c66..4e1ffe2fde 100644 --- a/test/003-omnibus-opcodes/src/Main.java +++ b/test/003-omnibus-opcodes/src/Main.java @@ -67,7 +67,7 @@ public class Main { } catch (Throwable th) { // We and the RI throw ClassNotFoundException, but that isn't declared so javac // won't let us try to catch it. - th.printStackTrace(); + th.printStackTrace(System.out); } InternedString.run(); GenSelect.run(); diff --git a/test/008-exceptions/src/Main.java b/test/008-exceptions/src/Main.java index 74af00ccf7..89fe016856 100644 --- a/test/008-exceptions/src/Main.java +++ b/test/008-exceptions/src/Main.java @@ -155,7 +155,7 @@ public class Main { } catch (BadError e) { System.out.println(e); } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(System.out); } try { // Before splitting mirror::Class::kStatusError into @@ -171,11 +171,11 @@ public class Main { throw new IllegalStateException("Should not reach here."); } catch (NoClassDefFoundError ncdfe) { if (!(ncdfe.getCause() instanceof BadError)) { - ncdfe.getCause().printStackTrace(); + ncdfe.getCause().printStackTrace(System.out); } } catch (VerifyError e) { } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(System.out); } } @@ -186,7 +186,7 @@ public class Main { } catch (Error e) { System.out.println(e); } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(System.out); } // Before splitting mirror::Class::kStatusError into // kStatusErrorUnresolved and kStatusErrorResolved, @@ -200,7 +200,7 @@ public class Main { System.out.println(ncdfe); System.out.println(" cause: " + ncdfe.getCause()); } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(System.out); } try { MultiDexBadInitWrapper2.setDummy(1); @@ -209,7 +209,7 @@ public class Main { System.out.println(ncdfe); System.out.println(" cause: " + ncdfe.getCause()); } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(System.out); } } } diff --git a/test/023-many-interfaces/src/ManyInterfaces.java b/test/023-many-interfaces/src/ManyInterfaces.java index d69a490f67..8ec4566802 100644 --- a/test/023-many-interfaces/src/ManyInterfaces.java +++ b/test/023-many-interfaces/src/ManyInterfaces.java @@ -355,7 +355,7 @@ public class ManyInterfaces static void testInstance001(Object obj, int count) { if (!(obj instanceof Interface001)) - System.err.println("BAD"); + System.out.println("BAD"); while (count-- != 0) { boolean is; is = obj instanceof Interface001; @@ -379,7 +379,7 @@ public class ManyInterfaces static void testInstance049(Object obj, int count) { if (!(obj instanceof Interface049)) - System.err.println("BAD"); + System.out.println("BAD"); while (count-- != 0) { boolean is; is = obj instanceof Interface049; @@ -403,7 +403,7 @@ public class ManyInterfaces static void testInstance099(Object obj, int count) { if (!(obj instanceof Interface099)) - System.err.println("BAD"); + System.out.println("BAD"); while (count-- != 0) { boolean is; is = obj instanceof Interface099; diff --git a/test/024-illegal-access/src/Main.java b/test/024-illegal-access/src/Main.java index 84c7114cb4..de9ad5b694 100644 --- a/test/024-illegal-access/src/Main.java +++ b/test/024-illegal-access/src/Main.java @@ -18,7 +18,7 @@ public class Main { static public void main(String[] args) { try { PublicAccess.accessStaticField(); - System.err.println("ERROR: call 1 not expected to succeed"); + System.out.println("ERROR: call 1 not expected to succeed"); } catch (VerifyError ve) { // dalvik System.out.println("Got expected failure 1"); @@ -29,7 +29,7 @@ public class Main { try { PublicAccess.accessStaticMethod(); - System.err.println("ERROR: call 2 not expected to succeed"); + System.out.println("ERROR: call 2 not expected to succeed"); } catch (IllegalAccessError iae) { // reference System.out.println("Got expected failure 2"); @@ -37,7 +37,7 @@ public class Main { try { PublicAccess.accessInstanceField(); - System.err.println("ERROR: call 3 not expected to succeed"); + System.out.println("ERROR: call 3 not expected to succeed"); } catch (VerifyError ve) { // dalvik System.out.println("Got expected failure 3"); @@ -48,7 +48,7 @@ public class Main { try { PublicAccess.accessInstanceMethod(); - System.err.println("ERROR: call 4 not expected to succeed"); + System.out.println("ERROR: call 4 not expected to succeed"); } catch (IllegalAccessError iae) { // reference System.out.println("Got expected failure 4"); @@ -56,7 +56,7 @@ public class Main { try { CheckInstanceof.main(new Object()); - System.err.println("ERROR: call 5 not expected to succeed"); + System.out.println("ERROR: call 5 not expected to succeed"); } catch (VerifyError ve) { // dalvik System.out.println("Got expected failure 5"); diff --git a/test/031-class-attributes/src/ClassAttrs.java b/test/031-class-attributes/src/ClassAttrs.java index 39e69a3066..8489a2c222 100644 --- a/test/031-class-attributes/src/ClassAttrs.java +++ b/test/031-class-attributes/src/ClassAttrs.java @@ -133,12 +133,12 @@ public class ClassAttrs { System.out.println("field signature: " + getSignatureAttribute(field)); } catch (NoSuchMethodException nsme) { - System.err.println("FAILED: " + nsme); + System.out.println("FAILED: " + nsme); } catch (NoSuchFieldException nsfe) { - System.err.println("FAILED: " + nsfe); + System.out.println("FAILED: " + nsfe); } catch (RuntimeException re) { - System.err.println("FAILED: " + re); - re.printStackTrace(); + System.out.println("FAILED: " + re); + re.printStackTrace(System.out); } test_isAssignableFrom(); @@ -228,7 +228,7 @@ public class ClassAttrs { method = c.getDeclaredMethod("getSignatureAttribute"); method.setAccessible(true); } catch (Exception ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); return "<unknown>"; } diff --git a/test/032-concrete-sub/src/ConcreteSub.java b/test/032-concrete-sub/src/ConcreteSub.java index 95adf63c37..61d1602492 100644 --- a/test/032-concrete-sub/src/ConcreteSub.java +++ b/test/032-concrete-sub/src/ConcreteSub.java @@ -45,7 +45,7 @@ public class ConcreteSub extends AbstractBase { try { meth = absClass.getMethod("redefineMe"); } catch (NoSuchMethodException nsme) { - nsme.printStackTrace(); + nsme.printStackTrace(System.out); return; } System.out.println("meth modifiers=" + meth.getModifiers()); diff --git a/test/032-concrete-sub/src/Main.java b/test/032-concrete-sub/src/Main.java index 4a5193d635..7d3be1525d 100644 --- a/test/032-concrete-sub/src/Main.java +++ b/test/032-concrete-sub/src/Main.java @@ -26,7 +26,7 @@ public class Main { ConcreteSub2 blah = new ConcreteSub2(); // other VMs fail here (AbstractMethodError) blah.doStuff(); - System.err.println("Succeeded unexpectedly"); + System.out.println("Succeeded unexpectedly"); } catch (VerifyError ve) { System.out.println("Got expected failure"); } catch (AbstractMethodError ame) { diff --git a/test/036-finalizer/src/Main.java b/test/036-finalizer/src/Main.java index 0de56f9a7c..734830f7de 100644 --- a/test/036-finalizer/src/Main.java +++ b/test/036-finalizer/src/Main.java @@ -120,7 +120,7 @@ public class Main { static void printNonFinalized() { for (int i = 0; i < maxCount; ++i) { if (!FinalizeCounter.finalized[i]) { - System.err.println("Element " + i + " was not finalized"); + System.out.println("Element " + i + " was not finalized"); } } } diff --git a/test/042-new-instance/src/Main.java b/test/042-new-instance/src/Main.java index 755d62ebb5..34d1f5a68d 100644 --- a/test/042-new-instance/src/Main.java +++ b/test/042-new-instance/src/Main.java @@ -37,31 +37,31 @@ public class Main { Object obj = c.newInstance(); System.out.println("LocalClass succeeded"); } catch (Exception ex) { - System.err.println("LocalClass failed"); - ex.printStackTrace(); + System.out.println("LocalClass failed"); + ex.printStackTrace(System.out); } // should fail try { Class<?> c = Class.forName("otherpackage.PackageAccess"); Object obj = c.newInstance(); - System.err.println("ERROR: PackageAccess succeeded unexpectedly"); + System.out.println("ERROR: PackageAccess succeeded unexpectedly"); } catch (IllegalAccessException iae) { System.out.println("Got expected PackageAccess complaint"); } catch (Exception ex) { - System.err.println("Got unexpected PackageAccess failure"); - ex.printStackTrace(); + System.out.println("Got unexpected PackageAccess failure"); + ex.printStackTrace(System.out); } LocalClass3.main(); try { MaybeAbstract ma = new MaybeAbstract(); - System.err.println("ERROR: MaybeAbstract succeeded unexpectedly"); + System.out.println("ERROR: MaybeAbstract succeeded unexpectedly"); } catch (InstantiationError ie) { System.out.println("Got expected InstantationError"); } catch (Exception ex) { - System.err.println("Got unexpected MaybeAbstract failure"); + System.out.println("Got unexpected MaybeAbstract failure"); } } @@ -73,12 +73,12 @@ public class Main { try { Class<?> c = Class.forName("LocalClass"); Constructor<?> cons = c.getConstructor(); - System.err.println("Cons LocalClass succeeded unexpectedly"); + System.out.println("Cons LocalClass succeeded unexpectedly"); } catch (NoSuchMethodException nsme) { System.out.println("Cons LocalClass failed as expected"); } catch (Exception ex) { - System.err.println("Cons LocalClass failed strangely"); - ex.printStackTrace(); + System.out.println("Cons LocalClass failed strangely"); + ex.printStackTrace(System.out); } // should succeed @@ -88,8 +88,8 @@ public class Main { Object obj = cons.newInstance(); System.out.println("Cons LocalClass2 succeeded"); } catch (Exception ex) { - System.err.println("Cons LocalClass2 failed"); - ex.printStackTrace(); + System.out.println("Cons LocalClass2 failed"); + ex.printStackTrace(System.out); } // should succeed @@ -99,8 +99,8 @@ public class Main { Object obj = cons.newInstance(new Main()); System.out.println("Cons InnerClass succeeded"); } catch (Exception ex) { - System.err.println("Cons InnerClass failed"); - ex.printStackTrace(); + System.out.println("Cons InnerClass failed"); + ex.printStackTrace(System.out); } // should succeed @@ -110,21 +110,21 @@ public class Main { Object obj = cons.newInstance(); System.out.println("Cons StaticInnerClass succeeded"); } catch (Exception ex) { - System.err.println("Cons StaticInnerClass failed"); - ex.printStackTrace(); + System.out.println("Cons StaticInnerClass failed"); + ex.printStackTrace(System.out); } // should fail try { Class<?> c = Class.forName("otherpackage.PackageAccess"); Constructor<?> cons = c.getConstructor(); - System.err.println("ERROR: Cons PackageAccess succeeded unexpectedly"); + System.out.println("ERROR: Cons PackageAccess succeeded unexpectedly"); } catch (NoSuchMethodException nsme) { // constructor isn't public System.out.println("Cons got expected PackageAccess complaint"); } catch (Exception ex) { - System.err.println("Cons got unexpected PackageAccess failure"); - ex.printStackTrace(); + System.out.println("Cons got unexpected PackageAccess failure"); + ex.printStackTrace(System.out); } // should fail @@ -132,13 +132,13 @@ public class Main { Class<?> c = Class.forName("MaybeAbstract"); Constructor<?> cons = c.getConstructor(); Object obj = cons.newInstance(); - System.err.println("ERROR: Cons MaybeAbstract succeeded unexpectedly"); + System.out.println("ERROR: Cons MaybeAbstract succeeded unexpectedly"); } catch (InstantiationException ie) { // note InstantiationException vs. InstantiationError System.out.println("Cons got expected InstantationException"); } catch (Exception ex) { - System.err.println("Cons got unexpected MaybeAbstract failure"); - ex.printStackTrace(); + System.out.println("Cons got unexpected MaybeAbstract failure"); + ex.printStackTrace(System.out); } // should fail @@ -147,13 +147,13 @@ public class Main { Constructor<?> cons = c.getConstructor(); if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); } Object obj = cons.newInstance(); - System.err.println("ERROR: Cons PackageAccess2 succeeded unexpectedly"); + System.out.println("ERROR: Cons PackageAccess2 succeeded unexpectedly"); } catch (IllegalAccessException iae) { // constructor is public, but class has package scope System.out.println("Cons got expected PackageAccess2 complaint"); } catch (Exception ex) { - System.err.println("Cons got unexpected PackageAccess2 failure"); - ex.printStackTrace(); + System.out.println("Cons got unexpected PackageAccess2 failure"); + ex.printStackTrace(System.out); } // should succeed @@ -161,8 +161,8 @@ public class Main { otherpackage.ConstructorAccess.newConstructorInstance(); System.out.println("Cons ConstructorAccess succeeded"); } catch (Exception ex) { - System.err.println("Cons ConstructorAccess failed"); - ex.printStackTrace(); + System.out.println("Cons ConstructorAccess failed"); + ex.printStackTrace(System.out); } } @@ -187,8 +187,8 @@ class LocalClass3 { CC.newInstance(); System.out.println("LocalClass3 succeeded"); } catch (Exception ex) { - System.err.println("Got unexpected LocalClass3 failure"); - ex.printStackTrace(); + System.out.println("Got unexpected LocalClass3 failure"); + ex.printStackTrace(System.out); } } @@ -200,7 +200,7 @@ class LocalClass3 { Class<?> c = CC.class; return c.newInstance(); } catch (Exception ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); return null; } } diff --git a/test/044-proxy/src/BasicTest.java b/test/044-proxy/src/BasicTest.java index 5f04b9344c..7f301f667b 100644 --- a/test/044-proxy/src/BasicTest.java +++ b/test/044-proxy/src/BasicTest.java @@ -34,9 +34,9 @@ public class BasicTest { Object proxy = createProxy(proxyMe); if (!Proxy.isProxyClass(proxy.getClass())) - System.err.println("not a proxy class?"); + System.out.println("not a proxy class?"); if (Proxy.getInvocationHandler(proxy) == null) - System.err.println("ERROR: Proxy.getInvocationHandler is null"); + System.out.println("ERROR: Proxy.getInvocationHandler is null"); /* take it for a spin; verifies instanceof constraint */ Shapes shapes = (Shapes) proxy; @@ -110,13 +110,13 @@ public class BasicTest { //System.out.println("Constructor is " + cons); proxy = cons.newInstance(handler); } catch (NoSuchMethodException nsme) { - System.err.println("failed: " + nsme); + System.out.println("failed: " + nsme); } catch (InstantiationException ie) { - System.err.println("failed: " + ie); + System.out.println("failed: " + ie); } catch (IllegalAccessException ie) { - System.err.println("failed: " + ie); + System.out.println("failed: " + ie); } catch (InvocationTargetException ite) { - System.err.println("failed: " + ite); + System.out.println("failed: " + ite); } return proxy; diff --git a/test/044-proxy/src/Clash.java b/test/044-proxy/src/Clash.java index d000112fb6..7dabe927b0 100644 --- a/test/044-proxy/src/Clash.java +++ b/test/044-proxy/src/Clash.java @@ -32,7 +32,7 @@ public class Clash { Proxy.newProxyInstance(Clash.class.getClassLoader(), new Class<?>[] { Interface1A.class, Interface1A.class }, handler); - System.err.println("Dupe did not throw expected exception"); + System.out.println("Dupe did not throw expected exception"); } catch (IllegalArgumentException iae) { System.out.println("Dupe threw expected exception"); } @@ -41,7 +41,7 @@ public class Clash { Proxy.newProxyInstance(Clash.class.getClassLoader(), new Class<?>[] { Interface1A.class, Interface1B.class }, handler); - System.err.println("Clash did not throw expected exception"); + System.out.println("Clash did not throw expected exception"); } catch (IllegalArgumentException iae) { System.out.println("Clash threw expected exception"); } diff --git a/test/044-proxy/src/Clash2.java b/test/044-proxy/src/Clash2.java index e405cfea03..51221f2656 100644 --- a/test/044-proxy/src/Clash2.java +++ b/test/044-proxy/src/Clash2.java @@ -31,7 +31,7 @@ public class Clash2 { Proxy.newProxyInstance(Clash.class.getClassLoader(), new Class<?>[] { Interface2A.class, Interface2B.class }, handler); - System.err.println("Clash2 did not throw expected exception"); + System.out.println("Clash2 did not throw expected exception"); } catch (IllegalArgumentException iae) { System.out.println("Clash2 threw expected exception"); } diff --git a/test/044-proxy/src/Clash3.java b/test/044-proxy/src/Clash3.java index 44806cee7d..9d23059b9c 100644 --- a/test/044-proxy/src/Clash3.java +++ b/test/044-proxy/src/Clash3.java @@ -35,7 +35,7 @@ public class Clash3 { Interface3aa.class, Interface3b.class }, handler); - System.err.println("Clash3 did not throw expected exception"); + System.out.println("Clash3 did not throw expected exception"); } catch (IllegalArgumentException iae) { System.out.println("Clash3 threw expected exception"); } diff --git a/test/044-proxy/src/Clash4.java b/test/044-proxy/src/Clash4.java index ca5c3ab6e6..45d48208e1 100644 --- a/test/044-proxy/src/Clash4.java +++ b/test/044-proxy/src/Clash4.java @@ -36,7 +36,7 @@ public class Clash4 { Interface4b.class, Interface4bb.class }, handler); - System.err.println("Clash4 did not throw expected exception"); + System.out.println("Clash4 did not throw expected exception"); } catch (IllegalArgumentException iae) { System.out.println("Clash4 threw expected exception"); //System.out.println(iae); diff --git a/test/044-proxy/src/ConstructorProxy.java b/test/044-proxy/src/ConstructorProxy.java index 95d150cbbd..dfafbd804a 100644 --- a/test/044-proxy/src/ConstructorProxy.java +++ b/test/044-proxy/src/ConstructorProxy.java @@ -28,7 +28,7 @@ class ConstructorProxy implements InvocationHandler { new ConstructorProxy().runTest(); } catch (Exception e) { System.out.println("Unexpected failure occured"); - e.printStackTrace(); + e.printStackTrace(System.out); } } diff --git a/test/044-proxy/src/WrappedThrow.java b/test/044-proxy/src/WrappedThrow.java index 643ba053b9..afea26d5d5 100644 --- a/test/044-proxy/src/WrappedThrow.java +++ b/test/044-proxy/src/WrappedThrow.java @@ -43,29 +43,29 @@ public class WrappedThrow { InterfaceW2 if2 = (InterfaceW2) proxy; try { if1.throwFunky(); - System.err.println("No exception thrown"); + System.out.println("No exception thrown"); } catch (UndeclaredThrowableException ute) { System.out.println("Got expected UTE"); } catch (Throwable t) { - System.err.println("Got unexpected exception: " + t); + System.out.println("Got unexpected exception: " + t); } try { if1.throwFunky2(); - System.err.println("No exception thrown"); + System.out.println("No exception thrown"); } catch (IOException ioe) { System.out.println("Got expected IOE"); } catch (Throwable t) { - System.err.println("Got unexpected exception: " + t); + System.out.println("Got unexpected exception: " + t); } try { if2.throwFunky2(); - System.err.println("No exception thrown"); + System.out.println("No exception thrown"); } catch (IOException ioe) { System.out.println("Got expected IOE"); } catch (Throwable t) { - System.err.println("Got unexpected exception: " + t); + System.out.println("Got unexpected exception: " + t); } /* @@ -73,38 +73,38 @@ public class WrappedThrow { */ try { if1.throwException(); - System.err.println("No exception thrown"); + System.out.println("No exception thrown"); } catch (UndeclaredThrowableException ute) { System.out.println("Got expected UTE"); } catch (Throwable t) { - System.err.println("Got unexpected exception: " + t); + System.out.println("Got unexpected exception: " + t); } try { if1.throwBase(); - System.err.println("No exception thrown"); + System.out.println("No exception thrown"); } catch (UndeclaredThrowableException ute) { System.out.println("Got expected UTE"); } catch (Throwable t) { - System.err.println("Got unexpected exception: " + t); + System.out.println("Got unexpected exception: " + t); } try { if2.throwSub(); - System.err.println("No exception thrown"); + System.out.println("No exception thrown"); } catch (SubException se) { System.out.println("Got expected exception"); } catch (Throwable t) { - System.err.println("Got unexpected exception: " + t); + System.out.println("Got unexpected exception: " + t); } try { if2.throwSubSub(); - System.err.println("No exception thrown"); + System.out.println("No exception thrown"); } catch (SubException se) { System.out.println("Got expected exception"); } catch (Throwable t) { - System.err.println("Got unexpected exception: " + t); + System.out.println("Got unexpected exception: " + t); } /* @@ -113,11 +113,11 @@ public class WrappedThrow { */ try { if1.bothThrowBase(); - System.err.println("No exception thrown"); + System.out.println("No exception thrown"); } catch (BaseException se) { System.out.println("Got expected exception"); } catch (Throwable t) { - System.err.println("Got unexpected exception: " + t); + System.out.println("Got unexpected exception: " + t); } } } diff --git a/test/045-reflect-array/src/Main.java b/test/045-reflect-array/src/Main.java index 7418eed824..4c321b3303 100644 --- a/test/045-reflect-array/src/Main.java +++ b/test/045-reflect-array/src/Main.java @@ -102,7 +102,7 @@ public class Main { throw new RuntimeException("load should have worked"); } } catch (IllegalArgumentException iae) { - iae.printStackTrace(); + iae.printStackTrace(System.out); } try { Array.getByte(charArray, 2); @@ -116,7 +116,7 @@ public class Main { + Array.getInt(charArray, 3)); } } catch (IllegalArgumentException iae) { - iae.printStackTrace(); + iae.printStackTrace(System.out); } System.out.println("ReflectArrayTest.testSingleChar passed"); diff --git a/test/046-reflect/src/Main.java b/test/046-reflect/src/Main.java index 10dad8ddac..b8a48ea247 100644 --- a/test/046-reflect/src/Main.java +++ b/test/046-reflect/src/Main.java @@ -89,7 +89,7 @@ public class Main { try { meth = target.getMethod("packageMethod"); - System.err.println("succeeded on package-scope method"); + System.out.println("succeeded on package-scope method"); } catch (NoSuchMethodException nsme) { // good } @@ -101,7 +101,7 @@ public class Main { try { if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); } meth.invoke(instance); - System.err.println("inner-method invoke unexpectedly worked"); + System.out.println("inner-method invoke unexpectedly worked"); } catch (IllegalAccessException iae) { // good } @@ -110,13 +110,13 @@ public class Main { try { int x = field.getInt(instance); if (!FULL_ACCESS_CHECKS) { throw new IllegalAccessException(); } - System.err.println("field get unexpectedly worked: " + x); + System.out.println("field get unexpectedly worked: " + x); } catch (IllegalAccessException iae) { // good } } catch (Exception ex) { System.out.println("----- unexpected exception -----"); - ex.printStackTrace(); + ex.printStackTrace(System.out); } } @@ -171,7 +171,7 @@ public class Main { } catch (Exception ex) { System.out.println("GLITCH: invoke got wrong exception:"); - ex.printStackTrace(); + ex.printStackTrace(System.out); } System.out.println(""); @@ -400,7 +400,7 @@ public class Main { } catch (Exception ex) { System.out.println("----- unexpected exception -----"); - ex.printStackTrace(); + ex.printStackTrace(System.out); } System.out.println("ReflectTest done!"); @@ -414,7 +414,7 @@ public class Main { m = Collections.class.getDeclaredMethod("swap", Object[].class, int.class, int.class); } catch (NoSuchMethodException nsme) { - nsme.printStackTrace(); + nsme.printStackTrace(System.out); return; } System.out.println(m + " accessible=" + m.isAccessible()); @@ -423,10 +423,10 @@ public class Main { try { m.invoke(null, objects, 0, 1); } catch (IllegalAccessException iae) { - iae.printStackTrace(); + iae.printStackTrace(System.out); return; } catch (InvocationTargetException ite) { - ite.printStackTrace(); + ite.printStackTrace(System.out); return; } @@ -434,10 +434,10 @@ public class Main { String s = "Should be ignored"; m.invoke(s, objects, 0, 1); } catch (IllegalAccessException iae) { - iae.printStackTrace(); + iae.printStackTrace(System.out); return; } catch (InvocationTargetException ite) { - ite.printStackTrace(); + ite.printStackTrace(System.out); return; } @@ -449,7 +449,7 @@ public class Main { } catch (InvocationTargetException ite) { System.out.println("checkType got expected exception"); } catch (IllegalAccessException iae) { - iae.printStackTrace(); + iae.printStackTrace(System.out); return; } } @@ -826,7 +826,7 @@ class FieldNoisyInit { static { System.out.println("FieldNoisyInit is initializing"); //Throwable th = new Throwable(); - //th.printStackTrace(); + //th.printStackTrace(System.out); } } @@ -842,7 +842,7 @@ class MethodNoisyInit { static { System.out.println("MethodNoisyInit is initializing"); //Throwable th = new Throwable(); - //th.printStackTrace(); + //th.printStackTrace(System.out); } } diff --git a/test/048-reflect-v8/src/DefaultDeclared.java b/test/048-reflect-v8/src/DefaultDeclared.java index 16e8a24c00..d49bdc91a5 100644 --- a/test/048-reflect-v8/src/DefaultDeclared.java +++ b/test/048-reflect-v8/src/DefaultDeclared.java @@ -52,7 +52,7 @@ public class DefaultDeclared { System.out.println("NoSuchMethodException thrown for class " + klass.toString()); } catch (Throwable t) { System.out.println("Unknown error thrown for class " + klass.toString()); - t.printStackTrace(); + t.printStackTrace(System.out); } } diff --git a/test/050-sync-test/src/Main.java b/test/050-sync-test/src/Main.java index 5364e2aaaa..734b51e811 100644 --- a/test/050-sync-test/src/Main.java +++ b/test/050-sync-test/src/Main.java @@ -39,7 +39,7 @@ public class Main { Thread.sleep(1000); } catch (InterruptedException ie) { System.out.println("INTERRUPT!"); - ie.printStackTrace(); + ie.printStackTrace(System.out); } System.out.println("GONE"); } @@ -56,7 +56,7 @@ public class Main { one.wait(); } catch (InterruptedException ie) { System.out.println("INTERRUPT!"); - ie.printStackTrace(); + ie.printStackTrace(System.out); } } @@ -69,7 +69,7 @@ public class Main { two.join(); } catch (InterruptedException ie) { System.out.println("INTERRUPT!"); - ie.printStackTrace(); + ie.printStackTrace(System.out); } System.out.println("main: all done"); } @@ -167,7 +167,7 @@ class SleepyThread extends Thread { " interrupted, flag=" + Thread.interrupted()); intr = true; } catch (Exception ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); } if (!intr) diff --git a/test/050-sync-test/src/ThreadDeathHandler.java b/test/050-sync-test/src/ThreadDeathHandler.java index 0a7437d307..58061f8d00 100644 --- a/test/050-sync-test/src/ThreadDeathHandler.java +++ b/test/050-sync-test/src/ThreadDeathHandler.java @@ -27,7 +27,7 @@ public class ThreadDeathHandler implements Thread.UncaughtExceptionHandler { } public void uncaughtException(Thread t, Throwable e) { - System.err.println("Uncaught exception " + mMyMessage + "!"); - e.printStackTrace(); + System.out.println("Uncaught exception " + mMyMessage + "!"); + e.printStackTrace(System.out); } } diff --git a/test/051-thread/src/Main.java b/test/051-thread/src/Main.java index 08cb5deeac..fe1cafef56 100644 --- a/test/051-thread/src/Main.java +++ b/test/051-thread/src/Main.java @@ -79,7 +79,7 @@ public class Main { try { t.join(); } catch (InterruptedException ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); } System.out.print("testThreadDaemons finished\n"); diff --git a/test/053-wait-some/src/Main.java b/test/053-wait-some/src/Main.java index 377a5781ea..b8e6dfeeae 100644 --- a/test/053-wait-some/src/Main.java +++ b/test/053-wait-some/src/Main.java @@ -39,7 +39,7 @@ public class Main { } catch (IllegalArgumentException iae) { System.out.println("Caught expected exception on neg arg"); } catch (InterruptedException ie) { - ie.printStackTrace(); + ie.printStackTrace(System.out); } for (long delay : DELAYS) { @@ -49,7 +49,7 @@ public class Main { try { sleepy.wait(delay); } catch (InterruptedException ie) { - ie.printStackTrace(); + ie.printStackTrace(System.out); } end = System.currentTimeMillis(); diff --git a/test/054-uncaught/src/Main.java b/test/054-uncaught/src/Main.java index 688a2a4d79..43de7ae258 100644 --- a/test/054-uncaught/src/Main.java +++ b/test/054-uncaught/src/Main.java @@ -33,7 +33,7 @@ public class Main { try { t.join(); } catch (InterruptedException ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); } } @@ -41,7 +41,7 @@ public class Main { ThreadDeathHandler defHandler = new ThreadDeathHandler("DEFAULT"); ThreadDeathHandler threadHandler = new ThreadDeathHandler("THREAD"); - System.err.println("Test " + which); + System.out.println("Test " + which); switch (which) { case 1: { Thread.setDefaultUncaughtExceptionHandler(defHandler); diff --git a/test/054-uncaught/src/ThreadDeathHandler.java b/test/054-uncaught/src/ThreadDeathHandler.java index 0a7437d307..58061f8d00 100644 --- a/test/054-uncaught/src/ThreadDeathHandler.java +++ b/test/054-uncaught/src/ThreadDeathHandler.java @@ -27,7 +27,7 @@ public class ThreadDeathHandler implements Thread.UncaughtExceptionHandler { } public void uncaughtException(Thread t, Throwable e) { - System.err.println("Uncaught exception " + mMyMessage + "!"); - e.printStackTrace(); + System.out.println("Uncaught exception " + mMyMessage + "!"); + e.printStackTrace(System.out); } } diff --git a/test/059-finalizer-throw/src/Main.java b/test/059-finalizer-throw/src/Main.java index fa80fe3f7a..3bfbc2d5b6 100644 --- a/test/059-finalizer-throw/src/Main.java +++ b/test/059-finalizer-throw/src/Main.java @@ -46,7 +46,7 @@ public class Main { try { Thread.sleep(500); } catch (InterruptedException ie) { - System.err.println(ie); + System.out.println(ie); } } @@ -54,7 +54,7 @@ public class Main { try { Thread.sleep(750); } catch (InterruptedException ie) { - System.err.println(ie); + System.out.println(ie); } System.out.println("done"); diff --git a/test/064-field-access/src/Main.java b/test/064-field-access/src/Main.java index 50ad5b9a20..b08f3ae305 100644 --- a/test/064-field-access/src/Main.java +++ b/test/064-field-access/src/Main.java @@ -28,7 +28,7 @@ public class Main { try { GetNonexistent.main(null); - System.err.println("Not expected to succeed"); + System.out.println("Not expected to succeed"); } catch (VerifyError fe) { // dalvik System.out.println("Got expected failure"); @@ -101,22 +101,22 @@ public class Main { /* success; expected? */ if (expectedException != null) { - System.err.println("ERROR: call succeeded for field " + field + + System.out.println("ERROR: call succeeded for field " + field + " with a read of type '" + type + "', was expecting " + expectedException); Thread.dumpStack(); } } catch (Exception ex) { if (expectedException == null) { - System.err.println("ERROR: call failed unexpectedly: " + System.out.println("ERROR: call failed unexpectedly: " + ex.getClass()); - ex.printStackTrace(); + ex.printStackTrace(System.out); } else { if (!expectedException.equals(ex.getClass())) { - System.err.println("ERROR: incorrect exception: wanted " + System.out.println("ERROR: incorrect exception: wanted " + expectedException.getName() + ", got " + ex.getClass()); - ex.printStackTrace(); + ex.printStackTrace(System.out); } } } @@ -675,22 +675,22 @@ class SubClass extends PublicClass { /* success; expected? */ if (expectedException != null) { - System.err.println("ERROR: call succeeded for field " + field + + System.out.println("ERROR: call succeeded for field " + field + " with a read of type '" + type + "', was expecting " + expectedException); Thread.dumpStack(); } } catch (Exception ex) { if (expectedException == null) { - System.err.println("ERROR: call failed unexpectedly: " + System.out.println("ERROR: call failed unexpectedly: " + ex.getClass()); - ex.printStackTrace(); + ex.printStackTrace(System.out); } else { if (!expectedException.equals(ex.getClass())) { - System.err.println("ERROR: incorrect exception: wanted " + System.out.println("ERROR: incorrect exception: wanted " + expectedException.getName() + ", got " + ex.getClass()); - ex.printStackTrace(); + ex.printStackTrace(System.out); } } } @@ -704,19 +704,19 @@ class SubClass extends PublicClass { result = method.invoke(obj); /* success; expected? */ if (expectedException != null) { - System.err.println("ERROR: call succeeded for method " + method + "', was expecting " + + System.out.println("ERROR: call succeeded for method " + method + "', was expecting " + expectedException); Thread.dumpStack(); } } catch (Exception ex) { if (expectedException == null) { - System.err.println("ERROR: call failed unexpectedly: " + ex.getClass()); - ex.printStackTrace(); + System.out.println("ERROR: call failed unexpectedly: " + ex.getClass()); + ex.printStackTrace(System.out); } else { if (!expectedException.equals(ex.getClass())) { - System.err.println("ERROR: incorrect exception: wanted " + expectedException.getName() + + System.out.println("ERROR: incorrect exception: wanted " + expectedException.getName() + ", got " + ex.getClass()); - ex.printStackTrace(); + ex.printStackTrace(System.out); } } } diff --git a/test/065-mismatched-implements/src/Main.java b/test/065-mismatched-implements/src/Main.java index 5975b99e92..55d0babbef 100644 --- a/test/065-mismatched-implements/src/Main.java +++ b/test/065-mismatched-implements/src/Main.java @@ -21,7 +21,7 @@ public class Main { public static void main(String[] args) { try { Indirect.main(); - System.err.println("Succeeded unexpectedly"); + System.out.println("Succeeded unexpectedly"); } catch (IncompatibleClassChangeError icce) { System.out.println("Got expected ICCE"); } diff --git a/test/066-mismatched-super/src/Main.java b/test/066-mismatched-super/src/Main.java index 5975b99e92..55d0babbef 100644 --- a/test/066-mismatched-super/src/Main.java +++ b/test/066-mismatched-super/src/Main.java @@ -21,7 +21,7 @@ public class Main { public static void main(String[] args) { try { Indirect.main(); - System.err.println("Succeeded unexpectedly"); + System.out.println("Succeeded unexpectedly"); } catch (IncompatibleClassChangeError icce) { System.out.println("Got expected ICCE"); } diff --git a/test/068-classloader/src/Main.java b/test/068-classloader/src/Main.java index 01539b7172..0aaa1528c0 100644 --- a/test/068-classloader/src/Main.java +++ b/test/068-classloader/src/Main.java @@ -129,7 +129,7 @@ public class Main { throw new RuntimeException("target 2 has unexpected value " + value); } } catch (Exception ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); } } @@ -153,8 +153,8 @@ public class Main { try { altClass = loader.loadClass("Inaccessible1"); } catch (ClassNotFoundException cnfe) { - System.err.println("loadClass failed"); - cnfe.printStackTrace(); + System.out.println("loadClass failed"); + cnfe.printStackTrace(System.out); return; } @@ -162,9 +162,9 @@ public class Main { Object obj; try { obj = altClass.newInstance(); - System.err.println("ERROR: Inaccessible1 was accessible"); + System.out.println("ERROR: Inaccessible1 was accessible"); } catch (InstantiationException ie) { - System.err.println("newInstance failed: " + ie); + System.out.println("newInstance failed: " + ie); return; } catch (IllegalAccessException iae) { System.out.println("Got expected access exception #1"); @@ -182,14 +182,14 @@ public class Main { try { altClass = loader.loadClass("Inaccessible2"); - System.err.println("ERROR: Inaccessible2 was accessible: " + altClass); + System.out.println("ERROR: Inaccessible2 was accessible: " + altClass); } catch (ClassNotFoundException cnfe) { Throwable cause = cnfe.getCause(); if (cause instanceof IllegalAccessError) { System.out.println("Got expected CNFE/IAE #2"); } else { - System.err.println("Got unexpected CNFE/IAE #2"); - cnfe.printStackTrace(); + System.out.println("Got unexpected CNFE/IAE #2"); + cnfe.printStackTrace(System.out); } } } @@ -202,14 +202,14 @@ public class Main { try { altClass = loader.loadClass("Inaccessible3"); - System.err.println("ERROR: Inaccessible3 was accessible: " + altClass); + System.out.println("ERROR: Inaccessible3 was accessible: " + altClass); } catch (ClassNotFoundException cnfe) { Throwable cause = cnfe.getCause(); if (cause instanceof IllegalAccessError) { System.out.println("Got expected CNFE/IAE #3"); } else { - System.err.println("Got unexpected CNFE/IAE #3"); - cnfe.printStackTrace(); + System.out.println("Got unexpected CNFE/IAE #3"); + cnfe.printStackTrace(System.out); } } } @@ -227,7 +227,7 @@ public class Main { //System.out.println("+++ DoubledExtend is " + doubledExtendClass // + " in " + doubledExtendClass.getClassLoader()); } catch (ClassNotFoundException cnfe) { - System.err.println("loadClass failed: " + cnfe); + System.out.println("loadClass failed: " + cnfe); return; } @@ -235,10 +235,10 @@ public class Main { try { obj = doubledExtendClass.newInstance(); } catch (InstantiationException ie) { - System.err.println("newInstance failed: " + ie); + System.out.println("newInstance failed: " + ie); return; } catch (IllegalAccessException iae) { - System.err.println("newInstance failed: " + iae); + System.out.println("newInstance failed: " + iae); return; } catch (LinkageError le) { System.out.println("Got expected LinkageError on DE"); @@ -254,8 +254,8 @@ public class Main { String result; result = Base.doStuff(de); - System.err.println("ERROR: did not get LinkageError on DE"); - System.err.println("(result=" + result + ")"); + System.out.println("ERROR: did not get LinkageError on DE"); + System.out.println("(result=" + result + ")"); } catch (LinkageError le) { System.out.println("Got expected LinkageError on DE"); return; @@ -274,7 +274,7 @@ public class Main { try { doubledExtendOkayClass = loader.loadClass("DoubledExtendOkay"); } catch (ClassNotFoundException cnfe) { - System.err.println("loadClass failed: " + cnfe); + System.out.println("loadClass failed: " + cnfe); return; } @@ -282,14 +282,14 @@ public class Main { try { obj = doubledExtendOkayClass.newInstance(); } catch (InstantiationException ie) { - System.err.println("newInstance failed: " + ie); + System.out.println("newInstance failed: " + ie); return; } catch (IllegalAccessException iae) { - System.err.println("newInstance failed: " + iae); + System.out.println("newInstance failed: " + iae); return; } catch (LinkageError le) { - System.err.println("Got unexpected LinkageError on DEO"); - le.printStackTrace(); + System.out.println("Got unexpected LinkageError on DEO"); + le.printStackTrace(System.out); return; } @@ -304,8 +304,8 @@ public class Main { result = BaseOkay.doStuff(de); System.out.println("Got DEO result " + result); } catch (LinkageError le) { - System.err.println("Got unexpected LinkageError on DEO"); - le.printStackTrace(); + System.out.println("Got unexpected LinkageError on DEO"); + le.printStackTrace(System.out); return; } } @@ -322,7 +322,7 @@ public class Main { try { getDoubledClass = loader.loadClass("GetDoubled"); } catch (ClassNotFoundException cnfe) { - System.err.println("loadClass failed: " + cnfe); + System.out.println("loadClass failed: " + cnfe); return; } @@ -330,10 +330,10 @@ public class Main { try { obj = getDoubledClass.newInstance(); } catch (InstantiationException ie) { - System.err.println("newInstance failed: " + ie); + System.out.println("newInstance failed: " + ie); return; } catch (IllegalAccessException iae) { - System.err.println("newInstance failed: " + iae); + System.out.println("newInstance failed: " + iae); return; } catch (LinkageError le) { // Dalvik bails here @@ -354,7 +354,7 @@ public class Main { System.out.println("Got LinkageError on GD"); return; } - System.err.println("Should have failed by now on GetDoubled"); + System.out.println("Should have failed by now on GetDoubled"); } /** @@ -368,7 +368,7 @@ public class Main { try { abstractGetClass = loader.loadClass("AbstractGet"); } catch (ClassNotFoundException cnfe) { - System.err.println("loadClass ta failed: " + cnfe); + System.out.println("loadClass ta failed: " + cnfe); return; } @@ -376,10 +376,10 @@ public class Main { try { obj = abstractGetClass.newInstance(); } catch (InstantiationException ie) { - System.err.println("newInstance failed: " + ie); + System.out.println("newInstance failed: " + ie); return; } catch (IllegalAccessException iae) { - System.err.println("newInstance failed: " + iae); + System.out.println("newInstance failed: " + iae); return; } catch (LinkageError le) { System.out.println("Got LinkageError on TA"); @@ -399,7 +399,7 @@ public class Main { System.out.println("Got LinkageError on TA"); return; } - System.err.println("Should have failed by now in testAbstract"); + System.out.println("Should have failed by now in testAbstract"); } /** @@ -415,7 +415,7 @@ public class Main { try { doubledImplementClass = loader.loadClass("DoubledImplement"); } catch (ClassNotFoundException cnfe) { - System.err.println("loadClass failed: " + cnfe); + System.out.println("loadClass failed: " + cnfe); return; } @@ -423,10 +423,10 @@ public class Main { try { obj = doubledImplementClass.newInstance(); } catch (InstantiationException ie) { - System.err.println("newInstance failed: " + ie); + System.out.println("newInstance failed: " + ie); return; } catch (IllegalAccessException iae) { - System.err.println("newInstance failed: " + iae); + System.out.println("newInstance failed: " + iae); return; } catch (LinkageError le) { System.out.println("Got LinkageError on DI (early)"); @@ -447,7 +447,7 @@ public class Main { try { di.one(); if (!isOne) { - System.err.println("ERROR: did not get LinkageError on DI"); + System.out.println("ERROR: did not get LinkageError on DI"); } } catch (LinkageError le) { if (!isOne) { @@ -476,7 +476,7 @@ public class Main { ifaceImplClass = loader.loadClass("IfaceImpl"); ifaceImplClass = loader.loadClass("DoubledImplement2"); } catch (ClassNotFoundException cnfe) { - System.err.println("loadClass failed: " + cnfe); + System.out.println("loadClass failed: " + cnfe); return; } @@ -484,10 +484,10 @@ public class Main { try { obj = ifaceImplClass.newInstance(); } catch (InstantiationException ie) { - System.err.println("newInstance failed: " + ie); + System.out.println("newInstance failed: " + ie); return; } catch (IllegalAccessException iae) { - System.err.println("newInstance failed: " + iae); + System.out.println("newInstance failed: " + iae); return; } catch (LinkageError le) { System.out.println("Got LinkageError on IDI (early)"); diff --git a/test/069-field-type/src/Main.java b/test/069-field-type/src/Main.java index f9885e64b2..d9aa9e11bf 100644 --- a/test/069-field-type/src/Main.java +++ b/test/069-field-type/src/Main.java @@ -19,7 +19,7 @@ public class Main { /* try to use the reference; should fail */ try { holder.mValue.run(); - System.err.println("ERROR: did not get expected ICCE"); + System.out.println("ERROR: did not get expected ICCE"); } catch (IncompatibleClassChangeError icce) { System.out.println("Got expected IncompatibleClassChangeError"); } diff --git a/test/070-nio-buffer/src/Main.java b/test/070-nio-buffer/src/Main.java index a7433b8516..a3eeb3fda6 100644 --- a/test/070-nio-buffer/src/Main.java +++ b/test/070-nio-buffer/src/Main.java @@ -58,7 +58,7 @@ public class Main { try { shortBuf.put(myShorts, 0, 1); // should fail - System.err.println("ERROR: out-of-bounds put succeeded\n"); + System.out.println("ERROR: out-of-bounds put succeeded\n"); } catch (BufferOverflowException boe) { System.out.println("Got expected buffer overflow exception"); } @@ -66,7 +66,7 @@ public class Main { try { shortBuf.position(0); shortBuf.put(myShorts, 0, 33); // should fail - System.err.println("ERROR: out-of-bounds put succeeded\n"); + System.out.println("ERROR: out-of-bounds put succeeded\n"); } catch (IndexOutOfBoundsException ioobe) { System.out.println("Got expected out-of-bounds exception"); } @@ -74,7 +74,7 @@ public class Main { try { shortBuf.position(16); shortBuf.put(myShorts, 0, 17); // should fail - System.err.println("ERROR: out-of-bounds put succeeded\n"); + System.out.println("ERROR: out-of-bounds put succeeded\n"); } catch (BufferOverflowException boe) { System.out.println("Got expected buffer overflow exception"); } diff --git a/test/073-mismatched-field/src/Main.java b/test/073-mismatched-field/src/Main.java index 70709c0c86..2d6b9eb51e 100644 --- a/test/073-mismatched-field/src/Main.java +++ b/test/073-mismatched-field/src/Main.java @@ -23,7 +23,7 @@ public class Main extends SuperMain implements IMain { void doit() { try { System.out.println("value=" + this.f); - System.err.println("Succeeded unexpectedly"); + System.out.println("Succeeded unexpectedly"); } catch (IncompatibleClassChangeError icce) { System.out.println("Got expected failure"); } diff --git a/test/074-gc-thrash/src/Main.java b/test/074-gc-thrash/src/Main.java index df0479365f..5165df7bd3 100644 --- a/test/074-gc-thrash/src/Main.java +++ b/test/074-gc-thrash/src/Main.java @@ -52,9 +52,9 @@ public class Main { try { dumpHprofDataMethod.invoke(null, dumpFile); } catch (IllegalAccessException iae) { - System.err.println(iae); + System.out.println(iae); } catch (InvocationTargetException ite) { - System.err.println(ite); + System.out.println(ite); } } @@ -80,7 +80,7 @@ public class Main { try { meth = vmdClass.getMethod("dumpHprofData", String.class); } catch (NoSuchMethodException nsme) { - System.err.println("Found VMDebug but not dumpHprofData method"); + System.out.println("Found VMDebug but not dumpHprofData method"); return null; } @@ -126,7 +126,7 @@ public class Main { deep.join(); large.join(); } catch (InterruptedException ie) { - System.err.println("join was interrupted"); + System.out.println("join was interrupted"); } } @@ -137,7 +137,7 @@ public class Main { try { Thread.sleep(ms); } catch (InterruptedException ie) { - System.err.println("sleep was interrupted"); + System.out.println("sleep was interrupted"); } } @@ -213,7 +213,7 @@ class Deep extends Thread { } if (!once) { - System.err.println("not even once?"); + System.out.println("not even once?"); return; } @@ -229,7 +229,7 @@ class Deep extends Thread { for (int i = 0; i < MAX_DEPTH; i++) { if (weak[i].get() != null) { - System.err.println("Deep: weak still has " + i); + System.out.println("Deep: weak still has " + i); } } @@ -251,7 +251,7 @@ class Deep extends Thread { private static void checkStringReferences() { for (int i = 0; i < MAX_DEPTH; i++) { if (strong[i] != weak[i].get()) { - System.err.println("Deep: " + i + " strong=" + strong[i] + + System.out.println("Deep: " + i + " strong=" + strong[i] + ", weak=" + weak[i].get()); } } diff --git a/test/075-verification-error/src/Main.java b/test/075-verification-error/src/Main.java index 9b66a8d5e1..3f2881eb10 100644 --- a/test/075-verification-error/src/Main.java +++ b/test/075-verification-error/src/Main.java @@ -36,12 +36,12 @@ public class Main { static void testClassNewInstance() { try { MaybeAbstract ma = new MaybeAbstract(); - System.err.println("ERROR: MaybeAbstract succeeded unexpectedly"); + System.out.println("ERROR: MaybeAbstract succeeded unexpectedly"); } catch (InstantiationError ie) { System.out.println("Got expected InstantationError"); if (VERBOSE) System.out.println("--- " + ie); } catch (Exception ex) { - System.err.println("Got unexpected MaybeAbstract failure"); + System.out.println("Got unexpected MaybeAbstract failure"); } } @@ -88,7 +88,7 @@ public class Main { try { int x = mutant.inaccessibleField; - System.err.println("ERROR: bad access succeeded (ifield)"); + System.out.println("ERROR: bad access succeeded (ifield)"); } catch (IllegalAccessError iae) { System.out.println("Got expected IllegalAccessError (ifield)"); if (VERBOSE) System.out.println("--- " + iae); @@ -96,7 +96,7 @@ public class Main { try { int y = Mutant.inaccessibleStaticField; - System.err.println("ERROR: bad access succeeded (sfield)"); + System.out.println("ERROR: bad access succeeded (sfield)"); } catch (IllegalAccessError iae) { System.out.println("Got expected IllegalAccessError (sfield)"); if (VERBOSE) System.out.println("--- " + iae); @@ -104,7 +104,7 @@ public class Main { try { mutant.inaccessibleMethod(); - System.err.println("ERROR: bad access succeeded (method)"); + System.out.println("ERROR: bad access succeeded (method)"); } catch (IllegalAccessError iae) { System.out.println("Got expected IllegalAccessError (method)"); if (VERBOSE) System.out.println("--- " + iae); @@ -112,7 +112,7 @@ public class Main { try { Mutant.inaccessibleStaticMethod(); - System.err.println("ERROR: bad access succeeded (smethod)"); + System.out.println("ERROR: bad access succeeded (smethod)"); } catch (IllegalAccessError iae) { System.out.println("Got expected IllegalAccessError (smethod)"); if (VERBOSE) System.out.println("--- " + iae); @@ -121,7 +121,7 @@ public class Main { try { /* accessible static method in an inaccessible class */ InaccessibleClass.test(); - System.err.println("ERROR: bad meth-class access succeeded (meth-class)"); + System.out.println("ERROR: bad meth-class access succeeded (meth-class)"); } catch (IllegalAccessError iae) { System.out.println("Got expected IllegalAccessError (meth-class)"); if (VERBOSE) System.out.println("--- " + iae); @@ -130,7 +130,7 @@ public class Main { try { /* accessible static field in an inaccessible class */ int blah = InaccessibleClass.blah; - System.err.println("ERROR: bad field-class access succeeded (field-class)"); + System.out.println("ERROR: bad field-class access succeeded (field-class)"); } catch (IllegalAccessError iae) { System.out.println("Got expected IllegalAccessError (field-class)"); if (VERBOSE) System.out.println("--- " + iae); @@ -139,7 +139,7 @@ public class Main { try { /* inaccessible static method in an accessible class */ InaccessibleMethod.test(); - System.err.println("ERROR: bad access succeeded (meth-meth)"); + System.out.println("ERROR: bad access succeeded (meth-meth)"); } catch (IllegalAccessError iae) { System.out.println("Got expected IllegalAccessError (meth-meth)"); if (VERBOSE) System.out.println("--- " + iae); diff --git a/test/077-method-override/src/Main.java b/test/077-method-override/src/Main.java index 84bdf35c29..3a3c528d61 100644 --- a/test/077-method-override/src/Main.java +++ b/test/077-method-override/src/Main.java @@ -37,8 +37,8 @@ public class Main { ((Base)derived).overrideVirtualWithStatic(); } catch (NoSuchMethodError nsme) { /* NSME is subclass of ICCE, so check it explicitly */ - System.err.println("Got NSME - ovws"); - nsme.printStackTrace(System.err); + System.out.println("Got NSME - ovws"); + nsme.printStackTrace(System.out); } catch (IncompatibleClassChangeError icce) { System.out.println("Got expected exception - ovws"); } @@ -46,8 +46,8 @@ public class Main { try { ((Base)derived).overrideStaticWithVirtual(); } catch (NoSuchMethodError nsme) { - System.err.println("Got NSME - oswv"); - nsme.printStackTrace(System.err); + System.out.println("Got NSME - oswv"); + nsme.printStackTrace(System.out); } catch (IncompatibleClassChangeError icce) { System.out.println("Got expected exception - oswv"); } diff --git a/test/079-phantom/src/Main.java b/test/079-phantom/src/Main.java index c54bc0be68..daead2e1dd 100644 --- a/test/079-phantom/src/Main.java +++ b/test/079-phantom/src/Main.java @@ -21,7 +21,7 @@ public class Main { try { Thread.sleep(ms); } catch (InterruptedException ie) { - System.err.println("sleep interrupted"); + System.out.println("sleep interrupted"); } } diff --git a/test/084-class-init/src/Main.java b/test/084-class-init/src/Main.java index 28eb3e923f..a60fbac84f 100644 --- a/test/084-class-init/src/Main.java +++ b/test/084-class-init/src/Main.java @@ -24,7 +24,7 @@ public class Main { // that is currently a resolution stub because it's running on behalf of <clinit>. try { throwDuringClinit(); - System.err.println("didn't throw!"); + System.out.println("didn't throw!"); } catch (NullPointerException ex) { System.out.println("caught exception thrown during clinit"); } @@ -44,34 +44,34 @@ public class Main { try { Thread.sleep(msec); } catch (InterruptedException ie) { - System.err.println("sleep interrupted"); + System.out.println("sleep interrupted"); } } static void checkExceptions() { try { System.out.println(PartialInit.FIELD0); - System.err.println("Construction of PartialInit succeeded unexpectedly"); + System.out.println("Construction of PartialInit succeeded unexpectedly"); } catch (ExceptionInInitializerError eiie) { System.out.println("Got expected EIIE for FIELD0"); } try { System.out.println(PartialInit.FIELD0); - System.err.println("Load of FIELD0 succeeded unexpectedly"); + System.out.println("Load of FIELD0 succeeded unexpectedly"); } catch (NoClassDefFoundError ncdfe) { System.out.println("Got expected NCDFE for FIELD0"); } try { System.out.println(PartialInit.FIELD1); - System.err.println("Load of FIELD1 succeeded unexpectedly"); + System.out.println("Load of FIELD1 succeeded unexpectedly"); } catch (NoClassDefFoundError ncdfe) { System.out.println("Got expected NCDFE for FIELD1"); } try { System.out.println(Exploder.FIELD); - System.err.println("Load of FIELD succeeded unexpectedly"); + System.out.println("Load of FIELD succeeded unexpectedly"); } catch (AssertionError expected) { System.out.println("Got expected '" + expected.getMessage() + "' from Exploder"); } @@ -92,7 +92,7 @@ public class Main { fieldThread.join(); methodThread.join(); } catch (InterruptedException ie) { - System.err.println(ie); + System.out.println(ie); } /* print all values */ diff --git a/test/086-null-super/src/Main.java b/test/086-null-super/src/Main.java index 8bd17860ea..039a9599e1 100644 --- a/test/086-null-super/src/Main.java +++ b/test/086-null-super/src/Main.java @@ -149,14 +149,14 @@ public class Main { loader = new BrokenDexLoader(ClassLoader.getSystemClassLoader()); loader.findBrokenClass(); - System.err.println("ERROR: Inaccessible was accessible"); + System.out.println("ERROR: Inaccessible was accessible"); } catch (InvocationTargetException ite) { Throwable cause = ite.getCause(); if (cause instanceof NullPointerException) { - System.err.println("Got expected ITE/NPE"); + System.out.println("Got expected ITE/NPE"); } else { - System.err.println("Got unexpected ITE"); - ite.printStackTrace(); + System.out.println("Got unexpected ITE"); + ite.printStackTrace(System.out); } } } diff --git a/test/088-monitor-verification/src/Main.java b/test/088-monitor-verification/src/Main.java index a6f0e642d4..bca3df6828 100644 --- a/test/088-monitor-verification/src/Main.java +++ b/test/088-monitor-verification/src/Main.java @@ -41,7 +41,7 @@ public class Main { m.nestedMayThrow(false); try { m.nestedMayThrow(true); - System.err.println("nestedThrow(true) did not throw"); + System.out.println("nestedThrow(true) did not throw"); } catch (MyException me) {} System.out.println("nestedMayThrow ok"); diff --git a/test/092-locale/src/Main.java b/test/092-locale/src/Main.java index 8916a29c47..60c0551b84 100644 --- a/test/092-locale/src/Main.java +++ b/test/092-locale/src/Main.java @@ -34,31 +34,31 @@ public class Main { try { testCalendar(); } catch (Exception ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); } try { testDateFormatSymbols(); } catch (Exception ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); } try { testCurrency(); } catch (Exception ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); } try { testNormalizer(); } catch (Exception ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); } try { testIso3(); } catch (Exception ex) { - ex.printStackTrace(); + ex.printStackTrace(System.out); } } @@ -125,13 +125,13 @@ public class Main { res = Normalizer.normalize(composed, Normalizer.Form.NFD); if (!decomposed.equals(res)) { - System.err.println("Bad decompose: '" + composed + "' --> '" + System.out.println("Bad decompose: '" + composed + "' --> '" + res + "'"); } res = Normalizer.normalize(decomposed, Normalizer.Form.NFC); if (!composed.equals(res)) { - System.err.println("Bad compose: '" + decomposed + "' --> '" + System.out.println("Bad compose: '" + decomposed + "' --> '" + res + "'"); } @@ -153,7 +153,7 @@ public class Main { try { System.out.println(" iso3=" + loc.getISO3Language()); } catch (MissingResourceException mre) { - System.err.println("couldn't get iso3 language"); + System.out.println("couldn't get iso3 language"); } } } diff --git a/test/095-switch-MAX_INT/src/Main.java b/test/095-switch-MAX_INT/src/Main.java index d1171ea6bc..a004a1aede 100644 --- a/test/095-switch-MAX_INT/src/Main.java +++ b/test/095-switch-MAX_INT/src/Main.java @@ -2,7 +2,7 @@ public class Main { static public void main(String[] args) throws Exception { switch (0x7fffffff) { case 0x7fffffff: - System.err.println("good"); + System.out.println("good"); break; default: throw new AssertionError(); diff --git a/test/100-reflect2/src/Main.java b/test/100-reflect2/src/Main.java index 91ba3075f4..5f6ffa8ae9 100644 --- a/test/100-reflect2/src/Main.java +++ b/test/100-reflect2/src/Main.java @@ -292,7 +292,7 @@ class Main { // Expected. } catch (Exception e) { // Error. - e.printStackTrace(); + e.printStackTrace(System.out); } } @@ -304,7 +304,7 @@ class Main { cons.newInstance(); } catch (Exception e) { // Error. - e.printStackTrace(); + e.printStackTrace(System.out); } } diff --git a/test/101-fibonacci/src/Main.java b/test/101-fibonacci/src/Main.java index c594edbded..9c57ba76eb 100644 --- a/test/101-fibonacci/src/Main.java +++ b/test/101-fibonacci/src/Main.java @@ -51,7 +51,7 @@ class Main { y = fibonacci(x + 1); System.out.printf("fibonacci(%d)=%d\n", x + 1, y); } catch (NumberFormatException ex) { - System.err.println(ex); + System.out.println(ex); System.exit(1); } } diff --git a/test/109-suspend-check/src/Main.java b/test/109-suspend-check/src/Main.java index 3c3353b4db..e140a59173 100644 --- a/test/109-suspend-check/src/Main.java +++ b/test/109-suspend-check/src/Main.java @@ -55,7 +55,7 @@ public class Main { try { Thread.sleep(ms); } catch (InterruptedException ie) { - System.err.println("sleep was interrupted"); + System.out.println("sleep was interrupted"); } } } diff --git a/test/114-ParallelGC/src/Main.java b/test/114-ParallelGC/src/Main.java index 159dd5c926..2199872ba6 100644 --- a/test/114-ParallelGC/src/Main.java +++ b/test/114-ParallelGC/src/Main.java @@ -82,7 +82,7 @@ public class Main implements Runnable { // Any exception or error getting here is bad. try { // May need allocations... - t.printStackTrace(System.err); + t.printStackTrace(System.out); } catch (Throwable tInner) { } System.exit(1); diff --git a/test/120-hashcode/src/Main.java b/test/120-hashcode/src/Main.java index d2435cee62..0955f50c1a 100644 --- a/test/120-hashcode/src/Main.java +++ b/test/120-hashcode/src/Main.java @@ -30,7 +30,7 @@ public class Main { // Make sure that all the hashes agree. if (hashOrig != hashInflated || hashOrig != hashSystemOrig || hashSystemOrig != hashSystemInflated) { - System.err.println("hash codes dont match: " + hashOrig + " " + hashInflated + " " + + System.out.println("hash codes dont match: " + hashOrig + " " + hashInflated + " " + hashSystemOrig + " " + hashSystemInflated); } System.out.println("Done."); diff --git a/test/130-hprof/src/Main.java b/test/130-hprof/src/Main.java index 5899dd1183..a8597f1391 100644 --- a/test/130-hprof/src/Main.java +++ b/test/130-hprof/src/Main.java @@ -140,7 +140,7 @@ public class Main { allocator.join(); dumper.join(); } catch (InterruptedException e) { - System.err.println("join interrupted"); + System.out.println("join interrupted"); } } @@ -178,7 +178,7 @@ public class Main { try { Thread.sleep(ms); } catch (InterruptedException e) { - System.err.println("sleep interrupted"); + System.out.println("sleep interrupted"); } } @@ -223,7 +223,7 @@ public class Main { try { meth = vmdClass.getMethod("dumpHprofData", String.class); } catch (NoSuchMethodException nsme) { - System.err.println("Found VMDebug but not dumpHprofData method"); + System.out.println("Found VMDebug but not dumpHprofData method"); return null; } diff --git a/test/1337-gc-coverage/gc_coverage.cc b/test/1337-gc-coverage/gc_coverage.cc index 1cb2fb0976..ac959f68e8 100644 --- a/test/1337-gc-coverage/gc_coverage.cc +++ b/test/1337-gc-coverage/gc_coverage.cc @@ -18,7 +18,7 @@ #include "jni.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace { diff --git a/test/135-MirandaDispatch/src/Main.java b/test/135-MirandaDispatch/src/Main.java index ada8cefead..ab2a90b3b7 100644 --- a/test/135-MirandaDispatch/src/Main.java +++ b/test/135-MirandaDispatch/src/Main.java @@ -53,7 +53,7 @@ public class Main { } catch (VerifyError expected) { System.out.println("b/21646347"); } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(System.out); } System.out.println("Finishing"); } diff --git a/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc b/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc index b7293015cf..7d40f5773d 100644 --- a/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc +++ b/test/136-daemon-jni-shutdown/daemon_jni_shutdown.cc @@ -21,7 +21,7 @@ #include "base/macros.h" #include "java_vm_ext.h" #include "jni_env_ext.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace { diff --git a/test/138-duplicate-classes-check/src/Main.java b/test/138-duplicate-classes-check/src/Main.java index 5ffceb94fe..b32f0bcc46 100644 --- a/test/138-duplicate-classes-check/src/Main.java +++ b/test/138-duplicate-classes-check/src/Main.java @@ -42,7 +42,7 @@ public class Main { Method test = testEx.getDeclaredMethod("test"); test.invoke(null); } catch (Exception exc) { - exc.printStackTrace(); + exc.printStackTrace(System.out); } } } diff --git a/test/138-duplicate-classes-check2/src/Main.java b/test/138-duplicate-classes-check2/src/Main.java index a0d6977405..faf8b5d337 100644 --- a/test/138-duplicate-classes-check2/src/Main.java +++ b/test/138-duplicate-classes-check2/src/Main.java @@ -37,7 +37,7 @@ public class Main { Method test = testEx.getDeclaredMethod("test"); test.invoke(null); } catch (Exception exc) { - exc.printStackTrace(); + exc.printStackTrace(System.out); } } } diff --git a/test/141-class-unload/jni_unload.cc b/test/141-class-unload/jni_unload.cc index 9b7e171a95..355457d68d 100644 --- a/test/141-class-unload/jni_unload.cc +++ b/test/141-class-unload/jni_unload.cc @@ -20,7 +20,7 @@ #include "jit/jit.h" #include "runtime.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace { diff --git a/test/141-class-unload/src/Main.java b/test/141-class-unload/src/Main.java index 7e8431fb52..9072c8b538 100644 --- a/test/141-class-unload/src/Main.java +++ b/test/141-class-unload/src/Main.java @@ -50,7 +50,7 @@ public class Main { // Test that objects keep class loader live for sticky GC. testStickyUnload(constructor); } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(System.out); } } diff --git a/test/142-classloader2/src/Main.java b/test/142-classloader2/src/Main.java index a0c77645a3..193fd5dea0 100644 --- a/test/142-classloader2/src/Main.java +++ b/test/142-classloader2/src/Main.java @@ -91,7 +91,7 @@ public class Main { if (e.getCause() instanceof VerifyError) { System.out.println("Caught wrapped VerifyError."); } else { - e.printStackTrace(); + e.printStackTrace(System.out); } } diff --git a/test/146-bad-interface/src/Main.java b/test/146-bad-interface/src/Main.java index 5534bb4bba..958ec7c3c4 100644 --- a/test/146-bad-interface/src/Main.java +++ b/test/146-bad-interface/src/Main.java @@ -37,7 +37,7 @@ public class Main { } catch (Throwable t) { System.out.println("Error occurred"); System.out.println(t); - t.printStackTrace(); + t.printStackTrace(System.out); } } } diff --git a/test/148-multithread-gc-annotations/gc_coverage.cc b/test/148-multithread-gc-annotations/gc_coverage.cc index 4862b87057..f48493c684 100644 --- a/test/148-multithread-gc-annotations/gc_coverage.cc +++ b/test/148-multithread-gc-annotations/gc_coverage.cc @@ -18,7 +18,7 @@ #include "jni.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace { diff --git a/test/155-java-set-resolved-type/src/Main.java b/test/155-java-set-resolved-type/src/Main.java index 8f79bd7ecd..44278a1c9a 100644 --- a/test/155-java-set-resolved-type/src/Main.java +++ b/test/155-java-set-resolved-type/src/Main.java @@ -61,7 +61,7 @@ public class Main { // to be resolved and found through simple lookup. timpl.newInstance(); } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(System.out); } } diff --git a/test/156-register-dex-file-multi-loader/src/Main.java b/test/156-register-dex-file-multi-loader/src/Main.java index ff5a2bd570..6aa1d780d3 100644 --- a/test/156-register-dex-file-multi-loader/src/Main.java +++ b/test/156-register-dex-file-multi-loader/src/Main.java @@ -81,7 +81,7 @@ public class Main { !message.endsWith(" with multiple class loaders"); } if (unexpected) { - cnfe.getCause().printStackTrace(); + cnfe.getCause().printStackTrace(System.out); } } } diff --git a/test/158-app-image-class-table/src/Main.java b/test/158-app-image-class-table/src/Main.java index 804468fe91..97aa14d4b1 100644 --- a/test/158-app-image-class-table/src/Main.java +++ b/test/158-app-image-class-table/src/Main.java @@ -39,7 +39,7 @@ public class Main { // to be resolved and found through simple lookup. timpl.newInstance(); } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(System.out); } } diff --git a/test/159-app-image-fields/src/Main.java b/test/159-app-image-fields/src/Main.java index d06a50204a..47d0116a19 100644 --- a/test/159-app-image-fields/src/Main.java +++ b/test/159-app-image-fields/src/Main.java @@ -57,7 +57,7 @@ public class Main { System.out.println("another_value: " + another_value); } } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(System.out); } } diff --git a/test/301-abstract-protected/src/Main.java b/test/301-abstract-protected/src/Main.java index 9b19a9d56b..f12026791e 100644 --- a/test/301-abstract-protected/src/Main.java +++ b/test/301-abstract-protected/src/Main.java @@ -16,7 +16,7 @@ public class Main { public static void main(String args[]) throws Exception { - System.err.println(new C().m()); + System.out.println(new C().m()); } } diff --git a/test/487-checker-inline-calls/src/Main.java b/test/487-checker-inline-calls/src/Main.java index 70384d5a7f..00694f359f 100644 --- a/test/487-checker-inline-calls/src/Main.java +++ b/test/487-checker-inline-calls/src/Main.java @@ -20,7 +20,7 @@ public class Main { try { doTopCall(); } catch (Error e) { - e.printStackTrace(); + e.printStackTrace(System.out); } } diff --git a/test/488-checker-inline-recursive-calls/src/Main.java b/test/488-checker-inline-recursive-calls/src/Main.java index 441dbbfcb6..1137837048 100644 --- a/test/488-checker-inline-recursive-calls/src/Main.java +++ b/test/488-checker-inline-recursive-calls/src/Main.java @@ -20,7 +20,7 @@ public class Main { try { doTopCall(true); } catch (Error e) { - e.printStackTrace(); + e.printStackTrace(System.out); } } diff --git a/test/492-checker-inline-invoke-interface/src/Main.java b/test/492-checker-inline-invoke-interface/src/Main.java index a919690000..785c0db0eb 100644 --- a/test/492-checker-inline-invoke-interface/src/Main.java +++ b/test/492-checker-inline-invoke-interface/src/Main.java @@ -21,7 +21,7 @@ interface Itf { class ForceStatic { static { System.out.println("Hello from clinit"); - new Exception().printStackTrace(); + new Exception().printStackTrace(System.out); } static int field; } diff --git a/test/493-checker-inline-invoke-interface/src/Main.java b/test/493-checker-inline-invoke-interface/src/Main.java index 171405ca44..0570b20a40 100644 --- a/test/493-checker-inline-invoke-interface/src/Main.java +++ b/test/493-checker-inline-invoke-interface/src/Main.java @@ -21,7 +21,7 @@ interface Itf { class ForceStatic { static { System.out.println("Hello from clinit"); - new Exception().printStackTrace(); + new Exception().printStackTrace(System.out); } static int field; } diff --git a/test/497-inlining-and-class-loader/src/Main.java b/test/497-inlining-and-class-loader/src/Main.java index 1e27e77786..01b4bcd391 100644 --- a/test/497-inlining-and-class-loader/src/Main.java +++ b/test/497-inlining-and-class-loader/src/Main.java @@ -121,7 +121,7 @@ class Main { // Because we cleared dex cache entries, we will have to find // classes again, which require to use the correct class loader // in the presence of inlining. - new Exception().printStackTrace(); + new Exception().printStackTrace(System.out); } static Object savedResolvedMethods; diff --git a/test/522-checker-regression-monitor-exit/src/Main.java b/test/522-checker-regression-monitor-exit/src/Main.java index c4f80fc9c6..5c26f36fe8 100644 --- a/test/522-checker-regression-monitor-exit/src/Main.java +++ b/test/522-checker-regression-monitor-exit/src/Main.java @@ -43,8 +43,8 @@ public class Main { Method m = c.getMethod("synchronizedHashCode", Object.class); result = (Integer) m.invoke(null, m_obj); } catch (Exception e) { - System.err.println("Hash code query exception"); - e.printStackTrace(); + System.out.println("Hash code query exception"); + e.printStackTrace(System.out); result = -1; } return result; @@ -77,7 +77,7 @@ public class Main { } pool.shutdown(); } catch (CancellationException ex) { - System.err.println("Job timeout"); + System.out.println("Job timeout"); System.exit(1); } } diff --git a/test/570-checker-osr/osr.cc b/test/570-checker-osr/osr.cc index 8eca6b2ccb..45ead6b204 100644 --- a/test/570-checker-osr/osr.cc +++ b/test/570-checker-osr/osr.cc @@ -21,6 +21,7 @@ #include "oat_quick_method_header.h" #include "scoped_thread_state_change-inl.h" #include "ScopedUtfChars.h" +#include "stack.h" #include "stack_map.h" namespace art { diff --git a/test/570-checker-osr/src/DeoptimizationController.java b/test/570-checker-osr/src/DeoptimizationController.java index 907d133d3b..e272607ec4 100644 --- a/test/570-checker-osr/src/DeoptimizationController.java +++ b/test/570-checker-osr/src/DeoptimizationController.java @@ -53,7 +53,7 @@ public class DeoptimizationController { throw new IllegalStateException("Not tracing."); } } catch (Exception exc) { - exc.printStackTrace(System.err); + exc.printStackTrace(System.out); } finally { if (tempFile != null) { tempFile.delete(); @@ -68,7 +68,7 @@ public class DeoptimizationController { throw new IllegalStateException("Still tracing."); } } catch (Exception exc) { - exc.printStackTrace(System.err); + exc.printStackTrace(System.out); } } diff --git a/test/595-profile-saving/profile-saving.cc b/test/595-profile-saving/profile-saving.cc index 0f8dd57385..019ddad595 100644 --- a/test/595-profile-saving/profile-saving.cc +++ b/test/595-profile-saving/profile-saving.cc @@ -26,6 +26,7 @@ #include "oat_file_manager.h" #include "scoped_thread_state_change-inl.h" #include "ScopedUtfChars.h" +#include "stack.h" #include "thread.h" namespace art { diff --git a/test/596-app-images/src/Main.java b/test/596-app-images/src/Main.java index 674ba4d037..88d95f4162 100644 --- a/test/596-app-images/src/Main.java +++ b/test/596-app-images/src/Main.java @@ -101,7 +101,7 @@ class Main { assertEqual(StaticInternString.getIntent(), getIntent.invoke(staticInternString), "Dynamically loaded app image's literal strings not interned properly."); } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(System.out); } } diff --git a/test/596-monitor-inflation/monitor_inflation.cc b/test/596-monitor-inflation/monitor_inflation.cc index fb4275b711..07d1ddbe69 100644 --- a/test/596-monitor-inflation/monitor_inflation.cc +++ b/test/596-monitor-inflation/monitor_inflation.cc @@ -18,7 +18,7 @@ #include "jni.h" #include "monitor.h" #include "runtime.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { namespace { diff --git a/test/602-deoptimizeable/src/Main.java b/test/602-deoptimizeable/src/Main.java index 743a5796c9..d995923f88 100644 --- a/test/602-deoptimizeable/src/Main.java +++ b/test/602-deoptimizeable/src/Main.java @@ -99,7 +99,7 @@ public class Main { System.exit(0); } } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(System.out); } } }); @@ -127,7 +127,7 @@ public class Main { map.put(new DummyObject(10), Long.valueOf(100)); assertIsInterpreted(); // Every deoptimizeable method is deoptimized. } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(System.out); } } }); diff --git a/test/617-clinit-oome/src/Main.java b/test/617-clinit-oome/src/Main.java index 749a2325ef..94cb7ce7db 100644 --- a/test/617-clinit-oome/src/Main.java +++ b/test/617-clinit-oome/src/Main.java @@ -37,7 +37,7 @@ public class Main { Other.print(); } catch (OutOfMemoryError e) { } catch (Exception e) { - System.err.println(e); + System.out.println(e); } } } diff --git a/test/626-const-class-linking/src/RacyMisbehavingHelper.java b/test/626-const-class-linking/src/RacyMisbehavingHelper.java index 45252789e4..9acd3c3ff6 100644 --- a/test/626-const-class-linking/src/RacyMisbehavingHelper.java +++ b/test/626-const-class-linking/src/RacyMisbehavingHelper.java @@ -26,7 +26,7 @@ public class RacyMisbehavingHelper { Method reportAfterLoading = loader.getClass().getDeclaredMethod("reportAfterLoading"); reportAfterLoading.invoke(loader); } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(System.out); } return new ClassPair(helper1_class, test_class); } diff --git a/test/638-no-line-number/src/Main.java b/test/638-no-line-number/src/Main.java index 7fe0404204..851f049ba6 100644 --- a/test/638-no-line-number/src/Main.java +++ b/test/638-no-line-number/src/Main.java @@ -19,12 +19,12 @@ public class Main { try { doThrow(new Error()); } catch (Error e) { - e.printStackTrace(); + e.printStackTrace(System.out); } try { doThrow(null); } catch (Throwable t) { - t.printStackTrace(); + t.printStackTrace(System.out); } } diff --git a/test/654-checker-periodic/expected.txt b/test/654-checker-periodic/expected.txt new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/test/654-checker-periodic/expected.txt @@ -0,0 +1 @@ +passed diff --git a/test/654-checker-periodic/info.txt b/test/654-checker-periodic/info.txt new file mode 100644 index 0000000000..7c8a7770ae --- /dev/null +++ b/test/654-checker-periodic/info.txt @@ -0,0 +1 @@ +Periodic sequence on integer and floating-point. diff --git a/test/654-checker-periodic/src/Main.java b/test/654-checker-periodic/src/Main.java new file mode 100644 index 0000000000..7a0c98cfae --- /dev/null +++ b/test/654-checker-periodic/src/Main.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2017 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. + */ + +/** + * Tests for last value of a few periodic sequences + * (found by fuzz testing). + */ +public class Main { + + /// CHECK-START: int Main.doitUpInt(int) loop_optimization (before) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none + // + /// CHECK-START: int Main.doitUpInt(int) loop_optimization (after) + /// CHECK-NOT: Phi + static int doitUpInt(int n) { + // Complete loop is replaced by last-value. + int lI = 1; + for (int i1 = 0; i1 < n; i1++) { + lI = (1486662021 - lI); + } + return lI; + } + + /// CHECK-START: int Main.doitDownInt(int) loop_optimization (before) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none + // + /// CHECK-START: int Main.doitDownInt(int) loop_optimization (after) + /// CHECK-NOT: Phi + static int doitDownInt(int n) { + // Complete loop is replaced by last-value. + int lI = 1; + for (int i1 = n - 1; i1 >= 0; i1--) { + lI = (1486662021 - lI); + } + return lI; + } + + /// CHECK-START: float Main.doitUpFloat(int) loop_optimization (before) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none + // + /// CHECK-START: float Main.doitUpFloat(int) loop_optimization (after) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none + static float doitUpFloat(int n) { + // FP arithmetic is not sufficiently precise. + // The loop remains. + float lF = 1.0f; + for (int i1 = 0; i1 < n; i1++) { + lF = (1486662021.0f - lF); + } + return lF; + } + + /// CHECK-START: float Main.doitDownFloat(int) loop_optimization (before) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none + // + /// CHECK-START: float Main.doitDownFloat(int) loop_optimization (after) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none + static float doitDownFloat(int n) { + // FP arithmetic is not sufficiently precise. + // The loop remains. + float lF = 1.0f; + for (int i1 = n - 1; i1 >= 0; i1--) { + lF = (1486662021.0f - lF); + } + return lF; + } + + /// CHECK-START: float Main.doitUpFloatAlt(int) loop_optimization (before) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none + // + /// CHECK-START: float Main.doitUpFloatAlt(int) loop_optimization (after) + /// CHECK-NOT: Phi + static float doitUpFloatAlt(int n) { + // Complete loop is replaced by last-value + // since the values are now precise. + float lF = 1.0f; + float l2 = 1486662020.0f; + for (int i1 = 0; i1 < n; i1++) { + float old = lF; + lF = l2; + l2 = old; + } + return lF; + } + + /// CHECK-START: float Main.doitDownFloatAlt(int) loop_optimization (before) + /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none + /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none + // + /// CHECK-START: float Main.doitDownFloatAlt(int) loop_optimization (after) + /// CHECK-NOT: Phi + static float doitDownFloatAlt(int n) { + // Complete loop is replaced by last-value + // since the values are now precise. + float lF = 1.0f; + float l2 = 1486662020.0f; + for (int i1 = n - 1; i1 >= 0; i1--) { + float old = lF; + lF = l2; + l2 = old; + } + return lF; + } + + // Main driver. + public static void main(String[] args) { + for (int i = 0; i < 10; i++) { + int ei = (i & 1) == 0 ? 1 : 1486662020; + int ci = doitUpInt(i); + expectEquals(ei, ci); + } + for (int i = 0; i < 10; i++) { + int ei = (i & 1) == 0 ? 1 : 1486662020; + int ci = doitDownInt(i); + expectEquals(ei, ci); + } + for (int i = 0; i < 10; i++) { + float ef = i == 0 ? 1.0f : ((i & 1) == 0 ? 0.0f : 1486662021.0f); + float cf = doitUpFloat(i); + expectEquals(ef, cf); + } + for (int i = 0; i < 10; i++) { + float ef = i == 0 ? 1.0f : ((i & 1) == 0 ? 0.0f : 1486662021.0f); + float cf = doitDownFloat(i); + expectEquals(ef, cf); + } + for (int i = 0; i < 10; i++) { + float ef = (i & 1) == 0 ? 1.0f : 1486662020.0f; + float cf = doitUpFloatAlt(i); + expectEquals(ef, cf); + } + for (int i = 0; i < 10; i++) { + float ef = (i & 1) == 0 ? 1.0f : 1486662020.0f; + float cf = doitDownFloatAlt(i); + expectEquals(ef, cf); + } + System.out.println("passed"); + } + + private static void expectEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } + + private static void expectEquals(float expected, float result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} + + diff --git a/test/802-deoptimization/src/DeoptimizationController.java b/test/802-deoptimization/src/DeoptimizationController.java index d6e662d04d..88579ded07 100644 --- a/test/802-deoptimization/src/DeoptimizationController.java +++ b/test/802-deoptimization/src/DeoptimizationController.java @@ -50,7 +50,7 @@ public class DeoptimizationController { throw new IllegalStateException("Not tracing."); } } catch (Exception exc) { - exc.printStackTrace(System.err); + exc.printStackTrace(System.out); } finally { if (tempFile != null) { tempFile.delete(); @@ -65,7 +65,7 @@ public class DeoptimizationController { throw new IllegalStateException("Still tracing."); } } catch (Exception exc) { - exc.printStackTrace(System.err); + exc.printStackTrace(System.out); } } diff --git a/test/909-attach-agent/src/Main.java b/test/909-attach-agent/src/Main.java index 569b89ad7d..25ebd57236 100644 --- a/test/909-attach-agent/src/Main.java +++ b/test/909-attach-agent/src/Main.java @@ -19,17 +19,17 @@ import java.io.IOException; public class Main { public static void main(String[] args) { - System.err.println("Hello, world!"); + System.out.println("Hello, world!"); for(String a : args) { if(a.startsWith("agent:")) { String agent = a.substring(6); try { VMDebug.attachAgent(agent); } catch(IOException e) { - e.printStackTrace(); + e.printStackTrace(System.out); } } } - System.err.println("Goodbye!"); + System.out.println("Goodbye!"); } } diff --git a/test/916-obsolete-jit/src/Main.java b/test/916-obsolete-jit/src/Main.java index 17a7a86ccc..d7b32ba102 100644 --- a/test/916-obsolete-jit/src/Main.java +++ b/test/916-obsolete-jit/src/Main.java @@ -132,7 +132,7 @@ public class Main { "sayHi", Runnable.class, Consumer.class); } catch (Exception e) { System.out.println("Unable to find methods!"); - e.printStackTrace(); + e.printStackTrace(System.out); return; } // Makes sure the stack is the way we want it for the test and does the redefinition. It will diff --git a/test/934-load-transform/src/Main.java b/test/934-load-transform/src/Main.java index 1401b7df01..2d0c2978e2 100644 --- a/test/934-load-transform/src/Main.java +++ b/test/934-load-transform/src/Main.java @@ -86,7 +86,7 @@ class Main { run_test.invoke(null); } catch (Exception e) { System.out.println(e.toString()); - e.printStackTrace(); + e.printStackTrace(System.out); } } } diff --git a/test/935-non-retransformable/src/Main.java b/test/935-non-retransformable/src/Main.java index f240224977..5098712044 100644 --- a/test/935-non-retransformable/src/Main.java +++ b/test/935-non-retransformable/src/Main.java @@ -97,7 +97,7 @@ class Main { run_test.invoke(null); } catch (Exception e) { System.out.println(e.toString()); - e.printStackTrace(); + e.printStackTrace(System.out); } } } diff --git a/test/938-load-transform-bcp/src-ex/TestMain.java b/test/938-load-transform-bcp/src-ex/TestMain.java index 3757a0f778..b60fe36556 100644 --- a/test/938-load-transform-bcp/src-ex/TestMain.java +++ b/test/938-load-transform-bcp/src-ex/TestMain.java @@ -29,7 +29,7 @@ public class TestMain { System.out.println( "Exception occured (did something load OptionalLong before this test method!: " + e.toString()); - e.printStackTrace(); + e.printStackTrace(System.out); } } } diff --git a/test/938-load-transform-bcp/src/Main.java b/test/938-load-transform-bcp/src/Main.java index 69658c0cec..939bdbe02b 100644 --- a/test/938-load-transform-bcp/src/Main.java +++ b/test/938-load-transform-bcp/src/Main.java @@ -111,7 +111,7 @@ class Main { run_test.invoke(null); } catch (Exception e) { System.out.println(e.toString()); - e.printStackTrace(); + e.printStackTrace(System.out); } } } diff --git a/test/941-recurive-obsolete-jit/src/Main.java b/test/941-recurive-obsolete-jit/src/Main.java index 89d593b7cd..e3065a7117 100644 --- a/test/941-recurive-obsolete-jit/src/Main.java +++ b/test/941-recurive-obsolete-jit/src/Main.java @@ -116,7 +116,7 @@ public class Main { "sayHi", int.class, Consumer.class, Runnable.class); } catch (Exception e) { System.out.println("Unable to find methods!"); - e.printStackTrace(); + e.printStackTrace(System.out); return; } // Makes sure the stack is the way we want it for the test and does the redefinition. It will diff --git a/test/943-private-recursive-jit/src/Main.java b/test/943-private-recursive-jit/src/Main.java index 871c63674f..09337bae26 100644 --- a/test/943-private-recursive-jit/src/Main.java +++ b/test/943-private-recursive-jit/src/Main.java @@ -129,7 +129,7 @@ public class Main { "privateSayHi", int.class, Consumer.class, Runnable.class); } catch (Exception e) { System.out.println("Unable to find methods!"); - e.printStackTrace(); + e.printStackTrace(System.out); return; } // Makes sure the stack is the way we want it for the test and does the redefinition. It will diff --git a/test/947-reflect-method/src/art/Test947.java b/test/947-reflect-method/src/art/Test947.java index 8cb515e492..90e0f81989 100644 --- a/test/947-reflect-method/src/art/Test947.java +++ b/test/947-reflect-method/src/art/Test947.java @@ -76,7 +76,7 @@ public class Test947 { Redefinition.doCommonClassRedefinition(Transform.class, CLASS_BYTES, DEX_BYTES); say_hi_method.invoke(t); } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(System.out); } } } diff --git a/test/953-invoke-polymorphic-compiler/src/Main.java b/test/953-invoke-polymorphic-compiler/src/Main.java index 20a8fec112..ce3f4db5d4 100644 --- a/test/953-invoke-polymorphic-compiler/src/Main.java +++ b/test/953-invoke-polymorphic-compiler/src/Main.java @@ -70,30 +70,30 @@ public class Main { } public static void fail() { - System.err.println("fail"); + System.out.println("fail"); Thread.dumpStack(); } public static void fail(String message) { - System.err.println("fail: " + message); + System.out.println("fail: " + message); Thread.dumpStack(); } public static int Min2Print2(int a, int b) { int[] values = new int[] { a, b }; - System.err.println("Running Main.Min2Print2(" + Arrays.toString(values) + ")"); + System.out.println("Running Main.Min2Print2(" + Arrays.toString(values) + ")"); return a > b ? a : b; } public static int Min2Print3(int a, int b, int c) { int[] values = new int[] { a, b, c }; - System.err.println("Running Main.Min2Print3(" + Arrays.toString(values) + ")"); + System.out.println("Running Main.Min2Print3(" + Arrays.toString(values) + ")"); return a > b ? a : b; } public static int Min2Print6(int a, int b, int c, int d, int e, int f) { int[] values = new int[] { a, b, c, d, e, f }; - System.err.println("Running Main.Min2Print6(" + Arrays.toString(values) + ")"); + System.out.println("Running Main.Min2Print6(" + Arrays.toString(values) + ")"); return a > b ? a : b; } @@ -106,7 +106,7 @@ public class Main { int y, int z) { int[] values = new int[] { a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z }; - System.err.println("Running Main.Min2Print26(" + Arrays.toString(values) + ")"); + System.out.println("Running Main.Min2Print26(" + Arrays.toString(values) + ")"); return a > b ? a : b; } @@ -176,7 +176,7 @@ public class Main { fail("No NPE for you"); } catch (NullPointerException npe) {} - System.err.println("BasicTest done."); + System.out.println("BasicTest done."); } private static boolean And(boolean lhs, boolean rhs) { @@ -248,7 +248,7 @@ public class Main { assertEquals(true, (boolean) mh.invoke(false, true)); assertEquals(false, (boolean) mh.invoke(false, false)); - System.err.println("$opt$ReturnBooleanTest done."); + System.out.println("$opt$ReturnBooleanTest done."); } public static void $opt$ReturnCharTest() throws Throwable { @@ -257,7 +257,7 @@ public class Main { MethodType.methodType(char.class, char.class)); assertEquals('B', (char) mh.invokeExact('A')); assertEquals((char) -55, (char) mh.invokeExact((char) -56)); - System.err.println("$opt$ReturnCharTest done."); + System.out.println("$opt$ReturnCharTest done."); } public static void $opt$ReturnByteTest() throws Throwable { @@ -266,7 +266,7 @@ public class Main { MethodType.methodType(byte.class, byte.class, byte.class)); assertEquals((byte) 30, (byte) mh.invokeExact((byte) 10, (byte) 3)); assertEquals((byte) -90, (byte) mh.invoke((byte) -10, (byte) 9)); - System.err.println("$opt$ReturnByteTest done."); + System.out.println("$opt$ReturnByteTest done."); } public static void $opt$ReturnShortTest() throws Throwable { @@ -275,7 +275,7 @@ public class Main { MethodType.methodType(short.class, short.class, short.class)); assertEquals((short) 3000, (short) mh.invokeExact((short) 1000, (short) 3)); assertEquals((short) -3000, (short) mh.invoke((short) -1000, (short) 3)); - System.err.println("$opt$ReturnShortTest done."); + System.out.println("$opt$ReturnShortTest done."); } public static void $opt$ReturnIntTest() throws Throwable { @@ -284,7 +284,7 @@ public class Main { MethodType.methodType(int.class, int.class, int.class)); assertEquals(3_000_000, (int) mh.invokeExact(1_000_000, 3)); assertEquals(-3_000_000, (int) mh.invoke(-1_000, 3_000)); - System.err.println("$opt$ReturnIntTest done."); + System.out.println("$opt$ReturnIntTest done."); } public static void $opt$ReturnLongTest() throws Throwable { @@ -293,7 +293,7 @@ public class Main { MethodType.methodType(long.class, long.class, long.class)); assertEquals(4_294_967_295_000L, (long) mh.invokeExact(1000L, 4_294_967_295L)); assertEquals(-4_294_967_295_000L, (long) mh.invoke(-1000L, 4_294_967_295L)); - System.err.println("$opt$ReturnLongTest done."); + System.out.println("$opt$ReturnLongTest done."); } public static void $opt$ReturnFloatTest() throws Throwable { @@ -302,7 +302,7 @@ public class Main { MethodType.methodType(float.class, float.class, float.class)); assertEquals(3.0F, (float) mh.invokeExact(1000.0F, 3e-3F)); assertEquals(-3.0F, (float) mh.invoke(-1000.0F, 3e-3F)); - System.err.println("$opt$ReturnFloatTest done."); + System.out.println("$opt$ReturnFloatTest done."); } public static void $opt$ReturnDoubleTest() throws Throwable { @@ -311,7 +311,7 @@ public class Main { MethodType.methodType(double.class, double.class, double.class)); assertEquals(3033000.0, (double) mh.invokeExact(1000.0, 3.033e3)); assertEquals(-3033000.0, (double) mh.invoke(-1000.0, 3.033e3)); - System.err.println("$opt$ReturnDoubleTest done."); + System.out.println("$opt$ReturnDoubleTest done."); } public static void $opt$ReturnStringTest() throws Throwable { @@ -320,7 +320,7 @@ public class Main { MethodType.methodType(String.class, String.class, int.class)); assertEquals("100010001000", (String) mh.invokeExact("1000", 3)); assertEquals("100010001000", (String) mh.invoke("1000", 3)); - System.err.println("$opt$ReturnStringTest done."); + System.out.println("$opt$ReturnStringTest done."); } public static void ReturnValuesTest() throws Throwable { @@ -333,7 +333,7 @@ public class Main { $opt$ReturnFloatTest(); $opt$ReturnDoubleTest(); $opt$ReturnStringTest(); - System.err.println("ReturnValuesTest done."); + System.out.println("ReturnValuesTest done."); } static class ValueHolder { diff --git a/test/972-default-imt-collision/src/Main.java b/test/972-default-imt-collision/src/Main.java index 6819e43ae7..043cef1147 100644 --- a/test/972-default-imt-collision/src/Main.java +++ b/test/972-default-imt-collision/src/Main.java @@ -24,7 +24,7 @@ public class Main { Method test = c.getMethod("testMe", iface); test.invoke(null, o); } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(System.out); System.out.println("FAILED: could not run testMe!"); } } diff --git a/test/972-iface-super-multidex/src/Main.java b/test/972-iface-super-multidex/src/Main.java index 3fb3f45428..dea5f1db68 100644 --- a/test/972-iface-super-multidex/src/Main.java +++ b/test/972-iface-super-multidex/src/Main.java @@ -22,7 +22,7 @@ public class Main { c = Class.forName("ConcreteClass"); } catch (Exception e) { System.out.println("Could not load class"); - e.printStackTrace(); + e.printStackTrace(System.out); return; } try { @@ -30,7 +30,7 @@ public class Main { System.out.println((String)m.invoke(c.newInstance(), new Object[0])); } catch (Exception e) { System.out.println("Unknown exception occurred"); - e.printStackTrace(); + e.printStackTrace(System.out); } try { Method m = c.getMethod("runConflict"); @@ -41,15 +41,15 @@ public class Main { } } catch (AbstractMethodError e) { System.out.println("Unexpected AME caught"); - e.printStackTrace(); + e.printStackTrace(System.out); } catch (NoSuchMethodError e) { System.out.println("Unexpected NSME caught"); - e.printStackTrace(); + e.printStackTrace(System.out); } catch (IncompatibleClassChangeError e) { System.out.println("Expected ICCE caught"); } catch (Throwable e) { System.out.println("Unknown exception caught!"); - e.printStackTrace(); + e.printStackTrace(System.out); } } } diff --git a/test/973-default-multidex/src/Main.java b/test/973-default-multidex/src/Main.java index b93265a5b8..c7dd6dc9a3 100644 --- a/test/973-default-multidex/src/Main.java +++ b/test/973-default-multidex/src/Main.java @@ -23,7 +23,7 @@ public class Main { Method m = c.getMethod("callMethod"); System.out.println(m.invoke(c.newInstance(), new Object[0])); } catch (Exception e) { - e.printStackTrace(); + e.printStackTrace(System.out); System.out.println("FAILED: Could not call method"); return; } diff --git a/test/983-source-transform-verify/source_transform.cc b/test/983-source-transform-verify/source_transform.cc index 3ef3c7cb45..a433dc9b75 100644 --- a/test/983-source-transform-verify/source_transform.cc +++ b/test/983-source-transform-verify/source_transform.cc @@ -34,7 +34,7 @@ #include "jvmti.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" +#include "thread-current-inl.h" #include "thread_list.h" // Test infrastructure diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc index d2cfbffc30..7ac019e5d3 100644 --- a/test/common/runtime_state.cc +++ b/test/common/runtime_state.cc @@ -29,7 +29,7 @@ #include "runtime.h" #include "scoped_thread_state_change-inl.h" #include "ScopedUtfChars.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/test/common/stack_inspect.cc b/test/common/stack_inspect.cc index ceb4ba241b..80a278012d 100644 --- a/test/common/stack_inspect.cc +++ b/test/common/stack_inspect.cc @@ -25,7 +25,7 @@ #include "runtime.h" #include "scoped_thread_state_change-inl.h" #include "stack.h" -#include "thread-inl.h" +#include "thread-current-inl.h" namespace art { diff --git a/tools/add_package_property.sh b/tools/add_package_property.sh new file mode 100644 index 0000000000..e9294a9ed2 --- /dev/null +++ b/tools/add_package_property.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# +# Copyright (C) 2017 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. +# +# Sets the property of an Android package + +if [ "$#" -ne 2 ] ; then + echo "USAGE: sh add_package_property.sh [PACKAGE_NAME] [PROPERTY_SCRIPT_PATH]" + exit 1 +fi +PACKAGE_NAME=$1 +PROPERTY_SCRIPT_PATH=$2 +PROPERTY_SCRIPT_NAME=`basename $PROPERTY_SCRIPT_PATH` +adb push $PROPERTY_SCRIPT_PATH /data/data/$PACKAGE_NAME/ +adb shell chmod o+x /data/data/$PACKAGE_NAME/$PROPERTY_SCRIPT_NAME +adb shell restorecon /data/data/$PACKAGE_NAME/$PROPERTY_SCRIPT_NAME +adb shell setprop wrap.$PACKAGE_NAME /data/data/$PACKAGE_NAME/$PROPERTY_SCRIPT_NAME diff --git a/tools/asan.sh b/tools/asan.sh new file mode 100644 index 0000000000..b74954510f --- /dev/null +++ b/tools/asan.sh @@ -0,0 +1,21 @@ +#!/system/bin/sh +# +# Copyright (C) 2017 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. +# +# NOTE: This script is used by add_package_property.sh and not meant to be executed directly +# +# This script contains the property and the options required to log poisoned +# memory accesses (found in logcat) +ASAN_OPTIONS=halt_on_error=0:verbosity=0:print_legend=0:print_full_thread_history=0:print_stats=0:print_summary=0:suppress_equal_pcs=0:fast_unwind_on_fatal=1 asanwrapper $@ |