diff options
37 files changed, 253 insertions, 340 deletions
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc index d603d9673c..586891a3ff 100644 --- a/compiler/common_compiler_test.cc +++ b/compiler/common_compiler_test.cc @@ -108,7 +108,7 @@ void CommonCompilerTest::MakeExecutable(const void* code_start, size_t code_leng int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC); CHECK_EQ(result, 0); - FlushInstructionCache(reinterpret_cast<char*>(base), reinterpret_cast<char*>(base + len)); + FlushInstructionCache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len)); } void CommonCompilerTest::MakeExecutable(ObjPtr<mirror::ClassLoader> class_loader, diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index f6afe2c958..95d08b3c64 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -2564,8 +2564,8 @@ static void CompileDexFile(CompilerDriver* driver, thread_pool); auto compile = [&context, &compile_fn](size_t class_def_index) { - ScopedTrace trace(__FUNCTION__); const DexFile& dex_file = *context.GetDexFile(); + SCOPED_TRACE << "compile " << dex_file.GetLocation() << "@" << class_def_index; ClassLinker* class_linker = context.GetClassLinker(); jobject jclass_loader = context.GetClassLoader(); ClassReference ref(&dex_file, class_def_index); diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 2757f7b719..bb96c211cb 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -2146,22 +2146,6 @@ void InstructionSimplifierVisitor::SimplifyStringEquals(HInvoke* instruction) { ReferenceTypeInfo argument_rti = argument->GetReferenceTypeInfo(); if (argument_rti.IsValid() && argument_rti.IsStringClass()) { optimizations.SetArgumentIsString(); - } else if (kUseReadBarrier) { - DCHECK(instruction->GetResolvedMethod() != nullptr); - DCHECK(instruction->GetResolvedMethod()->GetDeclaringClass()->IsStringClass() || - // Object.equals() can be devirtualized to String.equals(). - instruction->GetResolvedMethod()->GetDeclaringClass()->IsObjectClass()); - Runtime* runtime = Runtime::Current(); - // For AOT, we always assume that the boot image shall contain the String.class and - // we do not need a read barrier for boot image classes as they are non-moveable. - // For JIT, check if we actually have a boot image; if we do, the String.class - // should also be non-moveable. - if (runtime->IsAotCompiler() || runtime->GetHeap()->HasBootImageSpace()) { - DCHECK(runtime->IsAotCompiler() || - !runtime->GetHeap()->IsMovableObject( - instruction->GetResolvedMethod()->GetDeclaringClass())); - optimizations.SetNoReadBarrierForStringClass(); - } } } } diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index 06e2fbb355..2d93f234be 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -219,7 +219,6 @@ class StringEqualsOptimizations : public IntrinsicOptimizations { INTRINSIC_OPTIMIZATION(ArgumentNotNull, 0); INTRINSIC_OPTIMIZATION(ArgumentIsString, 1); - INTRINSIC_OPTIMIZATION(NoReadBarrierForStringClass, 2); private: DISALLOW_COPY_AND_ASSIGN(StringEqualsOptimizations); diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 1abfcb022b..7684dc79f2 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -1398,13 +1398,6 @@ static const char* GetConstString(HInstruction* candidate, uint32_t* utf16_lengt } void IntrinsicLocationsBuilderARM64::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc index 1127fb8191..bc59fcf50c 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.cc +++ b/compiler/optimizing/intrinsics_arm_vixl.cc @@ -1458,13 +1458,6 @@ static const char* GetConstString(HInstruction* candidate, uint32_t* utf16_lengt } void IntrinsicLocationsBuilderARMVIXL::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); InvokeRuntimeCallingConventionARMVIXL calling_convention; diff --git a/compiler/optimizing/intrinsics_mips.cc b/compiler/optimizing/intrinsics_mips.cc index 771714bf41..6f7f5e49c1 100644 --- a/compiler/optimizing/intrinsics_mips.cc +++ b/compiler/optimizing/intrinsics_mips.cc @@ -1516,13 +1516,6 @@ void IntrinsicCodeGeneratorMIPS::VisitStringCompareTo(HInvoke* invoke) { // boolean java.lang.String.equals(Object anObject) void IntrinsicLocationsBuilderMIPS::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); diff --git a/compiler/optimizing/intrinsics_mips64.cc b/compiler/optimizing/intrinsics_mips64.cc index 4a1bd5b7b2..2eb252908c 100644 --- a/compiler/optimizing/intrinsics_mips64.cc +++ b/compiler/optimizing/intrinsics_mips64.cc @@ -1369,13 +1369,6 @@ void IntrinsicCodeGeneratorMIPS64::VisitStringCompareTo(HInvoke* invoke) { // boolean java.lang.String.equals(Object anObject) void IntrinsicLocationsBuilderMIPS64::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index d33c0c344e..3504d7a6f8 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -922,13 +922,6 @@ void IntrinsicCodeGeneratorX86::VisitStringCompareTo(HInvoke* invoke) { } void IntrinsicLocationsBuilderX86::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index ae889744ad..96f6eaaf33 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -1230,13 +1230,6 @@ void IntrinsicCodeGeneratorX86_64::VisitStringCompareTo(HInvoke* invoke) { } void IntrinsicLocationsBuilderX86_64::VisitStringEquals(HInvoke* invoke) { - if (kEmitCompilerReadBarrier && - !StringEqualsOptimizations(invoke).GetArgumentIsString() && - !StringEqualsOptimizations(invoke).GetNoReadBarrierForStringClass()) { - // No support for this odd case (String class is moveable, not in the boot image). - return; - } - LocationSummary* locations = new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified); locations->SetInAt(0, Location::RequiresRegister()); diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h index 178a4d4df1..598f7df778 100644 --- a/dexlayout/dex_ir.h +++ b/dexlayout/dex_ir.h @@ -215,7 +215,7 @@ class CollectionBase { uint32_t GetOffset() const { return offset_; } void SetOffset(uint32_t new_offset) { offset_ = new_offset; } - virtual uint32_t Size() const { return 0U; } + virtual uint32_t Size() const = 0; private: // Start out unassigned. diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc index ca6ff9e514..947d3d5297 100644 --- a/dexlayout/dex_ir_builder.cc +++ b/dexlayout/dex_ir_builder.cc @@ -115,6 +115,8 @@ template<class T> class CollectionMap : public CollectionBase { return it != collection_.end() ? it->second : nullptr; } + uint32_t Size() const override { return size(); } + // Lower case for template interop with std::map. uint32_t size() const { return collection_.size(); } std::map<uint32_t, T*>& Collection() { return collection_; } diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc index ebc18fc5ff..6ecf90151d 100644 --- a/imgdiag/imgdiag.cc +++ b/imgdiag/imgdiag.cc @@ -26,6 +26,7 @@ #include <unordered_set> #include <vector> +#include <android-base/parseint.h> #include "android-base/stringprintf.h" #include "art_field-inl.h" @@ -1682,14 +1683,14 @@ struct ImgDiagArgs : public CmdlineArgs { if (option.starts_with("--image-diff-pid=")) { const char* image_diff_pid = option.substr(strlen("--image-diff-pid=")).data(); - if (!ParseInt(image_diff_pid, &image_diff_pid_)) { + if (!android::base::ParseInt(image_diff_pid, &image_diff_pid_)) { *error_msg = "Image diff pid out of range"; return kParseError; } } else if (option.starts_with("--zygote-diff-pid=")) { const char* zygote_diff_pid = option.substr(strlen("--zygote-diff-pid=")).data(); - if (!ParseInt(zygote_diff_pid, &zygote_diff_pid_)) { + if (!android::base::ParseInt(zygote_diff_pid, &zygote_diff_pid_)) { *error_msg = "Zygote diff pid out of range"; return kParseError; } diff --git a/libartbase/base/utils.cc b/libartbase/base/utils.cc index 761c6113d6..74cc5b97b2 100644 --- a/libartbase/base/utils.cc +++ b/libartbase/base/utils.cc @@ -38,6 +38,12 @@ #include "AvailabilityMacros.h" // For MAC_OS_X_VERSION_MAX_ALLOWED #endif +#if defined(__BIONIC__) +// membarrier(2) is only supported for target builds (b/111199492). +#include <linux/membarrier.h> +#include <sys/syscall.h> +#endif + #if defined(__linux__) #include <linux/unistd.h> #endif @@ -207,4 +213,42 @@ void SleepForever() { } } +bool FlushInstructionPipeline() { + // membarrier(2) is only supported for target builds (b/111199492). +#if defined(__BIONIC__) + static constexpr int kSyncCoreMask = + MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE | + MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE; + static bool have_probed = false; + static bool have_sync_core = false; + + if (UNLIKELY(!have_probed)) { + // Probe membarrier(2) commands supported by kernel. + int commands = syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0); + if (commands >= 0) { + have_sync_core = (commands & kSyncCoreMask) == kSyncCoreMask; + if (have_sync_core) { + // Register with kernel that we'll be using the private expedited sync core command. + CheckedCall(syscall, + "membarrier register sync core", + __NR_membarrier, + MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE, + 0); + } + } + have_probed = true; + } + + if (have_sync_core) { + CheckedCall(syscall, + "membarrier sync core", + __NR_membarrier, + MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE, + 0); + return true; + } +#endif // defined(__BIONIC__) + return false; +} + } // namespace art diff --git a/libartbase/base/utils.h b/libartbase/base/utils.h index ba61e1b0a3..d85960d811 100644 --- a/libartbase/base/utils.h +++ b/libartbase/base/utils.h @@ -24,6 +24,7 @@ #include <string> #include <android-base/logging.h> +#include <android-base/parseint.h> #include "casts.h" #include "enums.h" @@ -33,34 +34,6 @@ namespace art { -template <typename T> -bool ParseUint(const char *in, T* out) { - char* end; - unsigned long long int result = strtoull(in, &end, 0); // NOLINT(runtime/int) - if (in == end || *end != '\0') { - return false; - } - if (std::numeric_limits<T>::max() < result) { - return false; - } - *out = static_cast<T>(result); - return true; -} - -template <typename T> -bool ParseInt(const char* in, T* out) { - char* end; - long long int result = strtoll(in, &end, 0); // NOLINT(runtime/int) - if (in == end || *end != '\0') { - return false; - } - if (result < std::numeric_limits<T>::min() || std::numeric_limits<T>::max() < result) { - return false; - } - *out = static_cast<T>(result); - return true; -} - static inline uint32_t PointerToLowMemUInt32(const void* p) { uintptr_t intp = reinterpret_cast<uintptr_t>(p); DCHECK_LE(intp, 0xFFFFFFFFU); @@ -130,7 +103,7 @@ static void ParseIntOption(const StringPiece& option, DCHECK(option.starts_with(option_prefix)) << option << " " << option_prefix; const char* value_string = option.substr(option_prefix.size()).data(); int64_t parsed_integer_value = 0; - if (!ParseInt(value_string, &parsed_integer_value)) { + if (!android::base::ParseInt(value_string, &parsed_integer_value)) { usage("Failed to parse %s '%s' as an integer", option_name.c_str(), value_string); } *out = dchecked_integral_cast<T>(parsed_integer_value); @@ -179,16 +152,19 @@ static T GetRandomNumber(T min, T max) { // Sleep forever and never come back. NO_RETURN void SleepForever(); -inline void FlushInstructionCache(char* begin, char* end) { - __builtin___clear_cache(begin, end); +inline void FlushDataCache(void* begin, void* end) { + __builtin___clear_cache(reinterpret_cast<char*>(begin), reinterpret_cast<char*>(end)); } -inline void FlushDataCache(char* begin, char* end) { +inline void FlushInstructionCache(void* begin, void* end) { // Same as FlushInstructionCache for lack of other builtin. __builtin___clear_cache // flushes both caches. - __builtin___clear_cache(begin, end); + __builtin___clear_cache(reinterpret_cast<char*>(begin), reinterpret_cast<char*>(end)); } +// Flush instruction pipeline. Returns true on success, false if feature is unsupported. +bool FlushInstructionPipeline(); + template <typename T> constexpr PointerSize ConvertToPointerSize(T any) { if (any == 4 || any == 8) { diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index fc7f5b7666..ac9ece785a 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -28,6 +28,7 @@ #include <vector> #include "android-base/logging.h" +#include "android-base/parseint.h" #include "android-base/stringprintf.h" #include "android-base/strings.h" @@ -3380,7 +3381,7 @@ struct OatdumpArgs : public CmdlineArgs { } else if (option.starts_with("--export-dex-to=")) { export_dex_location_ = option.substr(strlen("--export-dex-to=")).data(); } else if (option.starts_with("--addr2instr=")) { - if (!ParseUint(option.substr(strlen("--addr2instr=")).data(), &addr2instr_)) { + if (!android::base::ParseUint(option.substr(strlen("--addr2instr=")).data(), &addr2instr_)) { *error_msg = "Address conversion failed"; return kParseError; } diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index aaa3e8339f..5d38e8bfed 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -26,6 +26,7 @@ #include <vector> #include "android-base/file.h" +#include <android-base/parseint.h> #include "android-base/stringprintf.h" #include "android-base/strings.h" @@ -630,7 +631,7 @@ bool PatchOat::Patch(const std::string& image_location, std::string image_relocation_filename = output_image_relocation_directory + (android::base::StartsWith(original_image_filename, "/") ? "" : "/") - + original_image_filename.substr(original_image_filename.find_last_of("/")); + + original_image_filename.substr(original_image_filename.find_last_of('/')); int64_t input_image_size = input_image->GetLength(); if (input_image_size < 0) { LOG(ERROR) << "Error while getting input image size"; @@ -1272,7 +1273,7 @@ static int patchoat(int argc, char **argv) { } else if (option.starts_with("--base-offset-delta=")) { const char* base_delta_str = option.substr(strlen("--base-offset-delta=")).data(); base_delta_set = true; - if (!ParseInt(base_delta_str, &base_delta)) { + if (!android::base::ParseInt(base_delta_str, &base_delta)) { Usage("Failed to parse --base-offset-delta argument '%s' as an off_t", base_delta_str); } } else if (option == "--dump-timings") { diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h index f693524a6c..9b69166567 100644 --- a/runtime/art_method-inl.h +++ b/runtime/art_method-inl.h @@ -417,7 +417,6 @@ inline HiddenApiAccessFlags::ApiList ArtMethod::GetHiddenApiAccessFlags() case Intrinsics::kMemoryPokeIntNative: case Intrinsics::kMemoryPokeLongNative: case Intrinsics::kMemoryPokeShortNative: - return HiddenApiAccessFlags::kDarkGreylist; case Intrinsics::kVarHandleFullFence: case Intrinsics::kVarHandleAcquireFence: case Intrinsics::kVarHandleReleaseFence: diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index e19dedcebd..511d468412 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -483,9 +483,17 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b mirror::ObjectArray<mirror::Object>::ClassSize(image_pointer_size_)))); object_array_class->SetComponentType(java_lang_Object.Get()); - // Setup String. + // Setup java.lang.String. + // + // We make this class non-movable for the unlikely case where it were to be + // moved by a sticky-bit (minor) collection when using the Generational + // Concurrent Copying (CC) collector, potentially creating a stale reference + // in the `klass_` field of one of its instances allocated in the Large-Object + // Space (LOS) -- see the comment about the dirty card scanning logic in + // art::gc::collector::ConcurrentCopying::MarkingPhase. Handle<mirror::Class> java_lang_String(hs.NewHandle( - AllocClass(self, java_lang_Class.Get(), mirror::String::ClassSize(image_pointer_size_)))); + AllocClass</* kMovable */ false>( + self, java_lang_Class.Get(), mirror::String::ClassSize(image_pointer_size_)))); java_lang_String->SetStringClass(); mirror::Class::SetStatus(java_lang_String, ClassStatus::kResolved, self); @@ -528,13 +536,13 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b // Create int array type for native pointer arrays (for example vtables) on 32-bit archs. Handle<mirror::Class> int_array_class(hs.NewHandle( - AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_)))); + AllocPrimitiveArrayClass(self, java_lang_Class.Get()))); int_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveInt, this)); SetClassRoot(ClassRoot::kIntArrayClass, int_array_class.Get()); // Create long array type for native pointer arrays (for example vtables) on 64-bit archs. Handle<mirror::Class> long_array_class(hs.NewHandle( - AllocClass(self, java_lang_Class.Get(), mirror::Array::ClassSize(image_pointer_size_)))); + AllocPrimitiveArrayClass(self, java_lang_Class.Get()))); long_array_class->SetComponentType(GetClassRoot(ClassRoot::kPrimitiveLong, this)); SetClassRoot(ClassRoot::kLongArrayClass, long_array_class.Get()); @@ -610,20 +618,29 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b CHECK_EQ(dalvik_system_ClassExt->GetObjectSize(), mirror::ClassExt::InstanceSize()); // Setup the primitive array type classes - can't be done until Object has a vtable. - SetClassRoot(ClassRoot::kBooleanArrayClass, FindSystemClass(self, "[Z")); + AllocAndSetPrimitiveArrayClassRoot(self, + java_lang_Class.Get(), + ClassRoot::kBooleanArrayClass, + ClassRoot::kPrimitiveBoolean, + "[Z"); - SetClassRoot(ClassRoot::kByteArrayClass, FindSystemClass(self, "[B")); + AllocAndSetPrimitiveArrayClassRoot( + self, java_lang_Class.Get(), ClassRoot::kByteArrayClass, ClassRoot::kPrimitiveByte, "[B"); - SetClassRoot(ClassRoot::kCharArrayClass, FindSystemClass(self, "[C")); + AllocAndSetPrimitiveArrayClassRoot( + self, java_lang_Class.Get(), ClassRoot::kCharArrayClass, ClassRoot::kPrimitiveChar, "[C"); - SetClassRoot(ClassRoot::kShortArrayClass, FindSystemClass(self, "[S")); + AllocAndSetPrimitiveArrayClassRoot( + self, java_lang_Class.Get(), ClassRoot::kShortArrayClass, ClassRoot::kPrimitiveShort, "[S"); CheckSystemClass(self, int_array_class, "[I"); CheckSystemClass(self, long_array_class, "[J"); - SetClassRoot(ClassRoot::kFloatArrayClass, FindSystemClass(self, "[F")); + AllocAndSetPrimitiveArrayClassRoot( + self, java_lang_Class.Get(), ClassRoot::kFloatArrayClass, ClassRoot::kPrimitiveFloat, "[F"); - SetClassRoot(ClassRoot::kDoubleArrayClass, FindSystemClass(self, "[D")); + AllocAndSetPrimitiveArrayClassRoot( + self, java_lang_Class.Get(), ClassRoot::kDoubleArrayClass, ClassRoot::kPrimitiveDouble, "[D"); // Run Class through FindSystemClass. This initializes the dex_cache_ fields and register it // in class_table_. @@ -2165,13 +2182,14 @@ ObjPtr<mirror::DexCache> ClassLinker::AllocAndInitializeDexCache(Thread* self, return dex_cache; } +template <bool kMovable> ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self, ObjPtr<mirror::Class> java_lang_Class, uint32_t class_size) { DCHECK_GE(class_size, sizeof(mirror::Class)); gc::Heap* heap = Runtime::Current()->GetHeap(); mirror::Class::InitializeClassVisitor visitor(class_size); - ObjPtr<mirror::Object> k = kMovingClasses ? + ObjPtr<mirror::Object> k = (kMovingClasses && kMovable) ? heap->AllocObject<true>(self, java_lang_Class, class_size, visitor) : heap->AllocNonMovableObject<true>(self, java_lang_Class, class_size, visitor); if (UNLIKELY(k == nullptr)) { @@ -2185,6 +2203,18 @@ ObjPtr<mirror::Class> ClassLinker::AllocClass(Thread* self, uint32_t class_size) return AllocClass(self, GetClassRoot<mirror::Class>(this), class_size); } +ObjPtr<mirror::Class> ClassLinker::AllocPrimitiveArrayClass(Thread* self, + ObjPtr<mirror::Class> java_lang_Class) { + // We make this class non-movable for the unlikely case where it were to be + // moved by a sticky-bit (minor) collection when using the Generational + // Concurrent Copying (CC) collector, potentially creating a stale reference + // in the `klass_` field of one of its instances allocated in the Large-Object + // Space (LOS) -- see the comment about the dirty card scanning logic in + // art::gc::collector::ConcurrentCopying::MarkingPhase. + return AllocClass</* kMovable */ false>( + self, java_lang_Class, mirror::Array::ClassSize(image_pointer_size_)); +} + ObjPtr<mirror::ObjectArray<mirror::StackTraceElement>> ClassLinker::AllocStackTraceElementArray( Thread* self, size_t length) { @@ -3648,10 +3678,22 @@ ObjPtr<mirror::Class> ClassLinker::CreateArrayClass(Thread* self, new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::Object>>(this)); } else if (strcmp(descriptor, "[Ljava/lang/String;") == 0) { new_class.Assign(GetClassRoot<mirror::ObjectArray<mirror::String>>(this)); + } else if (strcmp(descriptor, "[Z") == 0) { + new_class.Assign(GetClassRoot<mirror::BooleanArray>(this)); + } else if (strcmp(descriptor, "[B") == 0) { + new_class.Assign(GetClassRoot<mirror::ByteArray>(this)); + } else if (strcmp(descriptor, "[C") == 0) { + new_class.Assign(GetClassRoot<mirror::CharArray>(this)); + } else if (strcmp(descriptor, "[S") == 0) { + new_class.Assign(GetClassRoot<mirror::ShortArray>(this)); } else if (strcmp(descriptor, "[I") == 0) { new_class.Assign(GetClassRoot<mirror::IntArray>(this)); } else if (strcmp(descriptor, "[J") == 0) { new_class.Assign(GetClassRoot<mirror::LongArray>(this)); + } else if (strcmp(descriptor, "[F") == 0) { + new_class.Assign(GetClassRoot<mirror::FloatArray>(this)); + } else if (strcmp(descriptor, "[D") == 0) { + new_class.Assign(GetClassRoot<mirror::DoubleArray>(this)); } } if (new_class == nullptr) { @@ -8607,6 +8649,19 @@ void ClassLinker::SetClassRoot(ClassRoot class_root, ObjPtr<mirror::Class> klass class_roots->Set<false>(index, klass); } +void ClassLinker::AllocAndSetPrimitiveArrayClassRoot(Thread* self, + ObjPtr<mirror::Class> java_lang_Class, + ClassRoot primitive_array_class_root, + ClassRoot primitive_class_root, + const char* descriptor) { + StackHandleScope<1> hs(self); + Handle<mirror::Class> primitive_array_class(hs.NewHandle( + AllocPrimitiveArrayClass(self, java_lang_Class))); + primitive_array_class->SetComponentType(GetClassRoot(primitive_class_root, this)); + SetClassRoot(primitive_array_class_root, primitive_array_class.Get()); + CheckSystemClass(self, primitive_array_class, descriptor); +} + jobject ClassLinker::CreateWellKnownClassLoader(Thread* self, const std::vector<const DexFile*>& dex_files, jclass loader_class, @@ -8941,7 +8996,7 @@ ObjPtr<mirror::IfTable> ClassLinker::AllocIfTable(Thread* self, size_t ifcount) ifcount * mirror::IfTable::kMax))); } -// Instantiate ResolveMethod. +// Instantiate ClassLinker::ResolveMethod. template ArtMethod* ClassLinker::ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>( uint32_t method_idx, Handle<mirror::DexCache> dex_cache, @@ -8955,4 +9010,14 @@ template ArtMethod* ClassLinker::ResolveMethod<ClassLinker::ResolveMode::kNoChec ArtMethod* referrer, InvokeType type); +// Instantiate ClassLinker::AllocClass. +template ObjPtr<mirror::Class> ClassLinker::AllocClass</* kMovable */ true>( + Thread* self, + ObjPtr<mirror::Class> java_lang_Class, + uint32_t class_size); +template ObjPtr<mirror::Class> ClassLinker::AllocClass</* kMovable */ false>( + Thread* self, + ObjPtr<mirror::Class> java_lang_Class, + uint32_t class_size); + } // namespace art diff --git a/runtime/class_linker.h b/runtime/class_linker.h index e4d9c96696..efe29d3127 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -775,7 +775,11 @@ class ClassLinker { REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_); - // For early bootstrapping by Init + // For early bootstrapping by Init. + // If we do not allow moving classes (`art::kMovingClass` is false) or if + // parameter `kMovable` is false (or both), the class object is allocated in + // the non-moving space. + template <bool kMovable = true> ObjPtr<mirror::Class> AllocClass(Thread* self, ObjPtr<mirror::Class> java_lang_Class, uint32_t class_size) @@ -789,6 +793,12 @@ class ClassLinker { REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_); + // Allocate a primitive array class. + ObjPtr<mirror::Class> AllocPrimitiveArrayClass(Thread* self, + ObjPtr<mirror::Class> java_lang_Class) + REQUIRES_SHARED(Locks::mutator_lock_) + REQUIRES(!Roles::uninterruptible_); + ObjPtr<mirror::DexCache> AllocDexCache(/*out*/ ObjPtr<mirror::String>* out_location, Thread* self, const DexFile& dex_file) @@ -1206,6 +1216,20 @@ class ClassLinker { void SetClassRoot(ClassRoot class_root, ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); + // Allocate primitive array class for primitive with class root + // `primitive_class_root`, and associate it to class root + // `primitive_array_class_root`. + // + // Also check this class returned when searching system classes for + // `descriptor` matches the allocated class. + void AllocAndSetPrimitiveArrayClassRoot(Thread* self, + ObjPtr<mirror::Class> java_lang_Class, + ClassRoot primitive_array_class_root, + ClassRoot primitive_class_root, + const char* descriptor) + REQUIRES_SHARED(Locks::mutator_lock_) + REQUIRES(!Roles::uninterruptible_); + // Return the quick generic JNI stub for testing. const void* GetRuntimeQuickGenericJniStub() const; diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc index 2bd541118b..f6b764ddc0 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -16,6 +16,8 @@ #include "class_loader_context.h" +#include <android-base/parseint.h> + #include "art_field-inl.h" #include "base/dchecked_vector.h" #include "base/stl_util.h" @@ -120,7 +122,7 @@ bool ClassLoaderContext::ParseClassLoaderSpec(const std::string& class_loader_sp return false; } uint32_t checksum = 0; - if (!ParseInt(dex_file_with_checksum[1].c_str(), &checksum)) { + if (!android::base::ParseInt(dex_file_with_checksum[1].c_str(), &checksum)) { return false; } class_loader_chain_.back().classpath.push_back(dex_file_with_checksum[0]); diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc index 0c187675ba..eede5a56c0 100644 --- a/runtime/gc/collector/concurrent_copying.cc +++ b/runtime/gc/collector/concurrent_copying.cc @@ -905,13 +905,8 @@ void ConcurrentCopying::MarkingPhase() { // during a minor (young-generation) collection: // - In the case where we run with a boot image, these classes are part of the image space, // which is an immune space. - // - In the case where we run without a boot image, these classes are allocated in the region - // space (main space), but they are not expected to move during a minor collection (this - // would only happen if those classes were allocated between a major and a minor - // collections, which is unlikely -- we don't expect any GC to happen before these - // fundamental classes are initialized). Note that these classes could move during a major - // collection though, but this is fine: in that case, the whole heap is traced and the card - // table logic below is not used. + // - In the case where we run without a boot image, these classes are allocated in the + // non-moving space (see art::ClassLinker::InitWithoutImage). Runtime::Current()->GetHeap()->GetCardTable()->Scan<false>( space->GetMarkBitmap(), space->Begin(), diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 589e9a4826..e76d35d0f9 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -450,6 +450,7 @@ Heap::Heap(size_t initial_size, // Non moving space is always dlmalloc since we currently don't have support for multiple // active rosalloc spaces. const size_t size = non_moving_space_mem_map.Size(); + const void* non_moving_space_mem_map_begin = non_moving_space_mem_map.Begin(); non_moving_space_ = space::DlMallocSpace::CreateFromMemMap(std::move(non_moving_space_mem_map), "zygote / non moving space", kDefaultStartingSize, @@ -457,9 +458,9 @@ Heap::Heap(size_t initial_size, size, size, /* can_move_objects */ false); - non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity()); CHECK(non_moving_space_ != nullptr) << "Failed creating non moving space " - << non_moving_space_mem_map.Begin(); + << non_moving_space_mem_map_begin; + non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity()); AddSpace(non_moving_space_); } // Create other spaces based on whether or not we have a moving GC. diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc index 2b2898c195..184aba815d 100644 --- a/runtime/jit/jit_code_cache.cc +++ b/runtime/jit/jit_code_cache.cc @@ -28,6 +28,7 @@ #include "base/stl_util.h" #include "base/systrace.h" #include "base/time_utils.h" +#include "base/utils.h" #include "cha.h" #include "debugger_interface.h" #include "dex/dex_file_loader.h" @@ -53,8 +54,9 @@ namespace art { namespace jit { -static constexpr int kProtData = PROT_READ | PROT_WRITE; static constexpr int kProtCode = PROT_READ | PROT_EXEC; +static constexpr int kProtData = PROT_READ | PROT_WRITE; +static constexpr int kProtProfile = PROT_READ; static constexpr size_t kCodeSizeLogThreshold = 50 * KB; static constexpr size_t kStackMapSizeLogThreshold = 50 * KB; @@ -192,7 +194,7 @@ JitCodeCache* JitCodeCache::Create(size_t initial_capacity, // to profile system server. // NOTE 2: We could just not create the code section at all but we will need to // special case too many cases. - int memmap_flags_prot_code = used_only_for_profile_data ? (kProtCode & ~PROT_EXEC) : kProtCode; + int memmap_flags_prot_code = used_only_for_profile_data ? kProtProfile : kProtCode; std::string error_str; // Map name specific for android_os_Debug.cpp accounting. @@ -799,8 +801,18 @@ uint8_t* JitCodeCache::CommitCodeInternal(Thread* self, // // For reference, this behavior is caused by this commit: // https://android.googlesource.com/kernel/msm/+/3fbe6bc28a6b9939d0650f2f17eb5216c719950c - FlushInstructionCache(reinterpret_cast<char*>(code_ptr), - reinterpret_cast<char*>(code_ptr + code_size)); + FlushInstructionCache(code_ptr, code_ptr + code_size); + + // Ensure CPU instruction pipelines are flushed for all cores. This is necessary for + // correctness as code may still be in instruction pipelines despite the i-cache flush. It is + // not safe to assume that changing permissions with mprotect (RX->RWX->RX) will cause a TLB + // shootdown (incidentally invalidating the CPU pipelines by sending an IPI to all cores to + // notify them of the TLB invalidation). Some architectures, notably ARM and ARM64, have + // hardware support that broadcasts TLB invalidations and so their kernels have no software + // based TLB shootdown. FlushInstructionPipeline() is a wrapper around the Linux + // membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED) syscall which does the appropriate flushing. + FlushInstructionPipeline(); + DCHECK(!Runtime::Current()->IsAotCompiler()); if (has_should_deoptimize_flag) { method_header->SetHasShouldDeoptimizeFlag(); @@ -858,8 +870,7 @@ uint8_t* JitCodeCache::CommitCodeInternal(Thread* self, FillRootTable(roots_data, roots); { // Flush data cache, as compiled code references literals in it. - FlushDataCache(reinterpret_cast<char*>(roots_data), - reinterpret_cast<char*>(roots_data + data_size)); + FlushDataCache(roots_data, roots_data + data_size); } method_code_map_.Put(code_ptr, method); if (osr) { diff --git a/test/004-StackWalk/build b/test/004-StackWalk/build index eeecbfcc40..3de541c75d 100644 --- a/test/004-StackWalk/build +++ b/test/004-StackWalk/build @@ -18,10 +18,8 @@ set -e # This test depends on the exact format of the DEX file. Since dx is deprecated, -# the classes.dex file is packaged as a test input. It was created with: -# -# $ javac -g -Xlint:-options -source 1.7 -target 1.7 -d classes src/Main.java -# $ dx --debug --dex --output=classes.dex classes +# the classes.dex file is packaged as a test input. See src/Main.java file +# to check how it was created. # Wrapper function for javac which for this test does nothing as the # test uses a pre-built DEX file. diff --git a/test/004-StackWalk/classes.dex b/test/004-StackWalk/classes.dex Binary files differindex ad452960c3..61a7277cf9 100644 --- a/test/004-StackWalk/classes.dex +++ b/test/004-StackWalk/classes.dex diff --git a/test/004-StackWalk/src/Main.java b/test/004-StackWalk/src/Main.java index 072b1d0c4d..2a098f7686 100644 --- a/test/004-StackWalk/src/Main.java +++ b/test/004-StackWalk/src/Main.java @@ -1,19 +1,36 @@ +/* + * 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. + */ + +// This test depends on the exact format of the DEX file. Since dx is deprecated, +// the classes.dex file is packaged as a test input. It was created with: +// +// $ javac -g -Xlint:-options -source 1.7 -target 1.7 -d classes src/Main.java +// $ dx --debug --dex --output=classes.dex classes + public class Main { public Main() { } - boolean doThrow = false; - int $noinline$f() throws Exception { - g(1); - g(2); - - // This currently defeats inlining of `f`. - if (doThrow) { throw new Error(); } + $noinline$g(1); + $noinline$g(2); return 0; } - void g(int num_calls) { + void $noinline$g(int num_calls) { if (num_calls == 1) { System.out.println("1st call"); } else if (num_calls == 2) { @@ -81,11 +98,14 @@ public class Main { s4 = s18 = s19; s += s4; s += s18; - stackmap(0); - return s; + // Add a branch to workaround ART's large methods without branches heuristic. + if (testStackWalk(0) != 0) { + return s; + } + return s18; } - native int stackmap(int x); + native int testStackWalk(int x); public static void main(String[] args) throws Exception { System.loadLibrary(args[0]); diff --git a/test/004-StackWalk/stack_walk_jni.cc b/test/004-StackWalk/stack_walk_jni.cc index 89e2e660d9..53e0dae13d 100644 --- a/test/004-StackWalk/stack_walk_jni.cc +++ b/test/004-StackWalk/stack_walk_jni.cc @@ -20,7 +20,7 @@ namespace art { -#define CHECK_REGS(...) do { \ +#define CHECK_REGS_ARE_REFERENCES(...) do { \ int t[] = {__VA_ARGS__}; \ int t_size = sizeof(t) / sizeof(*t); \ CheckReferences(t, t_size, GetNativePcOffset()); \ @@ -43,58 +43,60 @@ class TestReferenceMapVisitor : public CheckReferenceMapVisitor { // Given the method name and the number of times the method has been called, // we know the Dex registers with live reference values. Assert that what we // find is what is expected. - if (m_name == "f") { + if (m_name == "$noinline$f") { if (gJava_StackWalk_refmap_calls == 1) { CHECK_EQ(1U, GetDexPc()); - CHECK_REGS(4); + CHECK_REGS_ARE_REFERENCES(1); } else { CHECK_EQ(gJava_StackWalk_refmap_calls, 2); CHECK_EQ(5U, GetDexPc()); - CHECK_REGS(4); + CHECK_REGS_ARE_REFERENCES(1); } - } else if (m_name == "g") { + found_f_ = true; + } else if (m_name == "$noinline$g") { if (gJava_StackWalk_refmap_calls == 1) { CHECK_EQ(0xcU, GetDexPc()); - CHECK_REGS(0, 2); // Note that v1 is not in the minimal root set + CHECK_REGS_ARE_REFERENCES(0, 2); // Note that v1 is not in the minimal root set } else { CHECK_EQ(gJava_StackWalk_refmap_calls, 2); CHECK_EQ(0xcU, GetDexPc()); - CHECK_REGS(0, 2); + CHECK_REGS_ARE_REFERENCES(0, 2); } + found_g_ = true; } else if (m_name == "shlemiel") { if (gJava_StackWalk_refmap_calls == 1) { CHECK_EQ(0x380U, GetDexPc()); - CHECK_REGS(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25); + CHECK_REGS_ARE_REFERENCES(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25); } else { CHECK_EQ(gJava_StackWalk_refmap_calls, 2); CHECK_EQ(0x380U, GetDexPc()); - CHECK_REGS(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25); + CHECK_REGS_ARE_REFERENCES(2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 25); } + found_shlemiel_ = true; } return true; } -}; -extern "C" JNIEXPORT jint JNICALL Java_Main_stackmap(JNIEnv*, jobject, jint count) { - ScopedObjectAccess soa(Thread::Current()); - CHECK_EQ(count, 0); - gJava_StackWalk_refmap_calls++; - - // Visitor - TestReferenceMapVisitor mapper(soa.Self()); - mapper.WalkStack(); + ~TestReferenceMapVisitor() { + } - return count + 1; -} + bool found_f_ = false; + bool found_g_ = false; + bool found_shlemiel_ = false; +}; -extern "C" JNIEXPORT jint JNICALL Java_Main_refmap2(JNIEnv*, jobject, jint count) { +extern "C" JNIEXPORT jint JNICALL Java_Main_testStackWalk(JNIEnv*, jobject, jint count) { ScopedObjectAccess soa(Thread::Current()); + CHECK_EQ(count, 0); gJava_StackWalk_refmap_calls++; // Visitor TestReferenceMapVisitor mapper(soa.Self()); mapper.WalkStack(); + CHECK(mapper.found_f_); + CHECK(mapper.found_g_); + CHECK(mapper.found_shlemiel_); return count + 1; } diff --git a/test/669-moveable-string-class-equals/expected.txt b/test/669-moveable-string-class-equals/expected.txt deleted file mode 100644 index 6a5618ebc6..0000000000 --- a/test/669-moveable-string-class-equals/expected.txt +++ /dev/null @@ -1 +0,0 @@ -JNI_OnLoad called diff --git a/test/669-moveable-string-class-equals/info.txt b/test/669-moveable-string-class-equals/info.txt deleted file mode 100644 index 1d3202ef46..0000000000 --- a/test/669-moveable-string-class-equals/info.txt +++ /dev/null @@ -1,2 +0,0 @@ -Regression test for String.equals() intrinsic instanceof check -when the String.class is moveable. diff --git a/test/669-moveable-string-class-equals/run b/test/669-moveable-string-class-equals/run deleted file mode 100755 index 7c74d8ca0e..0000000000 --- a/test/669-moveable-string-class-equals/run +++ /dev/null @@ -1,19 +0,0 @@ -#!/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. - -# Run without image, so that String.class is moveable. -# Reduce heap size to force more frequent GCs. -${RUN} --no-image --runtime-option -Xmx16m "$@" diff --git a/test/669-moveable-string-class-equals/src/Main.java b/test/669-moveable-string-class-equals/src/Main.java deleted file mode 100644 index d182d51a25..0000000000 --- a/test/669-moveable-string-class-equals/src/Main.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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. - */ - -public class Main { - public static void main(String[] args) { - System.loadLibrary(args[0]); - if (!hasJit()) { - // Make the test pass if not using JIT. - return; - } - if (hasImage()) { - throw new Error("The `run` script should prevent this test from running with an image!"); - } - if (!isClassMoveable(String.class)) { - throw new Error("String.class not moveable despite running without image!"); - } - - // Make sure the Main.test() is JIT-compiled and then call it. - ensureJitCompiled(Main.class, "test"); - test(); - } - - public static void test() { - int length = 5; - - // Hide the type of these strings in an Object array, - // so that we treat them as Object for the String.equals() below. - Object[] array = new Object[length]; - for (int i = 0; i != length; ++i) { - array[i] = "V" + i; - } - - // Continually check string equality between a newly allocated String and an - // already allocated String with the same contents while allocating over 128MiB - // memory (with heap size limited to 16MiB), ensuring we run GC and stress the - // instanceof check in the String.equals() implementation. - for (int count = 0; count != 128 * 1024; ++count) { - for (int i = 0; i != length; ++i) { - allocateAtLeast1KiB(); - assertTrue(("V" + i).equals(array[i])); - } - } - } - - public static void allocateAtLeast1KiB() { - // Give GC more work by allocating Object arrays. - memory[allocationIndex] = new Object[1024 / 4]; - ++allocationIndex; - if (allocationIndex == memory.length) { - allocationIndex = 0; - } - } - - public static void assertTrue(boolean value) { - if (!value) { - throw new Error("Assertion failed!"); - } - } - - private native static boolean hasJit(); - private native static boolean hasImage(); - private native static boolean isClassMoveable(Class<?> cls); - private static native void ensureJitCompiled(Class<?> itf, String method_name); - - // We shall retain some allocated memory and release old allocations - // so that the GC has something to do. - public static Object[] memory = new Object[4096]; - public static int allocationIndex = 0; -} diff --git a/test/StackWalk2/StackWalk2.java b/test/StackWalk2/StackWalk2.java deleted file mode 100644 index 5e7b22c252..0000000000 --- a/test/StackWalk2/StackWalk2.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -public class StackWalk2 { - // use v1 for this - - String str = new String(); // use v0 for str in <init> - - int f() { - g(1); // use v0 for 1, v1 for this - g(2); // use v0 for 2, v1 for this - strTest(); // use v1 for this - return 0; - } - - void g(int num_calls) throws RuntimeException { - if (num_calls == 1) { // use v0 for 1, v3 for num_calls - System.logI("1st call"); // use v0 for PrintStream, v1 for "1st call" - refmap2(24); // use v0 for 24, v2 for this - } else if (num_calls == 2) { // use v0 for 2, v3 for num_calls - System.logI("2nd call"); // use v0 for PrintStream, v1 for "2nd call" - refmap2(25); // use v0 for 24, v2 for this - } - throw new RuntimeException(); // use v0 for new RuntimeException - } - - void strTest() { - System.logI(str); // use v1 for PrintStream, v2, v3 for str - str = null; // use v1 for null, v3 for str - str = new String("ya"); // use v2 for "ya", v1 for new String - String s = str; // use v0, v1, v3 - System.logI(str); // use v1 for PrintStream, v2, v3 for str - System.logI(s); // use v1 for PrintStream, v0 for s - s = null; // use v0 - System.logI(s); // use v1 for PrintStream, v0 for s - } - - native int refmap2(int x); - - public static void main(String[] args) { - System.loadLibrary(args[0]); - StackWalk2 st = new StackWalk2(); - st.f(); - } -} diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc index da79164f12..c9b789e169 100644 --- a/test/common/runtime_state.cc +++ b/test/common/runtime_state.cc @@ -292,15 +292,6 @@ extern "C" JNIEXPORT void JNICALL Java_Main_fetchProfiles(JNIEnv*, jclass) { code_cache->GetProfiledMethods(unused_locations, unused_vector); } -extern "C" JNIEXPORT jboolean JNICALL Java_Main_isClassMoveable(JNIEnv*, - jclass, - jclass cls) { - Runtime* runtime = Runtime::Current(); - ScopedObjectAccess soa(Thread::Current()); - ObjPtr<mirror::Class> klass = soa.Decode<mirror::Class>(cls); - return runtime->GetHeap()->IsMovableObject(klass); -} - extern "C" JNIEXPORT void JNICALL Java_Main_waitForCompilation(JNIEnv*, jclass) { jit::Jit* jit = Runtime::Current()->GetJit(); if (jit != nullptr) { diff --git a/test/knownfailures.json b/test/knownfailures.json index 6004f25285..05c9aa9157 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -697,9 +697,9 @@ "description": ["Tests that depend on input-vdex are not supported with compact dex"] }, { - "tests": "661-oat-writer-layout", + "tests": ["661-oat-writer-layout", "004-StackWalk"], "variant": "interp-ac | interpreter | jit | no-prebuild | no-image | trace | redefine-stress | jvmti-stress", - "description": ["Test is designed to only check --compiler-filter=speed"] + "description": ["Tests are designed to only check --optimizing"] }, { "tests": "674-HelloWorld-Dm", diff --git a/tools/field-null-percent/fieldnull.cc b/tools/field-null-percent/fieldnull.cc index 86459d238b..1bd122a1b2 100644 --- a/tools/field-null-percent/fieldnull.cc +++ b/tools/field-null-percent/fieldnull.cc @@ -147,7 +147,7 @@ static void VMDeathCb(jvmtiEnv* jvmti, JNIEnv* env ATTRIBUTE_UNUSED) { delete list; } -static void CreateFieldList(jvmtiEnv* jvmti, JNIEnv* env, std::string args) { +static void CreateFieldList(jvmtiEnv* jvmti, JNIEnv* env, const std::string& args) { RequestList* list = nullptr; CHECK_JVMTI(jvmti->Allocate(sizeof(*list), reinterpret_cast<unsigned char**>(&list))); new (list) RequestList { .fields_ = GetRequestedFields(env, args), }; diff --git a/tools/libcore_gcstress_failures.txt b/tools/libcore_gcstress_failures.txt index 965e85c359..fff1c70ad8 100644 --- a/tools/libcore_gcstress_failures.txt +++ b/tools/libcore_gcstress_failures.txt @@ -29,6 +29,7 @@ modes: [device], names: ["libcore.java.lang.StringTest#testFastPathString_wellFormedUtf8Sequence", "org.apache.harmony.tests.java.lang.ref.ReferenceQueueTest#test_remove", + "org.apache.harmony.tests.java.text.DateFormatTest#test_getAvailableLocales", "org.apache.harmony.tests.java.util.TimerTest#testOverdueTaskExecutesImmediately", "org.apache.harmony.tests.java.util.WeakHashMapTest#test_keySet_hasNext", "libcore.java.text.DecimalFormatTest#testCurrencySymbolSpacing", |