diff options
author | Mathieu Chartier <mathieuc@google.com> | 2014-07-16 00:59:09 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2014-07-15 00:23:02 +0000 |
commit | ebaca192314e21d26b97646fa962e468ff07b893 (patch) | |
tree | 94fe46c84f790e195292461784656d54db946b1c | |
parent | 0e359ef64546e472ed7e2292c8a48354f9907a37 (diff) | |
parent | 4ee7a665e7f9cd2c5ace2d6304e33f64067b209f (diff) | |
download | art-ebaca192314e21d26b97646fa962e468ff07b893.zip art-ebaca192314e21d26b97646fa962e468ff07b893.tar.gz art-ebaca192314e21d26b97646fa962e468ff07b893.tar.bz2 |
Merge "Revert "Revert "Revert "Revert "Add intrinsic for Reference.get()"""""
-rw-r--r-- | compiler/dex/quick/dex_file_method_inliner.cc | 10 | ||||
-rw-r--r-- | compiler/dex/quick/dex_file_method_inliner.h | 3 | ||||
-rwxr-xr-x | compiler/dex/quick/gen_invoke.cc | 85 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 1 | ||||
-rw-r--r-- | runtime/Android.mk | 1 | ||||
-rw-r--r-- | runtime/class_linker.cc | 21 | ||||
-rw-r--r-- | runtime/gc/reference_processor-inl.h | 32 | ||||
-rw-r--r-- | runtime/gc/reference_processor.cc | 17 | ||||
-rw-r--r-- | runtime/gc/reference_processor.h | 9 | ||||
-rw-r--r-- | runtime/mirror/class-inl.h | 30 | ||||
-rw-r--r-- | runtime/mirror/class.h | 11 | ||||
-rw-r--r-- | runtime/mirror/object-inl.h | 4 | ||||
-rw-r--r-- | runtime/mirror/object.cc | 2 | ||||
-rw-r--r-- | runtime/mirror/reference-inl.h | 5 | ||||
-rw-r--r-- | runtime/mirror/reference.cc | 43 | ||||
-rw-r--r-- | runtime/mirror/reference.h | 24 | ||||
-rw-r--r-- | runtime/quick/inline_method_analyser.h | 1 | ||||
-rw-r--r-- | runtime/runtime.cc | 1 |
18 files changed, 282 insertions, 18 deletions
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc index 45dd7f0..0e46c96 100644 --- a/compiler/dex/quick/dex_file_method_inliner.cc +++ b/compiler/dex/quick/dex_file_method_inliner.cc @@ -48,6 +48,7 @@ static constexpr bool kIntrinsicIsStatic[] = { true, // kIntrinsicMinMaxFloat true, // kIntrinsicMinMaxDouble true, // kIntrinsicSqrt + false, // kIntrinsicGet false, // kIntrinsicCharAt false, // kIntrinsicCompareTo false, // kIntrinsicIsEmptyOrLength @@ -74,6 +75,7 @@ COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxLong], MinMaxLong_must_be_stat COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxFloat], MinMaxFloat_must_be_static); COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxDouble], MinMaxDouble_must_be_static); COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicSqrt], Sqrt_must_be_static); +COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicGet], Get_must_not_be_static); COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicCharAt], CharAt_must_not_be_static); COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicCompareTo], CompareTo_must_not_be_static); COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicIsEmptyOrLength], IsEmptyOrLength_must_not_be_static); @@ -126,6 +128,7 @@ const char* const DexFileMethodInliner::kClassCacheNames[] = { "D", // kClassCacheDouble "V", // kClassCacheVoid "Ljava/lang/Object;", // kClassCacheJavaLangObject + "Ljava/lang/ref/Reference;", // kClassCacheJavaLangRefReference "Ljava/lang/String;", // kClassCacheJavaLangString "Ljava/lang/Double;", // kClassCacheJavaLangDouble "Ljava/lang/Float;", // kClassCacheJavaLangFloat @@ -152,6 +155,7 @@ const char* const DexFileMethodInliner::kNameCacheNames[] = { "max", // kNameCacheMax "min", // kNameCacheMin "sqrt", // kNameCacheSqrt + "get", // kNameCacheGet "charAt", // kNameCacheCharAt "compareTo", // kNameCacheCompareTo "isEmpty", // kNameCacheIsEmpty @@ -220,6 +224,8 @@ const DexFileMethodInliner::ProtoDef DexFileMethodInliner::kProtoCacheDefs[] = { { kClassCacheBoolean, 0, { } }, // kProtoCache_I { kClassCacheInt, 0, { } }, + // kProtoCache_Object + { kClassCacheJavaLangObject, 0, { } }, // kProtoCache_Thread { kClassCacheJavaLangThread, 0, { } }, // kProtoCacheJ_B @@ -308,6 +314,8 @@ const DexFileMethodInliner::IntrinsicDef DexFileMethodInliner::kIntrinsicMethods INTRINSIC(JavaLangMath, Sqrt, D_D, kIntrinsicSqrt, 0), INTRINSIC(JavaLangStrictMath, Sqrt, D_D, kIntrinsicSqrt, 0), + INTRINSIC(JavaLangRefReference, Get, _Object, kIntrinsicGet, 0), + INTRINSIC(JavaLangString, CharAt, I_C, kIntrinsicCharAt, 0), INTRINSIC(JavaLangString, CompareTo, String_I, kIntrinsicCompareTo, 0), INTRINSIC(JavaLangString, IsEmpty, _Z, kIntrinsicIsEmptyOrLength, kIntrinsicFlagIsEmpty), @@ -428,6 +436,8 @@ bool DexFileMethodInliner::GenIntrinsic(Mir2Lir* backend, CallInfo* info) { return backend->GenInlinedMinMaxFP(info, intrinsic.d.data & kIntrinsicFlagMin, true /* is_double */); case kIntrinsicSqrt: return backend->GenInlinedSqrt(info); + case kIntrinsicGet: + return backend->GenInlinedGet(info); case kIntrinsicCharAt: return backend->GenInlinedCharAt(info); case kIntrinsicCompareTo: diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h index 5b3b104..cb8c165 100644 --- a/compiler/dex/quick/dex_file_method_inliner.h +++ b/compiler/dex/quick/dex_file_method_inliner.h @@ -107,6 +107,7 @@ class DexFileMethodInliner { kClassCacheDouble, kClassCacheVoid, kClassCacheJavaLangObject, + kClassCacheJavaLangRefReference, kClassCacheJavaLangString, kClassCacheJavaLangDouble, kClassCacheJavaLangFloat, @@ -140,6 +141,7 @@ class DexFileMethodInliner { kNameCacheMax, kNameCacheMin, kNameCacheSqrt, + kNameCacheGet, kNameCacheCharAt, kNameCacheCompareTo, kNameCacheIsEmpty, @@ -199,6 +201,7 @@ class DexFileMethodInliner { kProtoCacheString_I, kProtoCache_Z, kProtoCache_I, + kProtoCache_Object, kProtoCache_Thread, kProtoCacheJ_B, kProtoCacheJ_I, diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc index 79065b3..9dedeae 100755 --- a/compiler/dex/quick/gen_invoke.cc +++ b/compiler/dex/quick/gen_invoke.cc @@ -23,9 +23,12 @@ #include "invoke_type.h" #include "mirror/array.h" #include "mirror/class-inl.h" +#include "mirror/dex_cache.h" #include "mirror/object_array-inl.h" +#include "mirror/reference-inl.h" #include "mirror/string.h" #include "mir_to_lir-inl.h" +#include "scoped_thread_state_change.h" #include "x86/codegen_x86.h" namespace art { @@ -1218,6 +1221,88 @@ RegLocation Mir2Lir::InlineTargetWide(CallInfo* info) { return res; } +bool Mir2Lir::GenInlinedGet(CallInfo* info) { + if (cu_->instruction_set == kMips) { + // TODO - add Mips implementation + return false; + } + + // the refrence class is stored in the image dex file which might not be the same as the cu's + // dex file. Query the reference class for the image dex file then reset to starting dex file + // in after loading class type. + uint16_t type_idx = 0; + const DexFile* ref_dex_file = nullptr; + { + ScopedObjectAccess soa(Thread::Current()); + type_idx = mirror::Reference::GetJavaLangRefReference()->GetDexTypeIndex(); + ref_dex_file = mirror::Reference::GetJavaLangRefReference()->GetDexCache()->GetDexFile(); + } + CHECK(LIKELY(ref_dex_file != nullptr)); + + // address is either static within the image file, or needs to be patched up after compilation. + bool unused_type_initialized; + bool use_direct_type_ptr; + uintptr_t direct_type_ptr; + bool is_finalizable; + const DexFile* old_dex = cu_->dex_file; + cu_->dex_file = ref_dex_file; + RegStorage reg_class = TargetPtrReg(kArg1); + if (!cu_->compiler_driver->CanEmbedTypeInCode(*ref_dex_file, type_idx, &unused_type_initialized, + &use_direct_type_ptr, &direct_type_ptr, + &is_finalizable) || is_finalizable) { + cu_->dex_file = old_dex; + // address is not known and post-compile patch is not possible, cannot insert intrinsic. + return false; + } + if (use_direct_type_ptr) { + LoadConstant(reg_class, direct_type_ptr); + } else { + LoadClassType(type_idx, kArg1); + } + cu_->dex_file = old_dex; + + // get the offset for flags in reference class. + uint32_t slow_path_flag_offset = 0; + uint32_t disable_flag_offset = 0; + { + ScopedObjectAccess soa(Thread::Current()); + mirror::Class* reference_class = mirror::Reference::GetJavaLangRefReference(); + slow_path_flag_offset = reference_class->GetSlowPathFlagOffset().Uint32Value(); + disable_flag_offset = reference_class->GetDisableIntrinsicFlagOffset().Uint32Value(); + } + CHECK(slow_path_flag_offset && disable_flag_offset && + (slow_path_flag_offset != disable_flag_offset)); + + // intrinsic logic start. + RegLocation rl_obj = info->args[0]; + rl_obj = LoadValue(rl_obj); + + RegStorage reg_slow_path = AllocTemp(); + RegStorage reg_disabled = AllocTemp(); + Load32Disp(reg_class, slow_path_flag_offset, reg_slow_path); + Load32Disp(reg_class, disable_flag_offset, reg_disabled); + OpRegRegReg(kOpOr, reg_slow_path, reg_slow_path, reg_disabled); + FreeTemp(reg_disabled); + + // if slow path, jump to JNI path target + LIR* slow_path_branch = OpCmpImmBranch(kCondNe, reg_slow_path, 0, nullptr); + FreeTemp(reg_slow_path); + + // slow path not enabled, simply load the referent of the reference object + RegLocation rl_dest = InlineTarget(info); + RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true); + GenNullCheck(rl_obj.reg, info->opt_flags); + LoadRefDisp(rl_obj.reg, mirror::Reference::ReferentOffset().Int32Value(), rl_result.reg, + kNotVolatile); + MarkPossibleNullPointerException(info->opt_flags); + StoreValue(rl_dest, rl_result); + + LIR* intrinsic_finish = NewLIR0(kPseudoTargetLabel); + AddIntrinsicSlowPath(info, slow_path_branch, intrinsic_finish); + + return true; +} + bool Mir2Lir::GenInlinedCharAt(CallInfo* info) { if (cu_->instruction_set == kMips) { // TODO - add Mips implementation diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index fd0fe6e..c68ad6b 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -982,6 +982,7 @@ class Mir2Lir : public Backend { */ RegLocation InlineTargetWide(CallInfo* info); + bool GenInlinedGet(CallInfo* info); bool GenInlinedCharAt(CallInfo* info); bool GenInlinedStringIsEmptyOrLength(CallInfo* info, bool is_empty); virtual bool GenInlinedReverseBits(CallInfo* info, OpSize size); diff --git a/runtime/Android.mk b/runtime/Android.mk index b0c1a9c..9d42eea 100644 --- a/runtime/Android.mk +++ b/runtime/Android.mk @@ -97,6 +97,7 @@ LIBART_COMMON_SRC_FILES := \ mirror/class.cc \ mirror/dex_cache.cc \ mirror/object.cc \ + mirror/reference.cc \ mirror/stack_trace_element.cc \ mirror/string.cc \ mirror/throwable.cc \ diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 1436810..2e51cf8 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -54,6 +54,7 @@ #include "mirror/object-inl.h" #include "mirror/object_array-inl.h" #include "mirror/proxy.h" +#include "mirror/reference-inl.h" #include "mirror/stack_trace_element.h" #include "mirror/string-inl.h" #include "object_utils.h" @@ -257,6 +258,13 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class java_lang_String->SetObjectSize(mirror::String::InstanceSize()); java_lang_String->SetStatus(mirror::Class::kStatusResolved, self); + // Setup Reference. + Handle<mirror::Class> java_lang_ref_Reference(hs.NewHandle( + AllocClass(self, java_lang_Class.Get(), mirror::Reference::ClassSize()))); + mirror::Reference::SetClass(java_lang_ref_Reference.Get()); + java_lang_ref_Reference->SetObjectSize(mirror::Reference::InstanceSize()); + java_lang_ref_Reference->SetStatus(mirror::Class::kStatusResolved, self); + // Create storage for root classes, save away our work so far (requires descriptors). class_roots_ = mirror::ObjectArray<mirror::Class>::Alloc(self, object_array_class.Get(), kClassRootsMax); @@ -267,6 +275,7 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class SetClassRoot(kObjectArrayClass, object_array_class.Get()); SetClassRoot(kCharArrayClass, char_array_class.Get()); SetClassRoot(kJavaLangString, java_lang_String.Get()); + SetClassRoot(kJavaLangRefReference, java_lang_ref_Reference.Get()); // Setup the primitive type classes. SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass(self, Primitive::kPrimBoolean)); @@ -461,8 +470,12 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class SetClassRoot(kJavaLangReflectProxy, java_lang_reflect_Proxy); // java.lang.ref classes need to be specially flagged, but otherwise are normal classes - mirror::Class* java_lang_ref_Reference = FindSystemClass(self, "Ljava/lang/ref/Reference;"); - SetClassRoot(kJavaLangRefReference, java_lang_ref_Reference); + // finish initializing Reference class + java_lang_ref_Reference->SetStatus(mirror::Class::kStatusNotReady, self); + mirror::Class* Reference_class = FindSystemClass(self, "Ljava/lang/ref/Reference;"); + CHECK_EQ(java_lang_ref_Reference.Get(), Reference_class); + CHECK_EQ(java_lang_ref_Reference->GetObjectSize(), mirror::Reference::InstanceSize()); + CHECK_EQ(java_lang_ref_Reference->GetClassSize(), mirror::Reference::ClassSize()); mirror::Class* java_lang_ref_FinalizerReference = FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;"); java_lang_ref_FinalizerReference->SetAccessFlags( @@ -1231,6 +1244,7 @@ void ClassLinker::InitFromImage() { array_iftable_ = GetClassRoot(kObjectArrayClass)->GetIfTable(); DCHECK(array_iftable_ == GetClassRoot(kBooleanArrayClass)->GetIfTable()); // String class root was set above + mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference)); mirror::ArtField::SetClass(GetClassRoot(kJavaLangReflectArtField)); mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); @@ -1354,6 +1368,7 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor, void* ar ClassLinker::~ClassLinker() { mirror::Class::ResetClass(); mirror::String::ResetClass(); + mirror::Reference::ResetClass(); mirror::ArtField::ResetClass(); mirror::ArtMethod::ResetClass(); mirror::BooleanArray::ResetArrayClass(); @@ -1600,6 +1615,8 @@ mirror::Class* ClassLinker::DefineClass(const char* descriptor, klass.Assign(GetClassRoot(kJavaLangClass)); } else if (strcmp(descriptor, "Ljava/lang/String;") == 0) { klass.Assign(GetClassRoot(kJavaLangString)); + } else if (strcmp(descriptor, "Ljava/lang/ref/Reference;") == 0) { + klass.Assign(GetClassRoot(kJavaLangRefReference)); } else if (strcmp(descriptor, "Ljava/lang/DexCache;") == 0) { klass.Assign(GetClassRoot(kJavaLangDexCache)); } else if (strcmp(descriptor, "Ljava/lang/reflect/ArtField;") == 0) { diff --git a/runtime/gc/reference_processor-inl.h b/runtime/gc/reference_processor-inl.h new file mode 100644 index 0000000..f619a15 --- /dev/null +++ b/runtime/gc/reference_processor-inl.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 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_GC_REFERENCE_PROCESSOR_INL_H_ +#define ART_RUNTIME_GC_REFERENCE_PROCESSOR_INL_H_ + +#include "reference_processor.h" + +namespace art { +namespace gc { + +inline bool ReferenceProcessor::SlowPathEnabled() { + return mirror::Reference::GetJavaLangRefReference()->GetSlowPathEnabled(); +} + +} // namespace gc +} // namespace art + +#endif // ART_RUNTIME_GC_REFERENCE_PROCESSOR_INL_H_ diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc index e52bc1f..d3641d1 100644 --- a/runtime/gc/reference_processor.cc +++ b/runtime/gc/reference_processor.cc @@ -17,7 +17,9 @@ #include "reference_processor.h" #include "mirror/object-inl.h" +#include "mirror/reference.h" #include "mirror/reference-inl.h" +#include "reference_processor-inl.h" #include "reflection.h" #include "ScopedLocalRef.h" #include "scoped_thread_state_change.h" @@ -27,18 +29,17 @@ namespace art { namespace gc { ReferenceProcessor::ReferenceProcessor() - : process_references_args_(nullptr, nullptr, nullptr), slow_path_enabled_(false), + : process_references_args_(nullptr, nullptr, nullptr), preserving_references_(false), lock_("reference processor lock", kReferenceProcessorLock), condition_("reference processor condition", lock_) { } void ReferenceProcessor::EnableSlowPath() { - Locks::mutator_lock_->AssertExclusiveHeld(Thread::Current()); - slow_path_enabled_ = true; + mirror::Reference::GetJavaLangRefReference()->SetSlowPath(true); } void ReferenceProcessor::DisableSlowPath(Thread* self) { - slow_path_enabled_ = false; + mirror::Reference::GetJavaLangRefReference()->SetSlowPath(false); condition_.Broadcast(self); } @@ -46,11 +47,11 @@ mirror::Object* ReferenceProcessor::GetReferent(Thread* self, mirror::Reference* mirror::Object* const referent = reference->GetReferent(); // If the referent is null then it is already cleared, we can just return null since there is no // scenario where it becomes non-null during the reference processing phase. - if (LIKELY(!slow_path_enabled_) || referent == nullptr) { + if (UNLIKELY(!SlowPathEnabled()) || referent == nullptr) { return referent; } MutexLock mu(self, lock_); - while (slow_path_enabled_) { + while (SlowPathEnabled()) { mirror::HeapReference<mirror::Object>* const referent_addr = reference->GetReferentReferenceAddr(); // If the referent became cleared, return it. Don't need barrier since thread roots can't get @@ -117,7 +118,7 @@ void ReferenceProcessor::ProcessReferences(bool concurrent, TimingLogger* timing process_references_args_.is_marked_callback_ = is_marked_callback; process_references_args_.mark_callback_ = mark_object_callback; process_references_args_.arg_ = arg; - CHECK_EQ(slow_path_enabled_, concurrent) << "Slow path must be enabled iff concurrent"; + CHECK_EQ(SlowPathEnabled(), concurrent) << "Slow path must be enabled iff concurrent"; } // Unless required to clear soft references with white references, preserve some white referents. if (!clear_soft_references) { @@ -182,7 +183,7 @@ void ReferenceProcessor::DelayReferenceReferent(mirror::Class* klass, mirror::Re void* arg) { // klass can be the class of the old object if the visitor already updated the class of ref. DCHECK(klass != nullptr); - DCHECK(klass->IsReferenceClass()); + DCHECK(klass->IsTypeOfReferenceClass()); mirror::HeapReference<mirror::Object>* referent = ref->GetReferentReferenceAddr(); if (referent->AsMirrorPtr() != nullptr && !is_marked_callback(referent, arg)) { Thread* self = Thread::Current(); diff --git a/runtime/gc/reference_processor.h b/runtime/gc/reference_processor.h index 2771ea8..7274457 100644 --- a/runtime/gc/reference_processor.h +++ b/runtime/gc/reference_processor.h @@ -49,6 +49,7 @@ class ReferenceProcessor { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) LOCKS_EXCLUDED(lock_); + // The slow path bool is contained in the reference class object, can only be set once // Only allow setting this with mutators suspended so that we can avoid using a lock in the // GetReferent fast path as an optimization. void EnableSlowPath() EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -60,7 +61,7 @@ class ReferenceProcessor { IsHeapReferenceMarkedCallback* is_marked_callback, void* arg) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void UpdateRoots(IsMarkedCallback* callback, void* arg) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_); + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_); private: class ProcessReferencesArgs { @@ -75,8 +76,10 @@ class ReferenceProcessor { MarkObjectCallback* mark_callback_; void* arg_; }; + bool SlowPathEnabled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Called by ProcessReferences. - void DisableSlowPath(Thread* self) EXCLUSIVE_LOCKS_REQUIRED(lock_); + void DisableSlowPath(Thread* self) EXCLUSIVE_LOCKS_REQUIRED(lock_) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // If we are preserving references it means that some dead objects may become live, we use start // and stop preserving to block mutators using GetReferrent from getting access to these // referents. @@ -84,8 +87,6 @@ class ReferenceProcessor { void StopPreservingReferences(Thread* self) LOCKS_EXCLUDED(lock_); // Process args, used by the GetReferent to return referents which are already marked. ProcessReferencesArgs process_references_args_ GUARDED_BY(lock_); - // Boolean for whether or not we need to go slow path in GetReferent. - volatile bool slow_path_enabled_; // Boolean for whether or not we are preserving references (either soft references or finalizers). // If this is true, then we cannot return a referent (see comment in GetReferent). bool preserving_references_ GUARDED_BY(lock_); diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h index 349d4a3..329a984 100644 --- a/runtime/mirror/class-inl.h +++ b/runtime/mirror/class-inl.h @@ -30,6 +30,7 @@ #include "iftable.h" #include "object_array-inl.h" #include "read_barrier-inl.h" +#include "reference-inl.h" #include "runtime.h" #include "string.h" @@ -591,6 +592,11 @@ inline bool Class::IsArtMethodClass() const { return this == ArtMethod::GetJavaLangReflectArtMethod<kReadBarrierOption>(); } +template<ReadBarrierOption kReadBarrierOption> +inline bool Class::IsReferenceClass() const { + return this == Reference::GetJavaLangRefReference<kReadBarrierOption>(); +} + template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> inline bool Class::IsClassClass() { Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()-> @@ -642,6 +648,30 @@ inline ObjectArray<ObjectArray<Class>>* Class::GetThrows() { return GetFieldObject<ObjectArray<ObjectArray<Class>>>(field_offset); } +inline MemberOffset Class::GetDisableIntrinsicFlagOffset() { + CHECK(IsReferenceClass()); + // First static field + DCHECK(GetSFields()->Get(0)->IsArtField()); + DCHECK_STREQ(GetSFields()->Get(0)->GetName(), "disableIntrinsic"); + return GetSFields()->Get(0)->GetOffset(); +} + +inline MemberOffset Class::GetSlowPathFlagOffset() { + CHECK(IsReferenceClass()); + // Second static field + DCHECK(GetSFields()->Get(1)->IsArtField()); + DCHECK_STREQ(GetSFields()->Get(1)->GetName(), "slowPathEnabled"); + return GetSFields()->Get(1)->GetOffset(); +} + +inline bool Class::GetSlowPathEnabled() { + return GetField32(GetSlowPathFlagOffset()); +} + +inline void Class::SetSlowPath(bool enabled) { + SetField32<false>(GetSlowPathFlagOffset(), enabled); +} + inline void Class::InitializeClassVisitor::operator()( mirror::Object* obj, size_t usable_size) const { DCHECK_LE(class_size_, usable_size); diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 0f42044..648bdde 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -261,7 +261,7 @@ class MANAGED Class FINAL : public Object { } template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> - bool IsReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + bool IsTypeOfReferenceClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { return (GetAccessFlags<kVerifyFlags>() & kAccClassIsReference) != 0; } @@ -419,6 +419,9 @@ class MANAGED Class FINAL : public Object { template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> bool IsArtMethodClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> + bool IsReferenceClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + static MemberOffset ComponentTypeOffset() { return OFFSET_OF_OBJECT_MEMBER(Class, component_type_); } @@ -976,6 +979,12 @@ class MANAGED Class FINAL : public Object { // For proxy class only. ObjectArray<ObjectArray<Class>>* GetThrows() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // For reference class only. + MemberOffset GetDisableIntrinsicFlagOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + MemberOffset GetSlowPathFlagOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool GetSlowPathEnabled() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void SetSlowPath(bool enabled) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Used to initialize a class in the allocation code path to ensure it is guarded by a StoreStore // fence. class InitializeClassVisitor { diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h index 3d45683..9dbfb56 100644 --- a/runtime/mirror/object-inl.h +++ b/runtime/mirror/object-inl.h @@ -249,7 +249,7 @@ inline ArtMethod* Object::AsArtMethod() { template<VerifyObjectFlags kVerifyFlags> inline bool Object::IsReferenceInstance() { - return GetClass<kVerifyFlags>()->IsReferenceClass(); + return GetClass<kVerifyFlags>()->IsTypeOfReferenceClass(); } template<VerifyObjectFlags kVerifyFlags> @@ -806,7 +806,7 @@ inline void Object::VisitReferences(const Visitor& visitor, } else { DCHECK(!klass->IsVariableSize()); VisitInstanceFieldsReferences<kVisitClass>(klass, visitor); - if (UNLIKELY(klass->IsReferenceClass<kVerifyNone>())) { + if (UNLIKELY(klass->IsTypeOfReferenceClass<kVerifyNone>())) { ref_visitor(klass, AsReference()); } } diff --git a/runtime/mirror/object.cc b/runtime/mirror/object.cc index 5f88d54..bc5cbcb 100644 --- a/runtime/mirror/object.cc +++ b/runtime/mirror/object.cc @@ -57,7 +57,7 @@ class CopyReferenceFieldsWithReadBarrierVisitor { ALWAYS_INLINE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { // Copy java.lang.ref.Reference.referent which isn't visited in // Object::VisitReferences(). - DCHECK(klass->IsReferenceClass()); + DCHECK(klass->IsTypeOfReferenceClass()); this->operator()(ref, mirror::Reference::ReferentOffset(), false); } diff --git a/runtime/mirror/reference-inl.h b/runtime/mirror/reference-inl.h index 43767c8..b353402 100644 --- a/runtime/mirror/reference-inl.h +++ b/runtime/mirror/reference-inl.h @@ -22,6 +22,11 @@ namespace art { namespace mirror { +inline uint32_t Reference::ClassSize() { + uint32_t vtable_entries = Object::kVTableLength + 5; + return Class::ComputeClassSize(false, vtable_entries, 2, 0, 0); +} + inline bool Reference::IsEnqueuable() { // Not using volatile reads as an optimization since this is only called with all the mutators // suspended. diff --git a/runtime/mirror/reference.cc b/runtime/mirror/reference.cc new file mode 100644 index 0000000..077cd4b --- /dev/null +++ b/runtime/mirror/reference.cc @@ -0,0 +1,43 @@ +/* + * 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 "reference.h" + +namespace art { +namespace mirror { + +Class* Reference::java_lang_ref_Reference_ = nullptr; + +void Reference::SetClass(Class* java_lang_ref_Reference) { + CHECK(java_lang_ref_Reference_ == nullptr); + CHECK(java_lang_ref_Reference != nullptr); + java_lang_ref_Reference_ = java_lang_ref_Reference; +} + +void Reference::ResetClass() { + CHECK(java_lang_ref_Reference_ != nullptr); + java_lang_ref_Reference_ = nullptr; +} + +void Reference::VisitRoots(RootCallback* callback, void* arg) { + if (java_lang_ref_Reference_ != nullptr) { + callback(reinterpret_cast<mirror::Object**>(&java_lang_ref_Reference_), + arg, 0, kRootStickyClass); + } +} + +} // namespace mirror +} // namespace art diff --git a/runtime/mirror/reference.h b/runtime/mirror/reference.h index 9c9d87b..07d47d3 100644 --- a/runtime/mirror/reference.h +++ b/runtime/mirror/reference.h @@ -17,7 +17,11 @@ #ifndef ART_RUNTIME_MIRROR_REFERENCE_H_ #define ART_RUNTIME_MIRROR_REFERENCE_H_ +#include "class.h" #include "object.h" +#include "object_callbacks.h" +#include "read_barrier.h" +#include "thread.h" namespace art { @@ -36,6 +40,14 @@ namespace mirror { // C++ mirror of java.lang.ref.Reference class MANAGED Reference : public Object { public: + // Size of java.lang.ref.Reference.class. + static uint32_t ClassSize(); + + // Size of an instance of java.lang.ref.Reference. + static constexpr uint32_t InstanceSize() { + return sizeof(Reference); + } + static MemberOffset PendingNextOffset() { return OFFSET_OF_OBJECT_MEMBER(Reference, pending_next_); } @@ -80,6 +92,16 @@ class MANAGED Reference : public Object { bool IsEnqueuable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> + static Class* GetJavaLangRefReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + DCHECK(java_lang_ref_Reference_ != nullptr); + return ReadBarrier::BarrierForRoot<mirror::Class, kReadBarrierOption>( + &java_lang_ref_Reference_); + } + static void SetClass(Class* klass); + static void ResetClass(void); + static void VisitRoots(RootCallback* callback, void* arg); + private: // Note: This avoids a read barrier, it should only be used by the GC. HeapReference<Object>* GetReferentReferenceAddr() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { @@ -92,6 +114,8 @@ class MANAGED Reference : public Object { HeapReference<Reference> queue_next_; // Note this is Java volatile: HeapReference<Object> referent_; // Note this is Java volatile: + static Class* java_lang_ref_Reference_; + friend struct art::ReferenceOffsets; // for verifying offset information friend class gc::ReferenceProcessor; friend class gc::ReferenceQueue; diff --git a/runtime/quick/inline_method_analyser.h b/runtime/quick/inline_method_analyser.h index 5128b19..982553d 100644 --- a/runtime/quick/inline_method_analyser.h +++ b/runtime/quick/inline_method_analyser.h @@ -48,6 +48,7 @@ enum InlineMethodOpcode : uint16_t { kIntrinsicMinMaxFloat, kIntrinsicMinMaxDouble, kIntrinsicSqrt, + kIntrinsicGet, kIntrinsicCharAt, kIntrinsicCompareTo, kIntrinsicIsEmptyOrLength, diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 4cfd55e..0ddd2ae 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -926,6 +926,7 @@ void Runtime::VisitConstantRoots(RootCallback* callback, void* arg) { mirror::ArtField::VisitRoots(callback, arg); mirror::ArtMethod::VisitRoots(callback, arg); mirror::Class::VisitRoots(callback, arg); + mirror::Reference::VisitRoots(callback, arg); mirror::StackTraceElement::VisitRoots(callback, arg); mirror::String::VisitRoots(callback, arg); mirror::Throwable::VisitRoots(callback, arg); |