1*795d594fSAndroid Build Coastguard Worker /* Copyright (C) 2017 The Android Open Source Project 2*795d594fSAndroid Build Coastguard Worker * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3*795d594fSAndroid Build Coastguard Worker * 4*795d594fSAndroid Build Coastguard Worker * This file implements interfaces from the file jvmti.h. This implementation 5*795d594fSAndroid Build Coastguard Worker * is licensed under the same terms as the file jvmti.h. The 6*795d594fSAndroid Build Coastguard Worker * copyright and license information for the file jvmti.h follows. 7*795d594fSAndroid Build Coastguard Worker * 8*795d594fSAndroid Build Coastguard Worker * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 9*795d594fSAndroid Build Coastguard Worker * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 10*795d594fSAndroid Build Coastguard Worker * 11*795d594fSAndroid Build Coastguard Worker * This code is free software; you can redistribute it and/or modify it 12*795d594fSAndroid Build Coastguard Worker * under the terms of the GNU General Public License version 2 only, as 13*795d594fSAndroid Build Coastguard Worker * published by the Free Software Foundation. Oracle designates this 14*795d594fSAndroid Build Coastguard Worker * particular file as subject to the "Classpath" exception as provided 15*795d594fSAndroid Build Coastguard Worker * by Oracle in the LICENSE file that accompanied this code. 16*795d594fSAndroid Build Coastguard Worker * 17*795d594fSAndroid Build Coastguard Worker * This code is distributed in the hope that it will be useful, but WITHOUT 18*795d594fSAndroid Build Coastguard Worker * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19*795d594fSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 20*795d594fSAndroid Build Coastguard Worker * version 2 for more details (a copy is included in the LICENSE file that 21*795d594fSAndroid Build Coastguard Worker * accompanied this code). 22*795d594fSAndroid Build Coastguard Worker * 23*795d594fSAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License version 24*795d594fSAndroid Build Coastguard Worker * 2 along with this work; if not, write to the Free Software Foundation, 25*795d594fSAndroid Build Coastguard Worker * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 26*795d594fSAndroid Build Coastguard Worker * 27*795d594fSAndroid Build Coastguard Worker * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 28*795d594fSAndroid Build Coastguard Worker * or visit www.oracle.com if you need additional information or have any 29*795d594fSAndroid Build Coastguard Worker * questions. 30*795d594fSAndroid Build Coastguard Worker */ 31*795d594fSAndroid Build Coastguard Worker 32*795d594fSAndroid Build Coastguard Worker #ifndef ART_OPENJDKJVMTI_JVMTI_WEAK_TABLE_H_ 33*795d594fSAndroid Build Coastguard Worker #define ART_OPENJDKJVMTI_JVMTI_WEAK_TABLE_H_ 34*795d594fSAndroid Build Coastguard Worker 35*795d594fSAndroid Build Coastguard Worker #include <unordered_map> 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker #include "base/globals.h" 38*795d594fSAndroid Build Coastguard Worker #include "base/macros.h" 39*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h" 40*795d594fSAndroid Build Coastguard Worker #include "gc/system_weak.h" 41*795d594fSAndroid Build Coastguard Worker #include "gc_root-inl.h" 42*795d594fSAndroid Build Coastguard Worker #include "jvmti.h" 43*795d594fSAndroid Build Coastguard Worker #include "jvmti_allocator.h" 44*795d594fSAndroid Build Coastguard Worker #include "mirror/object.h" 45*795d594fSAndroid Build Coastguard Worker #include "thread-current-inl.h" 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker namespace openjdkjvmti { 48*795d594fSAndroid Build Coastguard Worker 49*795d594fSAndroid Build Coastguard Worker class EventHandler; 50*795d594fSAndroid Build Coastguard Worker 51*795d594fSAndroid Build Coastguard Worker // A system-weak container mapping objects to elements of the template type. This corresponds 52*795d594fSAndroid Build Coastguard Worker // to a weak hash map. For historical reasons the stored value is called "tag." 53*795d594fSAndroid Build Coastguard Worker template <typename T> 54*795d594fSAndroid Build Coastguard Worker class JvmtiWeakTable : public art::gc::SystemWeakHolder { 55*795d594fSAndroid Build Coastguard Worker public: JvmtiWeakTable()56*795d594fSAndroid Build Coastguard Worker JvmtiWeakTable() 57*795d594fSAndroid Build Coastguard Worker : art::gc::SystemWeakHolder(art::kTaggingLockLevel), 58*795d594fSAndroid Build Coastguard Worker update_since_last_sweep_(false) { 59*795d594fSAndroid Build Coastguard Worker } 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker // Remove the mapping for the given object, returning whether such a mapping existed (and the old 62*795d594fSAndroid Build Coastguard Worker // value). 63*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE bool Remove(art::ObjPtr<art::mirror::Object> obj, /* out */ T* tag) 64*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 65*795d594fSAndroid Build Coastguard Worker REQUIRES(!allow_disallow_lock_); 66*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE bool RemoveLocked(art::ObjPtr<art::mirror::Object> obj, /* out */ T* tag) 67*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 68*795d594fSAndroid Build Coastguard Worker REQUIRES(allow_disallow_lock_); 69*795d594fSAndroid Build Coastguard Worker 70*795d594fSAndroid Build Coastguard Worker // Set the mapping for the given object. Returns true if this overwrites an already existing 71*795d594fSAndroid Build Coastguard Worker // mapping. 72*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE virtual bool Set(art::ObjPtr<art::mirror::Object> obj, T tag) 73*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 74*795d594fSAndroid Build Coastguard Worker REQUIRES(!allow_disallow_lock_); 75*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE virtual bool SetLocked(art::ObjPtr<art::mirror::Object> obj, T tag) 76*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 77*795d594fSAndroid Build Coastguard Worker REQUIRES(allow_disallow_lock_); 78*795d594fSAndroid Build Coastguard Worker 79*795d594fSAndroid Build Coastguard Worker // Return the value associated with the given object. Returns true if the mapping exists, false 80*795d594fSAndroid Build Coastguard Worker // otherwise. GetTag(art::ObjPtr<art::mirror::Object> obj,T * result)81*795d594fSAndroid Build Coastguard Worker bool GetTag(art::ObjPtr<art::mirror::Object> obj, /* out */ T* result) 82*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 83*795d594fSAndroid Build Coastguard Worker REQUIRES(!allow_disallow_lock_) { 84*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current(); 85*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(self, allow_disallow_lock_); 86*795d594fSAndroid Build Coastguard Worker Wait(self); 87*795d594fSAndroid Build Coastguard Worker 88*795d594fSAndroid Build Coastguard Worker return GetTagLocked(self, obj, result); 89*795d594fSAndroid Build Coastguard Worker } GetTagLocked(art::ObjPtr<art::mirror::Object> obj,T * result)90*795d594fSAndroid Build Coastguard Worker bool GetTagLocked(art::ObjPtr<art::mirror::Object> obj, /* out */ T* result) 91*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 92*795d594fSAndroid Build Coastguard Worker REQUIRES(allow_disallow_lock_) { 93*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current(); 94*795d594fSAndroid Build Coastguard Worker allow_disallow_lock_.AssertHeld(self); 95*795d594fSAndroid Build Coastguard Worker Wait(self); 96*795d594fSAndroid Build Coastguard Worker 97*795d594fSAndroid Build Coastguard Worker return GetTagLocked(self, obj, result); 98*795d594fSAndroid Build Coastguard Worker } 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker // Sweep the container. DO NOT CALL MANUALLY. 101*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void Sweep(art::IsMarkedVisitor* visitor) 102*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 103*795d594fSAndroid Build Coastguard Worker REQUIRES(!allow_disallow_lock_); 104*795d594fSAndroid Build Coastguard Worker 105*795d594fSAndroid Build Coastguard Worker // Return all objects that have a value mapping in tags. 106*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE 107*795d594fSAndroid Build Coastguard Worker jvmtiError GetTaggedObjects(jvmtiEnv* jvmti_env, 108*795d594fSAndroid Build Coastguard Worker jint tag_count, 109*795d594fSAndroid Build Coastguard Worker const T* tags, 110*795d594fSAndroid Build Coastguard Worker /* out */ jint* count_ptr, 111*795d594fSAndroid Build Coastguard Worker /* out */ jobject** object_result_ptr, 112*795d594fSAndroid Build Coastguard Worker /* out */ T** tag_result_ptr) 113*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 114*795d594fSAndroid Build Coastguard Worker REQUIRES(!allow_disallow_lock_); 115*795d594fSAndroid Build Coastguard Worker 116*795d594fSAndroid Build Coastguard Worker // Locking functions, to allow coarse-grained locking and amortization. 117*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void Lock() ACQUIRE(allow_disallow_lock_); 118*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void Unlock() RELEASE(allow_disallow_lock_); 119*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void AssertLocked() ASSERT_CAPABILITY(allow_disallow_lock_); 120*795d594fSAndroid Build Coastguard Worker 121*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE art::ObjPtr<art::mirror::Object> Find(T tag) 122*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 123*795d594fSAndroid Build Coastguard Worker REQUIRES(!allow_disallow_lock_); 124*795d594fSAndroid Build Coastguard Worker 125*795d594fSAndroid Build Coastguard Worker protected: 126*795d594fSAndroid Build Coastguard Worker // Should HandleNullSweep be called when Sweep detects the release of an object? DoesHandleNullOnSweep()127*795d594fSAndroid Build Coastguard Worker virtual bool DoesHandleNullOnSweep() { 128*795d594fSAndroid Build Coastguard Worker return false; 129*795d594fSAndroid Build Coastguard Worker } 130*795d594fSAndroid Build Coastguard Worker // If DoesHandleNullOnSweep returns true, this function will be called. HandleNullSweep(T tag)131*795d594fSAndroid Build Coastguard Worker virtual void HandleNullSweep([[maybe_unused]] T tag) {} 132*795d594fSAndroid Build Coastguard Worker 133*795d594fSAndroid Build Coastguard Worker private: 134*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE 135*795d594fSAndroid Build Coastguard Worker bool SetLocked(art::Thread* self, art::ObjPtr<art::mirror::Object> obj, T tag) 136*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 137*795d594fSAndroid Build Coastguard Worker REQUIRES(allow_disallow_lock_); 138*795d594fSAndroid Build Coastguard Worker 139*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE 140*795d594fSAndroid Build Coastguard Worker bool RemoveLocked(art::Thread* self, art::ObjPtr<art::mirror::Object> obj, /* out */ T* tag) 141*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 142*795d594fSAndroid Build Coastguard Worker REQUIRES(allow_disallow_lock_); 143*795d594fSAndroid Build Coastguard Worker GetTagLocked(art::Thread * self,art::ObjPtr<art::mirror::Object> obj,T * result)144*795d594fSAndroid Build Coastguard Worker bool GetTagLocked(art::Thread* self, art::ObjPtr<art::mirror::Object> obj, /* out */ T* result) 145*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 146*795d594fSAndroid Build Coastguard Worker REQUIRES(allow_disallow_lock_) { 147*795d594fSAndroid Build Coastguard Worker auto it = tagged_objects_.find(art::GcRoot<art::mirror::Object>(obj)); 148*795d594fSAndroid Build Coastguard Worker if (it != tagged_objects_.end()) { 149*795d594fSAndroid Build Coastguard Worker *result = it->second; 150*795d594fSAndroid Build Coastguard Worker return true; 151*795d594fSAndroid Build Coastguard Worker } 152*795d594fSAndroid Build Coastguard Worker 153*795d594fSAndroid Build Coastguard Worker // Performance optimization: To avoid multiple table updates, ensure that during GC we 154*795d594fSAndroid Build Coastguard Worker // only update once. See the comment on the implementation of GetTagSlowPath. 155*795d594fSAndroid Build Coastguard Worker if (art::gUseReadBarrier && 156*795d594fSAndroid Build Coastguard Worker self != nullptr && 157*795d594fSAndroid Build Coastguard Worker self->GetIsGcMarking() && 158*795d594fSAndroid Build Coastguard Worker !update_since_last_sweep_) { 159*795d594fSAndroid Build Coastguard Worker return GetTagSlowPath(self, obj, result); 160*795d594fSAndroid Build Coastguard Worker } 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker return false; 163*795d594fSAndroid Build Coastguard Worker } 164*795d594fSAndroid Build Coastguard Worker 165*795d594fSAndroid Build Coastguard Worker // Slow-path for GetTag. We didn't find the object, but we might be storing from-pointers and 166*795d594fSAndroid Build Coastguard Worker // are asked to retrieve with a to-pointer. 167*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE 168*795d594fSAndroid Build Coastguard Worker bool GetTagSlowPath(art::Thread* self, art::ObjPtr<art::mirror::Object> obj, /* out */ T* result) 169*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 170*795d594fSAndroid Build Coastguard Worker REQUIRES(allow_disallow_lock_); 171*795d594fSAndroid Build Coastguard Worker 172*795d594fSAndroid Build Coastguard Worker // Update the table by doing read barriers on each element, ensuring that to-space pointers 173*795d594fSAndroid Build Coastguard Worker // are stored. 174*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE 175*795d594fSAndroid Build Coastguard Worker void UpdateTableWithReadBarrier() 176*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 177*795d594fSAndroid Build Coastguard Worker REQUIRES(allow_disallow_lock_); 178*795d594fSAndroid Build Coastguard Worker 179*795d594fSAndroid Build Coastguard Worker template <bool kHandleNull> 180*795d594fSAndroid Build Coastguard Worker void SweepImpl(art::IsMarkedVisitor* visitor) 181*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 182*795d594fSAndroid Build Coastguard Worker REQUIRES(!allow_disallow_lock_); 183*795d594fSAndroid Build Coastguard Worker 184*795d594fSAndroid Build Coastguard Worker enum TableUpdateNullTarget { 185*795d594fSAndroid Build Coastguard Worker kIgnoreNull, 186*795d594fSAndroid Build Coastguard Worker kRemoveNull, 187*795d594fSAndroid Build Coastguard Worker kCallHandleNull 188*795d594fSAndroid Build Coastguard Worker }; 189*795d594fSAndroid Build Coastguard Worker 190*795d594fSAndroid Build Coastguard Worker template <typename Updater, TableUpdateNullTarget kTargetNull> 191*795d594fSAndroid Build Coastguard Worker void UpdateTableWith(Updater& updater) 192*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) 193*795d594fSAndroid Build Coastguard Worker REQUIRES(allow_disallow_lock_); 194*795d594fSAndroid Build Coastguard Worker 195*795d594fSAndroid Build Coastguard Worker template <typename Storage, class Allocator = JvmtiAllocator<T>> 196*795d594fSAndroid Build Coastguard Worker struct ReleasableContainer; 197*795d594fSAndroid Build Coastguard Worker 198*795d594fSAndroid Build Coastguard Worker struct HashGcRoot { operatorHashGcRoot199*795d594fSAndroid Build Coastguard Worker size_t operator()(const art::GcRoot<art::mirror::Object>& r) const 200*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) { 201*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<uintptr_t>(r.Read<art::kWithoutReadBarrier>()); 202*795d594fSAndroid Build Coastguard Worker } 203*795d594fSAndroid Build Coastguard Worker }; 204*795d594fSAndroid Build Coastguard Worker 205*795d594fSAndroid Build Coastguard Worker struct EqGcRoot { operatorEqGcRoot206*795d594fSAndroid Build Coastguard Worker bool operator()(const art::GcRoot<art::mirror::Object>& r1, 207*795d594fSAndroid Build Coastguard Worker const art::GcRoot<art::mirror::Object>& r2) const 208*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) { 209*795d594fSAndroid Build Coastguard Worker return r1.Read<art::kWithoutReadBarrier>() == r2.Read<art::kWithoutReadBarrier>(); 210*795d594fSAndroid Build Coastguard Worker } 211*795d594fSAndroid Build Coastguard Worker }; 212*795d594fSAndroid Build Coastguard Worker 213*795d594fSAndroid Build Coastguard Worker using TagAllocator = JvmtiAllocator<std::pair<const art::GcRoot<art::mirror::Object>, T>>; 214*795d594fSAndroid Build Coastguard Worker using TagMap = std::unordered_map<art::GcRoot<art::mirror::Object>, 215*795d594fSAndroid Build Coastguard Worker T, 216*795d594fSAndroid Build Coastguard Worker HashGcRoot, 217*795d594fSAndroid Build Coastguard Worker EqGcRoot, 218*795d594fSAndroid Build Coastguard Worker TagAllocator>; 219*795d594fSAndroid Build Coastguard Worker 220*795d594fSAndroid Build Coastguard Worker TagMap tagged_objects_ GUARDED_BY(allow_disallow_lock_) GUARDED_BY(art::Locks::mutator_lock_); 221*795d594fSAndroid Build Coastguard Worker // To avoid repeatedly scanning the whole table, remember if we did that since the last sweep. 222*795d594fSAndroid Build Coastguard Worker bool update_since_last_sweep_; 223*795d594fSAndroid Build Coastguard Worker }; 224*795d594fSAndroid Build Coastguard Worker 225*795d594fSAndroid Build Coastguard Worker } // namespace openjdkjvmti 226*795d594fSAndroid Build Coastguard Worker 227*795d594fSAndroid Build Coastguard Worker #endif // ART_OPENJDKJVMTI_JVMTI_WEAK_TABLE_H_ 228