diff options
author | Christopher Ferris <cferris@google.com> | 2014-07-11 06:44:39 +0000 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2014-07-11 06:44:39 +0000 |
commit | d4415e8bd04c4a9367744ff0149597b4f37a0e0a (patch) | |
tree | 97c42c08fd04034cf6cecadb39644bf9531be0f1 /runtime | |
parent | a9b870b73a155ce70c867d5b3f9758fab0b45f07 (diff) | |
download | art-d4415e8bd04c4a9367744ff0149597b4f37a0e0a.tar.gz art-d4415e8bd04c4a9367744ff0149597b4f37a0e0a.tar.bz2 art-d4415e8bd04c4a9367744ff0149597b4f37a0e0a.zip |
Revert "Revert "Add intrinsic for Reference.get()""
This reverts commit a9b870b73a155ce70c867d5b3f9758fab0b45f07.
Change-Id: Ic2a9b47f2b911bef4b764d10bc33cf000e4b4211
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/Android.mk | 1 | ||||
-rw-r--r-- | runtime/class_linker.cc | 24 | ||||
-rw-r--r-- | runtime/class_linker_test.cc | 8 | ||||
-rw-r--r-- | runtime/gc/reference_processor-inl.h | 32 | ||||
-rw-r--r-- | runtime/gc/reference_processor.cc | 15 | ||||
-rw-r--r-- | runtime/gc/reference_processor.h | 10 | ||||
-rw-r--r-- | runtime/mirror/reference.cc | 43 | ||||
-rw-r--r-- | runtime/mirror/reference.h | 48 | ||||
-rw-r--r-- | runtime/quick/inline_method_analyser.h | 1 | ||||
-rw-r--r-- | runtime/runtime.cc | 1 |
10 files changed, 170 insertions, 13 deletions
diff --git a/runtime/Android.mk b/runtime/Android.mk index 7f5cf0c56f..2544a07794 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 5180e34313..a957eb6649 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -254,6 +254,13 @@ void ClassLinker::InitFromCompiler(const std::vector<const DexFile*>& boot_class java_lang_String->SetObjectSize(sizeof(mirror::String)); 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(), sizeof(mirror::ReferenceClass)))); + mirror::Reference::SetClass(down_cast<mirror::ReferenceClass*>(java_lang_ref_Reference.Get())); + java_lang_ref_Reference->SetObjectSize(sizeof(mirror::Reference)); + 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); @@ -264,6 +271,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)); @@ -452,8 +460,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(), sizeof(mirror::Reference)); + CHECK_EQ(java_lang_ref_Reference->GetClassSize(), sizeof(mirror::ReferenceClass)); mirror::Class* java_lang_ref_FinalizerReference = FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;"); java_lang_ref_FinalizerReference->SetAccessFlags( @@ -538,6 +550,9 @@ void ClassLinker::FinishInit(Thread* self) { CHECK(array_iftable_ != NULL); + // disable slow path for reference gets + mirror::Reference::GetJavaLangRefReference()->Init(); + // disable the slow paths in FindClass and CreatePrimitiveClass now // that Object, Class, and Object[] are setup init_done_ = true; @@ -1220,6 +1235,8 @@ void ClassLinker::InitFromImage() { array_iftable_ = GetClassRoot(kObjectArrayClass)->GetIfTable(); DCHECK(array_iftable_ == GetClassRoot(kBooleanArrayClass)->GetIfTable()); // String class root was set above + mirror::Reference::SetClass(down_cast<mirror::ReferenceClass*>(GetClassRoot( + kJavaLangRefReference))); mirror::ArtField::SetClass(GetClassRoot(kJavaLangReflectArtField)); mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass)); mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass)); @@ -1343,6 +1360,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(); @@ -1587,6 +1605,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/class_linker_test.cc b/runtime/class_linker_test.cc index 04f6946aa8..8fdead6dde 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -626,6 +626,13 @@ struct ReferenceOffsets : public CheckOffsets<mirror::Reference> { }; }; +struct ReferenceClassOffsets : public CheckOffsets<mirror::ReferenceClass> { + ReferenceClassOffsets() : CheckOffsets<mirror::ReferenceClass>(true, "Ljava/lang/ref/Reference;") { + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ReferenceClass, disable_intrinsic_), "disableIntrinsic")); + offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ReferenceClass, slow_path_enabled_), "slowPathEnabled")); + }; +}; + struct FinalizerReferenceOffsets : public CheckOffsets<mirror::FinalizerReference> { FinalizerReferenceOffsets() : CheckOffsets<mirror::FinalizerReference>(false, "Ljava/lang/ref/FinalizerReference;") { // alphabetical references @@ -651,6 +658,7 @@ TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) { EXPECT_TRUE(ProxyOffsets().Check()); EXPECT_TRUE(DexCacheOffsets().Check()); EXPECT_TRUE(ReferenceOffsets().Check()); + EXPECT_TRUE(ReferenceClassOffsets().Check()); EXPECT_TRUE(FinalizerReferenceOffsets().Check()); EXPECT_TRUE(ClassClassOffsets().Check()); diff --git a/runtime/gc/reference_processor-inl.h b/runtime/gc/reference_processor-inl.h new file mode 100644 index 0000000000..f619a15f74 --- /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 e52bc1fd1e..62d9e68273 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()->SetSlowPathEnabled(true); } void ReferenceProcessor::DisableSlowPath(Thread* self) { - slow_path_enabled_ = false; + mirror::Reference::GetJavaLangRefReference()->SetSlowPathEnabled(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) { diff --git a/runtime/gc/reference_processor.h b/runtime/gc/reference_processor.h index 2771ea809b..91328a385f 100644 --- a/runtime/gc/reference_processor.h +++ b/runtime/gc/reference_processor.h @@ -30,6 +30,7 @@ class TimingLogger; namespace mirror { class Object; class Reference; +class ReferenceClass; } // namespace mirror namespace gc { @@ -49,6 +50,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 +62,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 +77,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 +88,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/reference.cc b/runtime/mirror/reference.cc new file mode 100644 index 0000000000..533aaca536 --- /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 { + +ReferenceClass* Reference::java_lang_ref_Reference_ = nullptr; + +void Reference::SetClass(ReferenceClass* 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 9c9d87be01..15e0145baf 100644 --- a/runtime/mirror/reference.h +++ b/runtime/mirror/reference.h @@ -17,7 +17,10 @@ #ifndef ART_RUNTIME_MIRROR_REFERENCE_H_ #define ART_RUNTIME_MIRROR_REFERENCE_H_ +#include "class.h" #include "object.h" +#include "object_callbacks.h" +#include "thread.h" namespace art { @@ -29,9 +32,11 @@ class ReferenceQueue; } // namespace gc struct ReferenceOffsets; +struct ReferenceClassOffsets; struct FinalizerReferenceOffsets; namespace mirror { +class ReferenceClass; // C++ mirror of java.lang.ref.Reference class MANAGED Reference : public Object { @@ -80,6 +85,15 @@ class MANAGED Reference : public Object { bool IsEnqueuable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + static ReferenceClass* GetJavaLangRefReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + CHECK(java_lang_ref_Reference_ != nullptr); + return ReadBarrier::BarrierForRoot<mirror::ReferenceClass, kWithReadBarrier>( + &java_lang_ref_Reference_); + } + static void SetClass(ReferenceClass* 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,12 +106,46 @@ class MANAGED Reference : public Object { HeapReference<Reference> queue_next_; // Note this is Java volatile: HeapReference<Object> referent_; // Note this is Java volatile: + static ReferenceClass* java_lang_ref_Reference_; + friend struct art::ReferenceOffsets; // for verifying offset information friend class gc::ReferenceProcessor; friend class gc::ReferenceQueue; DISALLOW_IMPLICIT_CONSTRUCTORS(Reference); }; +// Tightly coupled with the ReferenceProcessor to provide switch for slow/fast path. Consistency +// is maintained by ReferenceProcessor. +class MANAGED ReferenceClass : public Class { + public: + static MemberOffset DisableIntrinsicOffset() { + return OFFSET_OF_OBJECT_MEMBER(ReferenceClass, disable_intrinsic_); + } + static MemberOffset SlowPathEnabledOffset() { + return OFFSET_OF_OBJECT_MEMBER(ReferenceClass, slow_path_enabled_); + } + + void Init() { + disable_intrinsic_ = false; + slow_path_enabled_ = false; + } + + bool GetSlowPathEnabled() const { + return slow_path_enabled_; + } + void SetSlowPathEnabled(bool enabled) { + slow_path_enabled_ = enabled; + } + + private: + int32_t disable_intrinsic_; + int32_t slow_path_enabled_; + // allows runtime to safely enable/disable intrinsics fast path for benchmarking + + friend struct art::ReferenceClassOffsets; // for verifying offset information + DISALLOW_IMPLICIT_CONSTRUCTORS(ReferenceClass); +}; + // C++ mirror of java.lang.ref.FinalizerReference class MANAGED FinalizerReference : public Reference { public: diff --git a/runtime/quick/inline_method_analyser.h b/runtime/quick/inline_method_analyser.h index 5128b19d12..982553d3af 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 efa205e079..ac478885d2 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -921,6 +921,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); |