1*795d594fSAndroid Build Coastguard Worker /* Copyright (C) 2016 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 #include "ti_redefine.h"
33*795d594fSAndroid Build Coastguard Worker
34*795d594fSAndroid Build Coastguard Worker #include <algorithm>
35*795d594fSAndroid Build Coastguard Worker #include <atomic>
36*795d594fSAndroid Build Coastguard Worker #include <iterator>
37*795d594fSAndroid Build Coastguard Worker #include <limits>
38*795d594fSAndroid Build Coastguard Worker #include <sstream>
39*795d594fSAndroid Build Coastguard Worker #include <string_view>
40*795d594fSAndroid Build Coastguard Worker #include <unordered_map>
41*795d594fSAndroid Build Coastguard Worker
42*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
43*795d594fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
44*795d594fSAndroid Build Coastguard Worker
45*795d594fSAndroid Build Coastguard Worker #include "alloc_manager.h"
46*795d594fSAndroid Build Coastguard Worker #include "android-base/macros.h"
47*795d594fSAndroid Build Coastguard Worker #include "android-base/thread_annotations.h"
48*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
49*795d594fSAndroid Build Coastguard Worker #include "art_field.h"
50*795d594fSAndroid Build Coastguard Worker #include "art_jvmti.h"
51*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
52*795d594fSAndroid Build Coastguard Worker #include "art_method.h"
53*795d594fSAndroid Build Coastguard Worker #include "base/array_ref.h"
54*795d594fSAndroid Build Coastguard Worker #include "base/casts.h"
55*795d594fSAndroid Build Coastguard Worker #include "base/globals.h"
56*795d594fSAndroid Build Coastguard Worker #include "base/iteration_range.h"
57*795d594fSAndroid Build Coastguard Worker #include "base/length_prefixed_array.h"
58*795d594fSAndroid Build Coastguard Worker #include "base/locks.h"
59*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
60*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
61*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
62*795d594fSAndroid Build Coastguard Worker #include "class_linker-inl.h"
63*795d594fSAndroid Build Coastguard Worker #include "class_linker.h"
64*795d594fSAndroid Build Coastguard Worker #include "class_root-inl.h"
65*795d594fSAndroid Build Coastguard Worker #include "class_status.h"
66*795d594fSAndroid Build Coastguard Worker #include "debugger.h"
67*795d594fSAndroid Build Coastguard Worker #include "dex/art_dex_file_loader.h"
68*795d594fSAndroid Build Coastguard Worker #include "dex/class_accessor-inl.h"
69*795d594fSAndroid Build Coastguard Worker #include "dex/class_accessor.h"
70*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
71*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_loader.h"
72*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_types.h"
73*795d594fSAndroid Build Coastguard Worker #include "dex/primitive.h"
74*795d594fSAndroid Build Coastguard Worker #include "dex/signature-inl.h"
75*795d594fSAndroid Build Coastguard Worker #include "dex/signature.h"
76*795d594fSAndroid Build Coastguard Worker #include "events-inl.h"
77*795d594fSAndroid Build Coastguard Worker #include "events.h"
78*795d594fSAndroid Build Coastguard Worker #include "gc/allocation_listener.h"
79*795d594fSAndroid Build Coastguard Worker #include "gc/heap.h"
80*795d594fSAndroid Build Coastguard Worker #include "gc/heap-inl.h"
81*795d594fSAndroid Build Coastguard Worker #include "gc/heap-visit-objects-inl.h"
82*795d594fSAndroid Build Coastguard Worker #include "handle.h"
83*795d594fSAndroid Build Coastguard Worker #include "handle_scope.h"
84*795d594fSAndroid Build Coastguard Worker #include "instrumentation.h"
85*795d594fSAndroid Build Coastguard Worker #include "intern_table.h"
86*795d594fSAndroid Build Coastguard Worker #include "jit/jit.h"
87*795d594fSAndroid Build Coastguard Worker #include "jit/jit_code_cache.h"
88*795d594fSAndroid Build Coastguard Worker #include "jni/jni_env_ext-inl.h"
89*795d594fSAndroid Build Coastguard Worker #include "jni/jni_id_manager.h"
90*795d594fSAndroid Build Coastguard Worker #include "jvmti.h"
91*795d594fSAndroid Build Coastguard Worker #include "jvmti_allocator.h"
92*795d594fSAndroid Build Coastguard Worker #include "linear_alloc-inl.h"
93*795d594fSAndroid Build Coastguard Worker #include "mirror/array-alloc-inl.h"
94*795d594fSAndroid Build Coastguard Worker #include "mirror/array.h"
95*795d594fSAndroid Build Coastguard Worker #include "mirror/class-alloc-inl.h"
96*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
97*795d594fSAndroid Build Coastguard Worker #include "mirror/class-refvisitor-inl.h"
98*795d594fSAndroid Build Coastguard Worker #include "mirror/class.h"
99*795d594fSAndroid Build Coastguard Worker #include "mirror/class_ext-inl.h"
100*795d594fSAndroid Build Coastguard Worker #include "mirror/dex_cache-inl.h"
101*795d594fSAndroid Build Coastguard Worker #include "mirror/dex_cache.h"
102*795d594fSAndroid Build Coastguard Worker #include "mirror/executable-inl.h"
103*795d594fSAndroid Build Coastguard Worker #include "mirror/field-inl.h"
104*795d594fSAndroid Build Coastguard Worker #include "mirror/field.h"
105*795d594fSAndroid Build Coastguard Worker #include "mirror/method.h"
106*795d594fSAndroid Build Coastguard Worker #include "mirror/method_handle_impl-inl.h"
107*795d594fSAndroid Build Coastguard Worker #include "mirror/object.h"
108*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-alloc-inl.h"
109*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
110*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array.h"
111*795d594fSAndroid Build Coastguard Worker #include "mirror/string.h"
112*795d594fSAndroid Build Coastguard Worker #include "mirror/var_handle.h"
113*795d594fSAndroid Build Coastguard Worker #include "nativehelper/scoped_local_ref.h"
114*795d594fSAndroid Build Coastguard Worker #include "non_debuggable_classes.h"
115*795d594fSAndroid Build Coastguard Worker #include "obj_ptr.h"
116*795d594fSAndroid Build Coastguard Worker #include "object_lock.h"
117*795d594fSAndroid Build Coastguard Worker #include "reflective_value_visitor.h"
118*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
119*795d594fSAndroid Build Coastguard Worker #include "runtime_globals.h"
120*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change.h"
121*795d594fSAndroid Build Coastguard Worker #include "stack.h"
122*795d594fSAndroid Build Coastguard Worker #include "thread.h"
123*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
124*795d594fSAndroid Build Coastguard Worker #include "ti_breakpoint.h"
125*795d594fSAndroid Build Coastguard Worker #include "ti_class_definition.h"
126*795d594fSAndroid Build Coastguard Worker #include "ti_class_loader.h"
127*795d594fSAndroid Build Coastguard Worker #include "ti_heap.h"
128*795d594fSAndroid Build Coastguard Worker #include "ti_logging.h"
129*795d594fSAndroid Build Coastguard Worker #include "ti_thread.h"
130*795d594fSAndroid Build Coastguard Worker #include "transform.h"
131*795d594fSAndroid Build Coastguard Worker #include "verifier/class_verifier.h"
132*795d594fSAndroid Build Coastguard Worker #include "verifier/verifier_enums.h"
133*795d594fSAndroid Build Coastguard Worker #include "well_known_classes-inl.h"
134*795d594fSAndroid Build Coastguard Worker #include "write_barrier.h"
135*795d594fSAndroid Build Coastguard Worker
136*795d594fSAndroid Build Coastguard Worker namespace openjdkjvmti {
137*795d594fSAndroid Build Coastguard Worker
138*795d594fSAndroid Build Coastguard Worker // Debug check to force us to directly check we saw all methods and fields exactly once directly.
139*795d594fSAndroid Build Coastguard Worker // Normally we don't need to do this since if any are missing the count will be different
140*795d594fSAndroid Build Coastguard Worker constexpr bool kCheckAllMethodsSeenOnce = art::kIsDebugBuild;
141*795d594fSAndroid Build Coastguard Worker
142*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
143*795d594fSAndroid Build Coastguard Worker
144*795d594fSAndroid Build Coastguard Worker // A helper that fills in a classes obsolete_methods_ and obsolete_dex_caches_ classExt fields as
145*795d594fSAndroid Build Coastguard Worker // they are created. This ensures that we can always call any method of an obsolete ArtMethod object
146*795d594fSAndroid Build Coastguard Worker // almost as soon as they are created since the GetObsoleteDexCache method will succeed.
147*795d594fSAndroid Build Coastguard Worker class ObsoleteMap {
148*795d594fSAndroid Build Coastguard Worker public:
FindObsoleteVersion(art::ArtMethod * original) const149*795d594fSAndroid Build Coastguard Worker art::ArtMethod* FindObsoleteVersion(art::ArtMethod* original) const
150*795d594fSAndroid Build Coastguard Worker REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
151*795d594fSAndroid Build Coastguard Worker auto method_pair = id_map_.find(original);
152*795d594fSAndroid Build Coastguard Worker if (method_pair != id_map_.end()) {
153*795d594fSAndroid Build Coastguard Worker art::ArtMethod* res = obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
154*795d594fSAndroid Build Coastguard Worker method_pair->second, art::kRuntimePointerSize);
155*795d594fSAndroid Build Coastguard Worker DCHECK(res != nullptr);
156*795d594fSAndroid Build Coastguard Worker return res;
157*795d594fSAndroid Build Coastguard Worker } else {
158*795d594fSAndroid Build Coastguard Worker return nullptr;
159*795d594fSAndroid Build Coastguard Worker }
160*795d594fSAndroid Build Coastguard Worker }
161*795d594fSAndroid Build Coastguard Worker
RecordObsolete(art::ArtMethod * original,art::ArtMethod * obsolete)162*795d594fSAndroid Build Coastguard Worker void RecordObsolete(art::ArtMethod* original, art::ArtMethod* obsolete)
163*795d594fSAndroid Build Coastguard Worker REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
164*795d594fSAndroid Build Coastguard Worker DCHECK(original != nullptr);
165*795d594fSAndroid Build Coastguard Worker DCHECK(obsolete != nullptr);
166*795d594fSAndroid Build Coastguard Worker int32_t slot = next_free_slot_++;
167*795d594fSAndroid Build Coastguard Worker DCHECK_LT(slot, obsolete_methods_->GetLength());
168*795d594fSAndroid Build Coastguard Worker DCHECK(nullptr ==
169*795d594fSAndroid Build Coastguard Worker obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(slot, art::kRuntimePointerSize));
170*795d594fSAndroid Build Coastguard Worker DCHECK(nullptr == obsolete_dex_caches_->Get(slot));
171*795d594fSAndroid Build Coastguard Worker obsolete_methods_->SetElementPtrSize(slot, obsolete, art::kRuntimePointerSize);
172*795d594fSAndroid Build Coastguard Worker obsolete_dex_caches_->Set(slot, original_dex_cache_);
173*795d594fSAndroid Build Coastguard Worker id_map_.insert({original, slot});
174*795d594fSAndroid Build Coastguard Worker }
175*795d594fSAndroid Build Coastguard Worker
ObsoleteMap(art::ObjPtr<art::mirror::PointerArray> obsolete_methods,art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> obsolete_dex_caches,art::ObjPtr<art::mirror::DexCache> original_dex_cache)176*795d594fSAndroid Build Coastguard Worker ObsoleteMap(art::ObjPtr<art::mirror::PointerArray> obsolete_methods,
177*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> obsolete_dex_caches,
178*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::DexCache> original_dex_cache)
179*795d594fSAndroid Build Coastguard Worker : next_free_slot_(0),
180*795d594fSAndroid Build Coastguard Worker obsolete_methods_(obsolete_methods),
181*795d594fSAndroid Build Coastguard Worker obsolete_dex_caches_(obsolete_dex_caches),
182*795d594fSAndroid Build Coastguard Worker original_dex_cache_(original_dex_cache) {
183*795d594fSAndroid Build Coastguard Worker // Figure out where the first unused slot in the obsolete_methods_ array is.
184*795d594fSAndroid Build Coastguard Worker while (obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
185*795d594fSAndroid Build Coastguard Worker next_free_slot_, art::kRuntimePointerSize) != nullptr) {
186*795d594fSAndroid Build Coastguard Worker DCHECK(obsolete_dex_caches_->Get(next_free_slot_) != nullptr);
187*795d594fSAndroid Build Coastguard Worker next_free_slot_++;
188*795d594fSAndroid Build Coastguard Worker }
189*795d594fSAndroid Build Coastguard Worker // Check that the same slot in obsolete_dex_caches_ is free.
190*795d594fSAndroid Build Coastguard Worker DCHECK(obsolete_dex_caches_->Get(next_free_slot_) == nullptr);
191*795d594fSAndroid Build Coastguard Worker }
192*795d594fSAndroid Build Coastguard Worker
193*795d594fSAndroid Build Coastguard Worker struct ObsoleteMethodPair {
194*795d594fSAndroid Build Coastguard Worker art::ArtMethod* old_method;
195*795d594fSAndroid Build Coastguard Worker art::ArtMethod* obsolete_method;
196*795d594fSAndroid Build Coastguard Worker };
197*795d594fSAndroid Build Coastguard Worker
198*795d594fSAndroid Build Coastguard Worker class ObsoleteMapIter {
199*795d594fSAndroid Build Coastguard Worker public:
200*795d594fSAndroid Build Coastguard Worker using iterator_category = std::forward_iterator_tag;
201*795d594fSAndroid Build Coastguard Worker using value_type = ObsoleteMethodPair;
202*795d594fSAndroid Build Coastguard Worker using difference_type = ptrdiff_t;
203*795d594fSAndroid Build Coastguard Worker using pointer = void; // Unsupported.
204*795d594fSAndroid Build Coastguard Worker using reference = void; // Unsupported.
205*795d594fSAndroid Build Coastguard Worker
operator *() const206*795d594fSAndroid Build Coastguard Worker ObsoleteMethodPair operator*() const
207*795d594fSAndroid Build Coastguard Worker REQUIRES(art::Locks::mutator_lock_, art::Roles::uninterruptible_) {
208*795d594fSAndroid Build Coastguard Worker art::ArtMethod* obsolete = map_->obsolete_methods_->GetElementPtrSize<art::ArtMethod*>(
209*795d594fSAndroid Build Coastguard Worker iter_->second, art::kRuntimePointerSize);
210*795d594fSAndroid Build Coastguard Worker DCHECK(obsolete != nullptr);
211*795d594fSAndroid Build Coastguard Worker return { iter_->first, obsolete };
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker
operator ==(ObsoleteMapIter other) const214*795d594fSAndroid Build Coastguard Worker bool operator==(ObsoleteMapIter other) const {
215*795d594fSAndroid Build Coastguard Worker return map_ == other.map_ && iter_ == other.iter_;
216*795d594fSAndroid Build Coastguard Worker }
217*795d594fSAndroid Build Coastguard Worker
operator !=(ObsoleteMapIter other) const218*795d594fSAndroid Build Coastguard Worker bool operator!=(ObsoleteMapIter other) const {
219*795d594fSAndroid Build Coastguard Worker return !(*this == other);
220*795d594fSAndroid Build Coastguard Worker }
221*795d594fSAndroid Build Coastguard Worker
operator ++(int)222*795d594fSAndroid Build Coastguard Worker ObsoleteMapIter operator++(int) {
223*795d594fSAndroid Build Coastguard Worker ObsoleteMapIter retval = *this;
224*795d594fSAndroid Build Coastguard Worker ++(*this);
225*795d594fSAndroid Build Coastguard Worker return retval;
226*795d594fSAndroid Build Coastguard Worker }
227*795d594fSAndroid Build Coastguard Worker
operator ++()228*795d594fSAndroid Build Coastguard Worker ObsoleteMapIter operator++() {
229*795d594fSAndroid Build Coastguard Worker ++iter_;
230*795d594fSAndroid Build Coastguard Worker return *this;
231*795d594fSAndroid Build Coastguard Worker }
232*795d594fSAndroid Build Coastguard Worker
233*795d594fSAndroid Build Coastguard Worker private:
ObsoleteMapIter(const ObsoleteMap * map,std::unordered_map<art::ArtMethod *,int32_t>::const_iterator iter)234*795d594fSAndroid Build Coastguard Worker ObsoleteMapIter(const ObsoleteMap* map,
235*795d594fSAndroid Build Coastguard Worker std::unordered_map<art::ArtMethod*, int32_t>::const_iterator iter)
236*795d594fSAndroid Build Coastguard Worker : map_(map), iter_(iter) {}
237*795d594fSAndroid Build Coastguard Worker
238*795d594fSAndroid Build Coastguard Worker const ObsoleteMap* map_;
239*795d594fSAndroid Build Coastguard Worker std::unordered_map<art::ArtMethod*, int32_t>::const_iterator iter_;
240*795d594fSAndroid Build Coastguard Worker
241*795d594fSAndroid Build Coastguard Worker friend class ObsoleteMap;
242*795d594fSAndroid Build Coastguard Worker };
243*795d594fSAndroid Build Coastguard Worker
end() const244*795d594fSAndroid Build Coastguard Worker ObsoleteMapIter end() const {
245*795d594fSAndroid Build Coastguard Worker return ObsoleteMapIter(this, id_map_.cend());
246*795d594fSAndroid Build Coastguard Worker }
247*795d594fSAndroid Build Coastguard Worker
begin() const248*795d594fSAndroid Build Coastguard Worker ObsoleteMapIter begin() const {
249*795d594fSAndroid Build Coastguard Worker return ObsoleteMapIter(this, id_map_.cbegin());
250*795d594fSAndroid Build Coastguard Worker }
251*795d594fSAndroid Build Coastguard Worker
252*795d594fSAndroid Build Coastguard Worker private:
253*795d594fSAndroid Build Coastguard Worker int32_t next_free_slot_;
254*795d594fSAndroid Build Coastguard Worker std::unordered_map<art::ArtMethod*, int32_t> id_map_;
255*795d594fSAndroid Build Coastguard Worker // Pointers to the fields in mirror::ClassExt. These can be held as ObjPtr since this is only used
256*795d594fSAndroid Build Coastguard Worker // when we have an exclusive mutator_lock_ (i.e. all threads are suspended).
257*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::PointerArray> obsolete_methods_;
258*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> obsolete_dex_caches_;
259*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::DexCache> original_dex_cache_;
260*795d594fSAndroid Build Coastguard Worker };
261*795d594fSAndroid Build Coastguard Worker
262*795d594fSAndroid Build Coastguard Worker // This visitor walks thread stacks and allocates and sets up the obsolete methods. It also does
263*795d594fSAndroid Build Coastguard Worker // some basic soundness checks that the obsolete method is valid.
264*795d594fSAndroid Build Coastguard Worker class ObsoleteMethodStackVisitor : public art::StackVisitor {
265*795d594fSAndroid Build Coastguard Worker protected:
ObsoleteMethodStackVisitor(art::Thread * thread,art::LinearAlloc * allocator,const std::unordered_set<art::ArtMethod * > & obsoleted_methods,ObsoleteMap * obsolete_maps)266*795d594fSAndroid Build Coastguard Worker ObsoleteMethodStackVisitor(
267*795d594fSAndroid Build Coastguard Worker art::Thread* thread,
268*795d594fSAndroid Build Coastguard Worker art::LinearAlloc* allocator,
269*795d594fSAndroid Build Coastguard Worker const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
270*795d594fSAndroid Build Coastguard Worker ObsoleteMap* obsolete_maps)
271*795d594fSAndroid Build Coastguard Worker : StackVisitor(thread,
272*795d594fSAndroid Build Coastguard Worker /*context=*/nullptr,
273*795d594fSAndroid Build Coastguard Worker StackVisitor::StackWalkKind::kIncludeInlinedFrames),
274*795d594fSAndroid Build Coastguard Worker allocator_(allocator),
275*795d594fSAndroid Build Coastguard Worker obsoleted_methods_(obsoleted_methods),
276*795d594fSAndroid Build Coastguard Worker obsolete_maps_(obsolete_maps) { }
277*795d594fSAndroid Build Coastguard Worker
~ObsoleteMethodStackVisitor()278*795d594fSAndroid Build Coastguard Worker ~ObsoleteMethodStackVisitor() override {}
279*795d594fSAndroid Build Coastguard Worker
280*795d594fSAndroid Build Coastguard Worker public:
281*795d594fSAndroid Build Coastguard Worker // Returns true if we successfully installed obsolete methods on this thread, filling
282*795d594fSAndroid Build Coastguard Worker // obsolete_maps_ with the translations if needed. Returns false and fills error_msg if we fail.
283*795d594fSAndroid Build Coastguard Worker // The stack is cleaned up when we fail.
UpdateObsoleteFrames(art::Thread * thread,art::LinearAlloc * allocator,const std::unordered_set<art::ArtMethod * > & obsoleted_methods,ObsoleteMap * obsolete_maps)284*795d594fSAndroid Build Coastguard Worker static void UpdateObsoleteFrames(
285*795d594fSAndroid Build Coastguard Worker art::Thread* thread,
286*795d594fSAndroid Build Coastguard Worker art::LinearAlloc* allocator,
287*795d594fSAndroid Build Coastguard Worker const std::unordered_set<art::ArtMethod*>& obsoleted_methods,
288*795d594fSAndroid Build Coastguard Worker ObsoleteMap* obsolete_maps) REQUIRES(art::Locks::mutator_lock_) {
289*795d594fSAndroid Build Coastguard Worker ObsoleteMethodStackVisitor visitor(thread,
290*795d594fSAndroid Build Coastguard Worker allocator,
291*795d594fSAndroid Build Coastguard Worker obsoleted_methods,
292*795d594fSAndroid Build Coastguard Worker obsolete_maps);
293*795d594fSAndroid Build Coastguard Worker visitor.WalkStack();
294*795d594fSAndroid Build Coastguard Worker }
295*795d594fSAndroid Build Coastguard Worker
VisitFrame()296*795d594fSAndroid Build Coastguard Worker bool VisitFrame() override REQUIRES(art::Locks::mutator_lock_) {
297*795d594fSAndroid Build Coastguard Worker art::ScopedAssertNoThreadSuspension snts("Fixing up the stack for obsolete methods.");
298*795d594fSAndroid Build Coastguard Worker art::ArtMethod* old_method = GetMethod();
299*795d594fSAndroid Build Coastguard Worker if (obsoleted_methods_.find(old_method) != obsoleted_methods_.end()) {
300*795d594fSAndroid Build Coastguard Worker // We cannot ensure that the right dex file is used in inlined frames so we don't support
301*795d594fSAndroid Build Coastguard Worker // redefining them.
302*795d594fSAndroid Build Coastguard Worker DCHECK(!IsInInlinedFrame()) << "Inlined frames are not supported when using redefinition: "
303*795d594fSAndroid Build Coastguard Worker << old_method->PrettyMethod() << " is inlined into "
304*795d594fSAndroid Build Coastguard Worker << GetOuterMethod()->PrettyMethod();
305*795d594fSAndroid Build Coastguard Worker art::ArtMethod* new_obsolete_method = obsolete_maps_->FindObsoleteVersion(old_method);
306*795d594fSAndroid Build Coastguard Worker if (new_obsolete_method == nullptr) {
307*795d594fSAndroid Build Coastguard Worker // Create a new Obsolete Method and put it in the list.
308*795d594fSAndroid Build Coastguard Worker art::Runtime* runtime = art::Runtime::Current();
309*795d594fSAndroid Build Coastguard Worker art::ClassLinker* cl = runtime->GetClassLinker();
310*795d594fSAndroid Build Coastguard Worker auto ptr_size = cl->GetImagePointerSize();
311*795d594fSAndroid Build Coastguard Worker const size_t method_size = art::ArtMethod::Size(ptr_size);
312*795d594fSAndroid Build Coastguard Worker auto* method_storage = allocator_->Alloc(art::Thread::Current(),
313*795d594fSAndroid Build Coastguard Worker method_size,
314*795d594fSAndroid Build Coastguard Worker art::LinearAllocKind::kArtMethod);
315*795d594fSAndroid Build Coastguard Worker CHECK(method_storage != nullptr) << "Unable to allocate storage for obsolete version of '"
316*795d594fSAndroid Build Coastguard Worker << old_method->PrettyMethod() << "'";
317*795d594fSAndroid Build Coastguard Worker new_obsolete_method = new (method_storage) art::ArtMethod();
318*795d594fSAndroid Build Coastguard Worker new_obsolete_method->CopyFrom(old_method, ptr_size);
319*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(new_obsolete_method->GetDeclaringClass(), old_method->GetDeclaringClass());
320*795d594fSAndroid Build Coastguard Worker new_obsolete_method->SetIsObsolete();
321*795d594fSAndroid Build Coastguard Worker new_obsolete_method->SetDontCompile();
322*795d594fSAndroid Build Coastguard Worker cl->SetEntryPointsForObsoleteMethod(new_obsolete_method);
323*795d594fSAndroid Build Coastguard Worker obsolete_maps_->RecordObsolete(old_method, new_obsolete_method);
324*795d594fSAndroid Build Coastguard Worker }
325*795d594fSAndroid Build Coastguard Worker DCHECK(new_obsolete_method != nullptr);
326*795d594fSAndroid Build Coastguard Worker SetMethod(new_obsolete_method);
327*795d594fSAndroid Build Coastguard Worker }
328*795d594fSAndroid Build Coastguard Worker return true;
329*795d594fSAndroid Build Coastguard Worker }
330*795d594fSAndroid Build Coastguard Worker
331*795d594fSAndroid Build Coastguard Worker private:
332*795d594fSAndroid Build Coastguard Worker // The linear allocator we should use to make new methods.
333*795d594fSAndroid Build Coastguard Worker art::LinearAlloc* allocator_;
334*795d594fSAndroid Build Coastguard Worker // The set of all methods which could be obsoleted.
335*795d594fSAndroid Build Coastguard Worker const std::unordered_set<art::ArtMethod*>& obsoleted_methods_;
336*795d594fSAndroid Build Coastguard Worker // A map from the original to the newly allocated obsolete method for frames on this thread. The
337*795d594fSAndroid Build Coastguard Worker // values in this map are added to the obsolete_methods_ (and obsolete_dex_caches_) fields of
338*795d594fSAndroid Build Coastguard Worker // the redefined classes ClassExt as it is filled.
339*795d594fSAndroid Build Coastguard Worker ObsoleteMap* obsolete_maps_;
340*795d594fSAndroid Build Coastguard Worker };
341*795d594fSAndroid Build Coastguard Worker
342*795d594fSAndroid Build Coastguard Worker namespace {
343*795d594fSAndroid Build Coastguard Worker // We need to make sure we only have one redefinition in progress. Redefining involves
344*795d594fSAndroid Build Coastguard Worker // re-verification and potentially new allocations among other things. So we only allow one
345*795d594fSAndroid Build Coastguard Worker // redefinition at a time.
346*795d594fSAndroid Build Coastguard Worker static std::mutex redefinition_lock;
347*795d594fSAndroid Build Coastguard Worker } // namespace
348*795d594fSAndroid Build Coastguard Worker
349*795d594fSAndroid Build Coastguard Worker template <RedefinitionType kType>
350*795d594fSAndroid Build Coastguard Worker jvmtiError
IsModifiableClassGeneric(jvmtiEnv * env,jclass klass,jboolean * is_redefinable)351*795d594fSAndroid Build Coastguard Worker Redefiner::IsModifiableClassGeneric(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
352*795d594fSAndroid Build Coastguard Worker if (env == nullptr) {
353*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_ENVIRONMENT);
354*795d594fSAndroid Build Coastguard Worker }
355*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
356*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
357*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<1> hs(self);
358*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> obj(self->DecodeJObject(klass));
359*795d594fSAndroid Build Coastguard Worker if (obj.IsNull() || !obj->IsClass()) {
360*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS);
361*795d594fSAndroid Build Coastguard Worker }
362*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> h_klass(hs.NewHandle(obj->AsClass()));
363*795d594fSAndroid Build Coastguard Worker std::string err_unused;
364*795d594fSAndroid Build Coastguard Worker *is_redefinable =
365*795d594fSAndroid Build Coastguard Worker Redefiner::CanRedefineClass<kType>(h_klass, &err_unused) != ERR(UNMODIFIABLE_CLASS)
366*795d594fSAndroid Build Coastguard Worker ? JNI_TRUE
367*795d594fSAndroid Build Coastguard Worker : JNI_FALSE;
368*795d594fSAndroid Build Coastguard Worker return OK;
369*795d594fSAndroid Build Coastguard Worker }
370*795d594fSAndroid Build Coastguard Worker
371*795d594fSAndroid Build Coastguard Worker jvmtiError
IsStructurallyModifiableClass(jvmtiEnv * env,jclass klass,jboolean * is_redefinable)372*795d594fSAndroid Build Coastguard Worker Redefiner::IsStructurallyModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
373*795d594fSAndroid Build Coastguard Worker return Redefiner::IsModifiableClassGeneric<RedefinitionType::kStructural>(
374*795d594fSAndroid Build Coastguard Worker env, klass, is_redefinable);
375*795d594fSAndroid Build Coastguard Worker }
376*795d594fSAndroid Build Coastguard Worker
IsModifiableClass(jvmtiEnv * env,jclass klass,jboolean * is_redefinable)377*795d594fSAndroid Build Coastguard Worker jvmtiError Redefiner::IsModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_redefinable) {
378*795d594fSAndroid Build Coastguard Worker return Redefiner::IsModifiableClassGeneric<RedefinitionType::kNormal>(env, klass, is_redefinable);
379*795d594fSAndroid Build Coastguard Worker }
380*795d594fSAndroid Build Coastguard Worker
381*795d594fSAndroid Build Coastguard Worker template <RedefinitionType kType>
CanRedefineClass(jclass klass,std::string * error_msg)382*795d594fSAndroid Build Coastguard Worker jvmtiError Redefiner::CanRedefineClass(jclass klass, /*out*/ std::string* error_msg) {
383*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
384*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
385*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<1> hs(self);
386*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> obj(self->DecodeJObject(klass));
387*795d594fSAndroid Build Coastguard Worker if (obj.IsNull() || !obj->IsClass()) {
388*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS);
389*795d594fSAndroid Build Coastguard Worker }
390*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> h_klass(hs.NewHandle(obj->AsClass()));
391*795d594fSAndroid Build Coastguard Worker return Redefiner::CanRedefineClass<kType>(h_klass, error_msg);
392*795d594fSAndroid Build Coastguard Worker }
393*795d594fSAndroid Build Coastguard Worker
394*795d594fSAndroid Build Coastguard Worker template <RedefinitionType kType>
CanRedefineClass(art::Handle<art::mirror::Class> klass,std::string * error_msg)395*795d594fSAndroid Build Coastguard Worker jvmtiError Redefiner::CanRedefineClass(art::Handle<art::mirror::Class> klass,
396*795d594fSAndroid Build Coastguard Worker /*out*/ std::string* error_msg) {
397*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
398*795d594fSAndroid Build Coastguard Worker if (!klass->IsResolved()) {
399*795d594fSAndroid Build Coastguard Worker // It's only a problem to try to retransform/redefine a unprepared class if it's happening on
400*795d594fSAndroid Build Coastguard Worker // the same thread as the class-linking process. If it's on another thread we will be able to
401*795d594fSAndroid Build Coastguard Worker // wait for the preparation to finish and continue from there.
402*795d594fSAndroid Build Coastguard Worker if (klass->GetLockOwnerThreadId() == self->GetThreadId()) {
403*795d594fSAndroid Build Coastguard Worker *error_msg = "Modification of class " + klass->PrettyClass() +
404*795d594fSAndroid Build Coastguard Worker " from within the classes ClassLoad callback is not supported to prevent deadlocks." +
405*795d594fSAndroid Build Coastguard Worker " Please use ClassFileLoadHook directly instead.";
406*795d594fSAndroid Build Coastguard Worker return ERR(INTERNAL);
407*795d594fSAndroid Build Coastguard Worker } else {
408*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << klass->PrettyClass() << " is not yet resolved. Attempting to transform "
409*795d594fSAndroid Build Coastguard Worker << "it could cause arbitrary length waits as the class is being resolved.";
410*795d594fSAndroid Build Coastguard Worker }
411*795d594fSAndroid Build Coastguard Worker }
412*795d594fSAndroid Build Coastguard Worker if (klass->IsPrimitive()) {
413*795d594fSAndroid Build Coastguard Worker *error_msg = "Modification of primitive classes is not supported";
414*795d594fSAndroid Build Coastguard Worker return ERR(UNMODIFIABLE_CLASS);
415*795d594fSAndroid Build Coastguard Worker } else if (klass->IsInterface()) {
416*795d594fSAndroid Build Coastguard Worker *error_msg = "Modification of Interface classes is currently not supported";
417*795d594fSAndroid Build Coastguard Worker return ERR(UNMODIFIABLE_CLASS);
418*795d594fSAndroid Build Coastguard Worker } else if (klass->IsStringClass()) {
419*795d594fSAndroid Build Coastguard Worker *error_msg = "Modification of String class is not supported";
420*795d594fSAndroid Build Coastguard Worker return ERR(UNMODIFIABLE_CLASS);
421*795d594fSAndroid Build Coastguard Worker } else if (klass->IsArrayClass()) {
422*795d594fSAndroid Build Coastguard Worker *error_msg = "Modification of Array classes is not supported";
423*795d594fSAndroid Build Coastguard Worker return ERR(UNMODIFIABLE_CLASS);
424*795d594fSAndroid Build Coastguard Worker } else if (klass->IsProxyClass()) {
425*795d594fSAndroid Build Coastguard Worker *error_msg = "Modification of proxy classes is not supported";
426*795d594fSAndroid Build Coastguard Worker return ERR(UNMODIFIABLE_CLASS);
427*795d594fSAndroid Build Coastguard Worker }
428*795d594fSAndroid Build Coastguard Worker
429*795d594fSAndroid Build Coastguard Worker for (jclass c : art::NonDebuggableClasses::GetNonDebuggableClasses()) {
430*795d594fSAndroid Build Coastguard Worker if (klass.Get() == self->DecodeJObject(c)->AsClass()) {
431*795d594fSAndroid Build Coastguard Worker *error_msg = "Class might have stack frames that cannot be made obsolete";
432*795d594fSAndroid Build Coastguard Worker return ERR(UNMODIFIABLE_CLASS);
433*795d594fSAndroid Build Coastguard Worker }
434*795d594fSAndroid Build Coastguard Worker }
435*795d594fSAndroid Build Coastguard Worker
436*795d594fSAndroid Build Coastguard Worker if (kType == RedefinitionType::kStructural) {
437*795d594fSAndroid Build Coastguard Worker // Class initialization interacts really badly with structural redefinition since we need to
438*795d594fSAndroid Build Coastguard Worker // make the old class obsolete. We currently just blanket don't allow it.
439*795d594fSAndroid Build Coastguard Worker // TODO It might be nice to allow this at some point.
440*795d594fSAndroid Build Coastguard Worker if (klass->IsInitializing() &&
441*795d594fSAndroid Build Coastguard Worker !klass->IsInitialized() &&
442*795d594fSAndroid Build Coastguard Worker klass->GetClinitThreadId() == self->GetTid()) {
443*795d594fSAndroid Build Coastguard Worker // We are in the class-init running on this thread.
444*795d594fSAndroid Build Coastguard Worker *error_msg = "Modification of class " + klass->PrettyClass() + " during class" +
445*795d594fSAndroid Build Coastguard Worker " initialization is not allowed.";
446*795d594fSAndroid Build Coastguard Worker return ERR(INTERNAL);
447*795d594fSAndroid Build Coastguard Worker }
448*795d594fSAndroid Build Coastguard Worker if (!art::Runtime::Current()->GetClassLinker()->EnsureInitialized(
449*795d594fSAndroid Build Coastguard Worker self, klass, /*can_init_fields=*/true, /*can_init_parents=*/true)) {
450*795d594fSAndroid Build Coastguard Worker self->AssertPendingException();
451*795d594fSAndroid Build Coastguard Worker *error_msg = "Class " + klass->PrettyClass() + " failed initialization. Structural" +
452*795d594fSAndroid Build Coastguard Worker " redefinition of erroneous classes is not allowed. Failure was: " +
453*795d594fSAndroid Build Coastguard Worker self->GetException()->Dump();
454*795d594fSAndroid Build Coastguard Worker self->ClearException();
455*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS);
456*795d594fSAndroid Build Coastguard Worker }
457*795d594fSAndroid Build Coastguard Worker if (klass->IsMirrored()) {
458*795d594fSAndroid Build Coastguard Worker std::string pc(klass->PrettyClass());
459*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf("Class %s is a mirror class and cannot be structurally redefined.",
460*795d594fSAndroid Build Coastguard Worker pc.c_str());
461*795d594fSAndroid Build Coastguard Worker return ERR(UNMODIFIABLE_CLASS);
462*795d594fSAndroid Build Coastguard Worker }
463*795d594fSAndroid Build Coastguard Worker // Check Thread specifically since it's not a root but too many things reach into it with Unsafe
464*795d594fSAndroid Build Coastguard Worker // too allow structural redefinition.
465*795d594fSAndroid Build Coastguard Worker if (klass->IsAssignableFrom(art::WellKnownClasses::java_lang_Thread.Get())) {
466*795d594fSAndroid Build Coastguard Worker *error_msg =
467*795d594fSAndroid Build Coastguard Worker "java.lang.Thread has fields accessed using sun.misc.unsafe directly. It is not "
468*795d594fSAndroid Build Coastguard Worker "safe to structurally redefine it.";
469*795d594fSAndroid Build Coastguard Worker return ERR(UNMODIFIABLE_CLASS);
470*795d594fSAndroid Build Coastguard Worker }
471*795d594fSAndroid Build Coastguard Worker auto has_pointer_marker =
472*795d594fSAndroid Build Coastguard Worker [](art::ObjPtr<art::mirror::Class> k) REQUIRES_SHARED(art::Locks::mutator_lock_) {
473*795d594fSAndroid Build Coastguard Worker // Check for fields/methods which were returned before moving to index jni id type.
474*795d594fSAndroid Build Coastguard Worker // TODO We might want to rework how this is done. Once full redefinition is implemented we
475*795d594fSAndroid Build Coastguard Worker // will need to check any subtypes too.
476*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ClassExt> ext(k->GetExtData());
477*795d594fSAndroid Build Coastguard Worker if (!ext.IsNull()) {
478*795d594fSAndroid Build Coastguard Worker if (ext->HasInstanceFieldPointerIdMarker() || ext->HasMethodPointerIdMarker() ||
479*795d594fSAndroid Build Coastguard Worker ext->HasStaticFieldPointerIdMarker()) {
480*795d594fSAndroid Build Coastguard Worker return true;
481*795d594fSAndroid Build Coastguard Worker }
482*795d594fSAndroid Build Coastguard Worker }
483*795d594fSAndroid Build Coastguard Worker return false;
484*795d594fSAndroid Build Coastguard Worker };
485*795d594fSAndroid Build Coastguard Worker if (has_pointer_marker(klass.Get())) {
486*795d594fSAndroid Build Coastguard Worker *error_msg =
487*795d594fSAndroid Build Coastguard Worker StringPrintf("%s has active pointer jni-ids and cannot be redefined structurally",
488*795d594fSAndroid Build Coastguard Worker klass->PrettyClass().c_str());
489*795d594fSAndroid Build Coastguard Worker return ERR(UNMODIFIABLE_CLASS);
490*795d594fSAndroid Build Coastguard Worker }
491*795d594fSAndroid Build Coastguard Worker jvmtiError res = OK;
492*795d594fSAndroid Build Coastguard Worker art::ClassFuncVisitor cfv(
493*795d594fSAndroid Build Coastguard Worker [&](art::ObjPtr<art::mirror::Class> k) REQUIRES_SHARED(art::Locks::mutator_lock_) {
494*795d594fSAndroid Build Coastguard Worker // if there is any class 'K' that is a subtype (i.e. extends) klass and has pointer-jni-ids
495*795d594fSAndroid Build Coastguard Worker // we cannot structurally redefine the class 'k' since we would structurally redefine the
496*795d594fSAndroid Build Coastguard Worker // subtype.
497*795d594fSAndroid Build Coastguard Worker if (k->IsLoaded() && klass->IsAssignableFrom(k) && has_pointer_marker(k)) {
498*795d594fSAndroid Build Coastguard Worker *error_msg = StringPrintf(
499*795d594fSAndroid Build Coastguard Worker "%s has active pointer jni-ids from subtype %s and cannot be redefined structurally",
500*795d594fSAndroid Build Coastguard Worker klass->PrettyClass().c_str(),
501*795d594fSAndroid Build Coastguard Worker k->PrettyClass().c_str());
502*795d594fSAndroid Build Coastguard Worker res = ERR(UNMODIFIABLE_CLASS);
503*795d594fSAndroid Build Coastguard Worker return false;
504*795d594fSAndroid Build Coastguard Worker }
505*795d594fSAndroid Build Coastguard Worker return true;
506*795d594fSAndroid Build Coastguard Worker });
507*795d594fSAndroid Build Coastguard Worker art::Runtime::Current()->GetClassLinker()->VisitClasses(&cfv);
508*795d594fSAndroid Build Coastguard Worker return res;
509*795d594fSAndroid Build Coastguard Worker }
510*795d594fSAndroid Build Coastguard Worker return OK;
511*795d594fSAndroid Build Coastguard Worker }
512*795d594fSAndroid Build Coastguard Worker
513*795d594fSAndroid Build Coastguard Worker template jvmtiError Redefiner::CanRedefineClass<RedefinitionType::kNormal>(
514*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> klass, /*out*/ std::string* error_msg);
515*795d594fSAndroid Build Coastguard Worker template jvmtiError Redefiner::CanRedefineClass<RedefinitionType::kStructural>(
516*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> klass, /*out*/ std::string* error_msg);
517*795d594fSAndroid Build Coastguard Worker
518*795d594fSAndroid Build Coastguard Worker // Moves dex data to an anonymous, read-only mmap'd region.
MoveDataToMemMap(const std::string & original_location,art::ArrayRef<const unsigned char> data,std::string * error_msg)519*795d594fSAndroid Build Coastguard Worker art::MemMap Redefiner::MoveDataToMemMap(const std::string& original_location,
520*795d594fSAndroid Build Coastguard Worker art::ArrayRef<const unsigned char> data,
521*795d594fSAndroid Build Coastguard Worker std::string* error_msg) {
522*795d594fSAndroid Build Coastguard Worker std::string modified_location = StringPrintf("%s-transformed", original_location.c_str());
523*795d594fSAndroid Build Coastguard Worker // A dangling multi-dex location appended to bootclasspath can cause inaccuracy in oat file
524*795d594fSAndroid Build Coastguard Worker // validation. For simplicity, just convert it to a normal location.
525*795d594fSAndroid Build Coastguard Worker size_t pos = modified_location.find(art::DexFileLoader::kMultiDexSeparator);
526*795d594fSAndroid Build Coastguard Worker if (pos != std::string::npos) {
527*795d594fSAndroid Build Coastguard Worker modified_location[pos] = '-';
528*795d594fSAndroid Build Coastguard Worker }
529*795d594fSAndroid Build Coastguard Worker art::MemMap map = art::MemMap::MapAnonymous(
530*795d594fSAndroid Build Coastguard Worker modified_location.c_str(),
531*795d594fSAndroid Build Coastguard Worker data.size(),
532*795d594fSAndroid Build Coastguard Worker PROT_READ|PROT_WRITE,
533*795d594fSAndroid Build Coastguard Worker /*low_4gb=*/ false,
534*795d594fSAndroid Build Coastguard Worker error_msg);
535*795d594fSAndroid Build Coastguard Worker if (LIKELY(map.IsValid())) {
536*795d594fSAndroid Build Coastguard Worker memcpy(map.Begin(), data.data(), data.size());
537*795d594fSAndroid Build Coastguard Worker // Make the dex files mmap read only. This matches how other DexFiles are mmaped and prevents
538*795d594fSAndroid Build Coastguard Worker // programs from corrupting it.
539*795d594fSAndroid Build Coastguard Worker map.Protect(PROT_READ);
540*795d594fSAndroid Build Coastguard Worker }
541*795d594fSAndroid Build Coastguard Worker return map;
542*795d594fSAndroid Build Coastguard Worker }
543*795d594fSAndroid Build Coastguard Worker
ClassRedefinition(Redefiner * driver,jclass klass,const art::DexFile * redefined_dex_file,const char * class_sig,art::ArrayRef<const unsigned char> orig_dex_file)544*795d594fSAndroid Build Coastguard Worker Redefiner::ClassRedefinition::ClassRedefinition(
545*795d594fSAndroid Build Coastguard Worker Redefiner* driver,
546*795d594fSAndroid Build Coastguard Worker jclass klass,
547*795d594fSAndroid Build Coastguard Worker const art::DexFile* redefined_dex_file,
548*795d594fSAndroid Build Coastguard Worker const char* class_sig,
549*795d594fSAndroid Build Coastguard Worker art::ArrayRef<const unsigned char> orig_dex_file) :
550*795d594fSAndroid Build Coastguard Worker driver_(driver),
551*795d594fSAndroid Build Coastguard Worker klass_(klass),
552*795d594fSAndroid Build Coastguard Worker dex_file_(redefined_dex_file),
553*795d594fSAndroid Build Coastguard Worker class_sig_(class_sig),
554*795d594fSAndroid Build Coastguard Worker original_dex_file_(orig_dex_file) {
555*795d594fSAndroid Build Coastguard Worker }
556*795d594fSAndroid Build Coastguard Worker
~ClassRedefinition()557*795d594fSAndroid Build Coastguard Worker Redefiner::ClassRedefinition::~ClassRedefinition() {
558*795d594fSAndroid Build Coastguard Worker if (art::kIsDebugBuild) {
559*795d594fSAndroid Build Coastguard Worker if (dex_file_ != nullptr) {
560*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
561*795d594fSAndroid Build Coastguard Worker art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
562*795d594fSAndroid Build Coastguard Worker CHECK(!cl->IsDexFileRegistered(self, *dex_file_));
563*795d594fSAndroid Build Coastguard Worker }
564*795d594fSAndroid Build Coastguard Worker }
565*795d594fSAndroid Build Coastguard Worker }
566*795d594fSAndroid Build Coastguard Worker
567*795d594fSAndroid Build Coastguard Worker template<RedefinitionType kType>
RedefineClassesGeneric(jvmtiEnv * jenv,jint class_count,const jvmtiClassDefinition * definitions)568*795d594fSAndroid Build Coastguard Worker jvmtiError Redefiner::RedefineClassesGeneric(jvmtiEnv* jenv,
569*795d594fSAndroid Build Coastguard Worker jint class_count,
570*795d594fSAndroid Build Coastguard Worker const jvmtiClassDefinition* definitions) {
571*795d594fSAndroid Build Coastguard Worker art::Runtime* runtime = art::Runtime::Current();
572*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
573*795d594fSAndroid Build Coastguard Worker ArtJvmTiEnv* env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
574*795d594fSAndroid Build Coastguard Worker if (env == nullptr) {
575*795d594fSAndroid Build Coastguard Worker JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE env was null!";
576*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_ENVIRONMENT);
577*795d594fSAndroid Build Coastguard Worker } else if (class_count < 0) {
578*795d594fSAndroid Build Coastguard Worker JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE class_count was less then 0";
579*795d594fSAndroid Build Coastguard Worker return ERR(ILLEGAL_ARGUMENT);
580*795d594fSAndroid Build Coastguard Worker } else if (class_count == 0) {
581*795d594fSAndroid Build Coastguard Worker // We don't actually need to do anything. Just return OK.
582*795d594fSAndroid Build Coastguard Worker return OK;
583*795d594fSAndroid Build Coastguard Worker } else if (definitions == nullptr) {
584*795d594fSAndroid Build Coastguard Worker JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE null definitions!";
585*795d594fSAndroid Build Coastguard Worker return ERR(NULL_POINTER);
586*795d594fSAndroid Build Coastguard Worker }
587*795d594fSAndroid Build Coastguard Worker std::string error_msg;
588*795d594fSAndroid Build Coastguard Worker std::vector<ArtClassDefinition> def_vector;
589*795d594fSAndroid Build Coastguard Worker def_vector.reserve(class_count);
590*795d594fSAndroid Build Coastguard Worker for (jint i = 0; i < class_count; i++) {
591*795d594fSAndroid Build Coastguard Worker jvmtiError res =
592*795d594fSAndroid Build Coastguard Worker Redefiner::CanRedefineClass<RedefinitionType::kNormal>(definitions[i].klass, &error_msg);
593*795d594fSAndroid Build Coastguard Worker if (res != OK) {
594*795d594fSAndroid Build Coastguard Worker JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE " << error_msg;
595*795d594fSAndroid Build Coastguard Worker return res;
596*795d594fSAndroid Build Coastguard Worker }
597*795d594fSAndroid Build Coastguard Worker ArtClassDefinition def;
598*795d594fSAndroid Build Coastguard Worker res = def.Init(self, definitions[i]);
599*795d594fSAndroid Build Coastguard Worker if (res != OK) {
600*795d594fSAndroid Build Coastguard Worker JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE bad definition " << i;
601*795d594fSAndroid Build Coastguard Worker return res;
602*795d594fSAndroid Build Coastguard Worker }
603*795d594fSAndroid Build Coastguard Worker def_vector.push_back(std::move(def));
604*795d594fSAndroid Build Coastguard Worker }
605*795d594fSAndroid Build Coastguard Worker
606*795d594fSAndroid Build Coastguard Worker // Call necessary hooks. According to the spec we should send class file load hooks here. We
607*795d594fSAndroid Build Coastguard Worker // handle it slightly differently to support structural redefinition. Look at the comments
608*795d594fSAndroid Build Coastguard Worker // in Transformer::CallClassFileLoadHooks for more details.
609*795d594fSAndroid Build Coastguard Worker Transformer::CallClassFileLoadHooks<kType>(self, &def_vector);
610*795d594fSAndroid Build Coastguard Worker
611*795d594fSAndroid Build Coastguard Worker jvmtiError res = RedefineClassesDirect(env, runtime, self, def_vector, kType, &error_msg);
612*795d594fSAndroid Build Coastguard Worker if (res != OK) {
613*795d594fSAndroid Build Coastguard Worker JVMTI_LOG(WARNING, env) << "FAILURE TO REDEFINE " << error_msg;
614*795d594fSAndroid Build Coastguard Worker }
615*795d594fSAndroid Build Coastguard Worker return res;
616*795d594fSAndroid Build Coastguard Worker }
617*795d594fSAndroid Build Coastguard Worker
StructurallyRedefineClasses(jvmtiEnv * jenv,jint class_count,const jvmtiClassDefinition * definitions)618*795d594fSAndroid Build Coastguard Worker jvmtiError Redefiner::StructurallyRedefineClasses(jvmtiEnv* jenv,
619*795d594fSAndroid Build Coastguard Worker jint class_count,
620*795d594fSAndroid Build Coastguard Worker const jvmtiClassDefinition* definitions) {
621*795d594fSAndroid Build Coastguard Worker ArtJvmTiEnv* art_env = ArtJvmTiEnv::AsArtJvmTiEnv(jenv);
622*795d594fSAndroid Build Coastguard Worker if (art_env == nullptr) {
623*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_ENVIRONMENT);
624*795d594fSAndroid Build Coastguard Worker } else if (art_env->capabilities.can_redefine_classes != 1) {
625*795d594fSAndroid Build Coastguard Worker return ERR(MUST_POSSESS_CAPABILITY);
626*795d594fSAndroid Build Coastguard Worker }
627*795d594fSAndroid Build Coastguard Worker return RedefineClassesGeneric<RedefinitionType::kStructural>(jenv, class_count, definitions);
628*795d594fSAndroid Build Coastguard Worker }
629*795d594fSAndroid Build Coastguard Worker
RedefineClasses(jvmtiEnv * jenv,jint class_count,const jvmtiClassDefinition * definitions)630*795d594fSAndroid Build Coastguard Worker jvmtiError Redefiner::RedefineClasses(jvmtiEnv* jenv,
631*795d594fSAndroid Build Coastguard Worker jint class_count,
632*795d594fSAndroid Build Coastguard Worker const jvmtiClassDefinition* definitions) {
633*795d594fSAndroid Build Coastguard Worker return RedefineClassesGeneric<RedefinitionType::kNormal>(jenv, class_count, definitions);
634*795d594fSAndroid Build Coastguard Worker }
635*795d594fSAndroid Build Coastguard Worker
RedefineClassesDirect(ArtJvmTiEnv * env,art::Runtime * runtime,art::Thread * self,const std::vector<ArtClassDefinition> & definitions,RedefinitionType type,std::string * error_msg)636*795d594fSAndroid Build Coastguard Worker jvmtiError Redefiner::RedefineClassesDirect(ArtJvmTiEnv* env,
637*795d594fSAndroid Build Coastguard Worker art::Runtime* runtime,
638*795d594fSAndroid Build Coastguard Worker art::Thread* self,
639*795d594fSAndroid Build Coastguard Worker const std::vector<ArtClassDefinition>& definitions,
640*795d594fSAndroid Build Coastguard Worker RedefinitionType type,
641*795d594fSAndroid Build Coastguard Worker std::string* error_msg) {
642*795d594fSAndroid Build Coastguard Worker DCHECK(env != nullptr);
643*795d594fSAndroid Build Coastguard Worker if (definitions.size() == 0) {
644*795d594fSAndroid Build Coastguard Worker // We don't actually need to do anything. Just return OK.
645*795d594fSAndroid Build Coastguard Worker return OK;
646*795d594fSAndroid Build Coastguard Worker }
647*795d594fSAndroid Build Coastguard Worker
648*795d594fSAndroid Build Coastguard Worker // Take a lock to avoid any concurrent redefinitions.
649*795d594fSAndroid Build Coastguard Worker // TODO(mythria): It is hard to reason that it is safe to hold locks here. It is probably okay,
650*795d594fSAndroid Build Coastguard Worker // since the thread is suspended and we know the thread isn't in the middle of allocations. The
651*795d594fSAndroid Build Coastguard Worker // current implementation of redefinition is prone to deadlocks. For example, we pause allocations
652*795d594fSAndroid Build Coastguard Worker // and then allocate new objects which could trigger a GC. This is unsafe. See b/359829378 for
653*795d594fSAndroid Build Coastguard Worker // more details. Ideally we should rework the code so that:
654*795d594fSAndroid Build Coastguard Worker // 1. Estimate the size required for the new allocations
655*795d594fSAndroid Build Coastguard Worker // 2. Ensure we have the required space
656*795d594fSAndroid Build Coastguard Worker // 3. Acquire any locks required (this would also include the lock to prevent
657*795d594fSAndroid Build Coastguard Worker // concurrent redefinitions)
658*795d594fSAndroid Build Coastguard Worker // 3. SuspendAll the threads
659*795d594fSAndroid Build Coastguard Worker // 4. If the estimated size is no longer sufficient - retry from 1.
660*795d594fSAndroid Build Coastguard Worker // 5. Finish redefinition.
661*795d594fSAndroid Build Coastguard Worker //
662*795d594fSAndroid Build Coastguard Worker // Step 4 is required because there might be allocations after we have estimated and before we
663*795d594fSAndroid Build Coastguard Worker // suspend all threads. This isn't expected to be frequent so we shouldn't usually need to retry
664*795d594fSAndroid Build Coastguard Worker // multiple times.
665*795d594fSAndroid Build Coastguard Worker // Using a lock here is a short-term fix to block on concurrent redefinitions (instead of
666*795d594fSAndroid Build Coastguard Worker // returning an error) while we rework the redefinition code.
667*795d594fSAndroid Build Coastguard Worker // art::MutexLock lg(self, redefinition_lock);
668*795d594fSAndroid Build Coastguard Worker std::lock_guard<std::mutex> lg(redefinition_lock);
669*795d594fSAndroid Build Coastguard Worker
670*795d594fSAndroid Build Coastguard Worker // We need to fiddle with the verification class flags. To do this we need to make sure there are
671*795d594fSAndroid Build Coastguard Worker // no concurrent redefinitions of the same class at the same time. For simplicity and because
672*795d594fSAndroid Build Coastguard Worker // this is not expected to be a common occurrence we will just wrap the whole thing in a TOP-level
673*795d594fSAndroid Build Coastguard Worker // lock.
674*795d594fSAndroid Build Coastguard Worker Redefiner r(env, runtime, self, type, error_msg);
675*795d594fSAndroid Build Coastguard Worker
676*795d594fSAndroid Build Coastguard Worker // Stop JIT for the duration of this redefine since the JIT might concurrently compile a method we
677*795d594fSAndroid Build Coastguard Worker // are going to redefine.
678*795d594fSAndroid Build Coastguard Worker // TODO We should prevent user-code suspensions to make sure this isn't held for too long.
679*795d594fSAndroid Build Coastguard Worker art::jit::ScopedJitSuspend suspend_jit;
680*795d594fSAndroid Build Coastguard Worker // Get shared mutator lock so we can lock all the classes.
681*795d594fSAndroid Build Coastguard Worker art::ScopedObjectAccess soa(self);
682*795d594fSAndroid Build Coastguard Worker for (const ArtClassDefinition& def : definitions) {
683*795d594fSAndroid Build Coastguard Worker // Only try to transform classes that have been modified.
684*795d594fSAndroid Build Coastguard Worker if (def.IsModified()) {
685*795d594fSAndroid Build Coastguard Worker jvmtiError res = r.AddRedefinition(env, def);
686*795d594fSAndroid Build Coastguard Worker if (res != OK) {
687*795d594fSAndroid Build Coastguard Worker return res;
688*795d594fSAndroid Build Coastguard Worker }
689*795d594fSAndroid Build Coastguard Worker }
690*795d594fSAndroid Build Coastguard Worker }
691*795d594fSAndroid Build Coastguard Worker jvmtiError res = r.Run();
692*795d594fSAndroid Build Coastguard Worker return res;
693*795d594fSAndroid Build Coastguard Worker }
694*795d594fSAndroid Build Coastguard Worker
AddRedefinition(ArtJvmTiEnv * env,const ArtClassDefinition & def)695*795d594fSAndroid Build Coastguard Worker jvmtiError Redefiner::AddRedefinition(ArtJvmTiEnv* env, const ArtClassDefinition& def) {
696*795d594fSAndroid Build Coastguard Worker std::string original_dex_location;
697*795d594fSAndroid Build Coastguard Worker jvmtiError ret = OK;
698*795d594fSAndroid Build Coastguard Worker if ((ret = GetClassLocation(env, def.GetClass(), &original_dex_location))) {
699*795d594fSAndroid Build Coastguard Worker *error_msg_ = "Unable to get original dex file location!";
700*795d594fSAndroid Build Coastguard Worker return ret;
701*795d594fSAndroid Build Coastguard Worker }
702*795d594fSAndroid Build Coastguard Worker char* generic_ptr_unused = nullptr;
703*795d594fSAndroid Build Coastguard Worker char* signature_ptr = nullptr;
704*795d594fSAndroid Build Coastguard Worker if ((ret = env->GetClassSignature(def.GetClass(), &signature_ptr, &generic_ptr_unused)) != OK) {
705*795d594fSAndroid Build Coastguard Worker *error_msg_ = "Unable to get class signature!";
706*795d594fSAndroid Build Coastguard Worker return ret;
707*795d594fSAndroid Build Coastguard Worker }
708*795d594fSAndroid Build Coastguard Worker JvmtiUniquePtr<char> generic_unique_ptr(MakeJvmtiUniquePtr(env, generic_ptr_unused));
709*795d594fSAndroid Build Coastguard Worker JvmtiUniquePtr<char> signature_unique_ptr(MakeJvmtiUniquePtr(env, signature_ptr));
710*795d594fSAndroid Build Coastguard Worker art::MemMap map = MoveDataToMemMap(original_dex_location, def.GetDexData(), error_msg_);
711*795d594fSAndroid Build Coastguard Worker std::ostringstream os;
712*795d594fSAndroid Build Coastguard Worker if (!map.IsValid()) {
713*795d594fSAndroid Build Coastguard Worker os << "Failed to create anonymous mmap for modified dex file of class " << def.GetName()
714*795d594fSAndroid Build Coastguard Worker << "in dex file " << original_dex_location << " because: " << *error_msg_;
715*795d594fSAndroid Build Coastguard Worker *error_msg_ = os.str();
716*795d594fSAndroid Build Coastguard Worker return ERR(OUT_OF_MEMORY);
717*795d594fSAndroid Build Coastguard Worker }
718*795d594fSAndroid Build Coastguard Worker if (map.Size() < sizeof(art::DexFile::Header)) {
719*795d594fSAndroid Build Coastguard Worker *error_msg_ = "Could not read dex file header because dex_data was too short";
720*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS_FORMAT);
721*795d594fSAndroid Build Coastguard Worker }
722*795d594fSAndroid Build Coastguard Worker std::string name = map.GetName();
723*795d594fSAndroid Build Coastguard Worker uint32_t checksum = reinterpret_cast<const art::DexFile::Header*>(map.Begin())->checksum_;
724*795d594fSAndroid Build Coastguard Worker art::ArtDexFileLoader dex_file_loader(std::move(map), name);
725*795d594fSAndroid Build Coastguard Worker std::unique_ptr<const art::DexFile> dex_file(dex_file_loader.Open(checksum,
726*795d594fSAndroid Build Coastguard Worker /*verify=*/true,
727*795d594fSAndroid Build Coastguard Worker /*verify_checksum=*/true,
728*795d594fSAndroid Build Coastguard Worker error_msg_));
729*795d594fSAndroid Build Coastguard Worker if (dex_file.get() == nullptr) {
730*795d594fSAndroid Build Coastguard Worker os << "Unable to load modified dex file for " << def.GetName() << ": " << *error_msg_;
731*795d594fSAndroid Build Coastguard Worker *error_msg_ = os.str();
732*795d594fSAndroid Build Coastguard Worker return ERR(INVALID_CLASS_FORMAT);
733*795d594fSAndroid Build Coastguard Worker }
734*795d594fSAndroid Build Coastguard Worker redefinitions_.push_back(
735*795d594fSAndroid Build Coastguard Worker Redefiner::ClassRedefinition(this,
736*795d594fSAndroid Build Coastguard Worker def.GetClass(),
737*795d594fSAndroid Build Coastguard Worker dex_file.release(),
738*795d594fSAndroid Build Coastguard Worker signature_ptr,
739*795d594fSAndroid Build Coastguard Worker def.GetNewOriginalDexFile()));
740*795d594fSAndroid Build Coastguard Worker return OK;
741*795d594fSAndroid Build Coastguard Worker }
742*795d594fSAndroid Build Coastguard Worker
GetMirrorClass()743*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::GetMirrorClass() {
744*795d594fSAndroid Build Coastguard Worker return driver_->self_->DecodeJObject(klass_)->AsClass();
745*795d594fSAndroid Build Coastguard Worker }
746*795d594fSAndroid Build Coastguard Worker
GetClassLoader()747*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ClassLoader> Redefiner::ClassRedefinition::GetClassLoader() {
748*795d594fSAndroid Build Coastguard Worker return GetMirrorClass()->GetClassLoader();
749*795d594fSAndroid Build Coastguard Worker }
750*795d594fSAndroid Build Coastguard Worker
CreateNewDexCache(art::Handle<art::mirror::ClassLoader> loader)751*795d594fSAndroid Build Coastguard Worker art::mirror::DexCache* Redefiner::ClassRedefinition::CreateNewDexCache(
752*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::ClassLoader> loader) {
753*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<2> hs(driver_->self_);
754*795d594fSAndroid Build Coastguard Worker art::ClassLinker* cl = driver_->runtime_->GetClassLinker();
755*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::DexCache> cache(hs.NewHandle(
756*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::DexCache>::DownCast(
757*795d594fSAndroid Build Coastguard Worker art::GetClassRoot<art::mirror::DexCache>(cl)->AllocObject(driver_->self_))));
758*795d594fSAndroid Build Coastguard Worker if (cache.IsNull()) {
759*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
760*795d594fSAndroid Build Coastguard Worker return nullptr;
761*795d594fSAndroid Build Coastguard Worker }
762*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::String> location(hs.NewHandle(
763*795d594fSAndroid Build Coastguard Worker cl->GetInternTable()->InternStrong(dex_file_->GetLocation().c_str())));
764*795d594fSAndroid Build Coastguard Worker if (location.IsNull()) {
765*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
766*795d594fSAndroid Build Coastguard Worker return nullptr;
767*795d594fSAndroid Build Coastguard Worker }
768*795d594fSAndroid Build Coastguard Worker art::WriterMutexLock mu(driver_->self_, *art::Locks::dex_lock_);
769*795d594fSAndroid Build Coastguard Worker cache->SetLocation(location.Get());
770*795d594fSAndroid Build Coastguard Worker cache->Initialize(dex_file_.get(), loader.Get());
771*795d594fSAndroid Build Coastguard Worker return cache.Get();
772*795d594fSAndroid Build Coastguard Worker }
773*795d594fSAndroid Build Coastguard Worker
RecordFailure(jvmtiError result,const std::string & class_sig,const std::string & error_msg)774*795d594fSAndroid Build Coastguard Worker void Redefiner::RecordFailure(jvmtiError result,
775*795d594fSAndroid Build Coastguard Worker const std::string& class_sig,
776*795d594fSAndroid Build Coastguard Worker const std::string& error_msg) {
777*795d594fSAndroid Build Coastguard Worker *error_msg_ = StringPrintf("Unable to perform redefinition of '%s': %s",
778*795d594fSAndroid Build Coastguard Worker class_sig.c_str(),
779*795d594fSAndroid Build Coastguard Worker error_msg.c_str());
780*795d594fSAndroid Build Coastguard Worker result_ = result;
781*795d594fSAndroid Build Coastguard Worker }
782*795d594fSAndroid Build Coastguard Worker
AllocateOrGetOriginalDexFile()783*795d594fSAndroid Build Coastguard Worker art::mirror::Object* Redefiner::ClassRedefinition::AllocateOrGetOriginalDexFile() {
784*795d594fSAndroid Build Coastguard Worker // If we have been specifically given a new set of bytes use that
785*795d594fSAndroid Build Coastguard Worker if (original_dex_file_.size() != 0) {
786*795d594fSAndroid Build Coastguard Worker return art::mirror::ByteArray::AllocateAndFill(
787*795d594fSAndroid Build Coastguard Worker driver_->self_,
788*795d594fSAndroid Build Coastguard Worker reinterpret_cast<const signed char*>(original_dex_file_.data()),
789*795d594fSAndroid Build Coastguard Worker original_dex_file_.size()).Ptr();
790*795d594fSAndroid Build Coastguard Worker }
791*795d594fSAndroid Build Coastguard Worker
792*795d594fSAndroid Build Coastguard Worker // See if we already have one set.
793*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ClassExt> ext(GetMirrorClass()->GetExtData());
794*795d594fSAndroid Build Coastguard Worker if (!ext.IsNull()) {
795*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> old_original_dex_file(ext->GetOriginalDexFile());
796*795d594fSAndroid Build Coastguard Worker if (!old_original_dex_file.IsNull()) {
797*795d594fSAndroid Build Coastguard Worker // We do. Use it.
798*795d594fSAndroid Build Coastguard Worker return old_original_dex_file.Ptr();
799*795d594fSAndroid Build Coastguard Worker }
800*795d594fSAndroid Build Coastguard Worker }
801*795d594fSAndroid Build Coastguard Worker
802*795d594fSAndroid Build Coastguard Worker // return the current dex_cache which has the dex file in it.
803*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::DexCache> current_dex_cache(GetMirrorClass()->GetDexCache());
804*795d594fSAndroid Build Coastguard Worker return current_dex_cache.Ptr();
805*795d594fSAndroid Build Coastguard Worker }
806*795d594fSAndroid Build Coastguard Worker
807*795d594fSAndroid Build Coastguard Worker struct CallbackCtx {
808*795d594fSAndroid Build Coastguard Worker ObsoleteMap* obsolete_map;
809*795d594fSAndroid Build Coastguard Worker art::LinearAlloc* allocator;
810*795d594fSAndroid Build Coastguard Worker std::unordered_set<art::ArtMethod*> obsolete_methods;
811*795d594fSAndroid Build Coastguard Worker
CallbackCtxopenjdkjvmti::CallbackCtx812*795d594fSAndroid Build Coastguard Worker explicit CallbackCtx(ObsoleteMap* map, art::LinearAlloc* alloc)
813*795d594fSAndroid Build Coastguard Worker : obsolete_map(map), allocator(alloc) {}
814*795d594fSAndroid Build Coastguard Worker };
815*795d594fSAndroid Build Coastguard Worker
DoAllocateObsoleteMethodsCallback(art::Thread * t,void * vdata)816*795d594fSAndroid Build Coastguard Worker void DoAllocateObsoleteMethodsCallback(art::Thread* t, void* vdata) NO_THREAD_SAFETY_ANALYSIS {
817*795d594fSAndroid Build Coastguard Worker CallbackCtx* data = reinterpret_cast<CallbackCtx*>(vdata);
818*795d594fSAndroid Build Coastguard Worker ObsoleteMethodStackVisitor::UpdateObsoleteFrames(t,
819*795d594fSAndroid Build Coastguard Worker data->allocator,
820*795d594fSAndroid Build Coastguard Worker data->obsolete_methods,
821*795d594fSAndroid Build Coastguard Worker data->obsolete_map);
822*795d594fSAndroid Build Coastguard Worker }
823*795d594fSAndroid Build Coastguard Worker
824*795d594fSAndroid Build Coastguard Worker // This creates any ArtMethod* structures needed for obsolete methods and ensures that the stack is
825*795d594fSAndroid Build Coastguard Worker // updated so they will be run.
826*795d594fSAndroid Build Coastguard Worker // TODO Rewrite so we can do this only once regardless of how many redefinitions there are.
FindAndAllocateObsoleteMethods(art::ObjPtr<art::mirror::Class> art_klass)827*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::FindAndAllocateObsoleteMethods(
828*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> art_klass) {
829*795d594fSAndroid Build Coastguard Worker DCHECK(!IsStructuralRedefinition());
830*795d594fSAndroid Build Coastguard Worker art::ScopedAssertNoThreadSuspension ns("No thread suspension during thread stack walking");
831*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ClassExt> ext = art_klass->GetExtData();
832*795d594fSAndroid Build Coastguard Worker CHECK(ext->GetObsoleteMethods() != nullptr);
833*795d594fSAndroid Build Coastguard Worker art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
834*795d594fSAndroid Build Coastguard Worker // This holds pointers to the obsolete methods map fields which are updated as needed.
835*795d594fSAndroid Build Coastguard Worker ObsoleteMap map(ext->GetObsoleteMethods(), ext->GetObsoleteDexCaches(), art_klass->GetDexCache());
836*795d594fSAndroid Build Coastguard Worker CallbackCtx ctx(&map, linker->GetAllocatorForClassLoader(art_klass->GetClassLoader()));
837*795d594fSAndroid Build Coastguard Worker // Add all the declared methods to the map
838*795d594fSAndroid Build Coastguard Worker for (auto& m : art_klass->GetDeclaredMethods(art::kRuntimePointerSize)) {
839*795d594fSAndroid Build Coastguard Worker if (m.IsIntrinsic()) {
840*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "Redefining intrinsic method " << m.PrettyMethod() << ". This may cause the "
841*795d594fSAndroid Build Coastguard Worker << "unexpected use of the original definition of " << m.PrettyMethod() << "in "
842*795d594fSAndroid Build Coastguard Worker << "methods that have already been compiled.";
843*795d594fSAndroid Build Coastguard Worker }
844*795d594fSAndroid Build Coastguard Worker // It is possible to simply filter out some methods where they cannot really become obsolete,
845*795d594fSAndroid Build Coastguard Worker // such as native methods and keep their original (possibly optimized) implementations. We don't
846*795d594fSAndroid Build Coastguard Worker // do this, however, since we would need to mark these functions (still in the classes
847*795d594fSAndroid Build Coastguard Worker // declared_methods array) as obsolete so we will find the correct dex file to get meta-data
848*795d594fSAndroid Build Coastguard Worker // from (for example about stack-frame size). Furthermore we would be unable to get some useful
849*795d594fSAndroid Build Coastguard Worker // error checking from the interpreter which ensure we don't try to start executing obsolete
850*795d594fSAndroid Build Coastguard Worker // methods.
851*795d594fSAndroid Build Coastguard Worker ctx.obsolete_methods.insert(&m);
852*795d594fSAndroid Build Coastguard Worker }
853*795d594fSAndroid Build Coastguard Worker {
854*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(driver_->self_, *art::Locks::thread_list_lock_);
855*795d594fSAndroid Build Coastguard Worker art::ThreadList* list = art::Runtime::Current()->GetThreadList();
856*795d594fSAndroid Build Coastguard Worker list->ForEach(DoAllocateObsoleteMethodsCallback, static_cast<void*>(&ctx));
857*795d594fSAndroid Build Coastguard Worker // After we've done walking all threads' stacks and updating method pointers on them,
858*795d594fSAndroid Build Coastguard Worker // update JIT data structures (used by the stack walk above) to point to the new methods.
859*795d594fSAndroid Build Coastguard Worker art::jit::Jit* jit = art::Runtime::Current()->GetJit();
860*795d594fSAndroid Build Coastguard Worker if (jit != nullptr) {
861*795d594fSAndroid Build Coastguard Worker for (const ObsoleteMap::ObsoleteMethodPair& it : *ctx.obsolete_map) {
862*795d594fSAndroid Build Coastguard Worker // Notify the JIT we are making this obsolete method. It will update the jit's internal
863*795d594fSAndroid Build Coastguard Worker // structures to keep track of the new obsolete method.
864*795d594fSAndroid Build Coastguard Worker jit->GetCodeCache()->MoveObsoleteMethod(it.old_method, it.obsolete_method);
865*795d594fSAndroid Build Coastguard Worker }
866*795d594fSAndroid Build Coastguard Worker }
867*795d594fSAndroid Build Coastguard Worker }
868*795d594fSAndroid Build Coastguard Worker }
869*795d594fSAndroid Build Coastguard Worker
870*795d594fSAndroid Build Coastguard Worker namespace {
871*795d594fSAndroid Build Coastguard Worker template <typename T> struct SignatureType {};
872*795d594fSAndroid Build Coastguard Worker template <> struct SignatureType<art::ArtField> { using type = std::string_view; };
873*795d594fSAndroid Build Coastguard Worker template <> struct SignatureType<art::ArtMethod> { using type = art::Signature; };
874*795d594fSAndroid Build Coastguard Worker
875*795d594fSAndroid Build Coastguard Worker template <typename T> struct NameAndSignature {
876*795d594fSAndroid Build Coastguard Worker public:
877*795d594fSAndroid Build Coastguard Worker using SigType = typename SignatureType<T>::type;
878*795d594fSAndroid Build Coastguard Worker
879*795d594fSAndroid Build Coastguard Worker NameAndSignature(const art::DexFile* dex_file, uint32_t id);
880*795d594fSAndroid Build Coastguard Worker
NameAndSignatureopenjdkjvmti::__anond2bfe4210211::NameAndSignature881*795d594fSAndroid Build Coastguard Worker NameAndSignature(const std::string_view& name, const SigType& sig) : name_(name), sig_(sig) {}
882*795d594fSAndroid Build Coastguard Worker
operator ==openjdkjvmti::__anond2bfe4210211::NameAndSignature883*795d594fSAndroid Build Coastguard Worker bool operator==(const NameAndSignature<T>& o) const {
884*795d594fSAndroid Build Coastguard Worker return name_ == o.name_ && sig_ == o.sig_;
885*795d594fSAndroid Build Coastguard Worker }
886*795d594fSAndroid Build Coastguard Worker
operator !=openjdkjvmti::__anond2bfe4210211::NameAndSignature887*795d594fSAndroid Build Coastguard Worker bool operator!=(const NameAndSignature<T>& o) const {
888*795d594fSAndroid Build Coastguard Worker return !(*this == o);
889*795d594fSAndroid Build Coastguard Worker }
890*795d594fSAndroid Build Coastguard Worker
dumpopenjdkjvmti::__anond2bfe4210211::NameAndSignature891*795d594fSAndroid Build Coastguard Worker std::ostream& dump(std::ostream& os) const {
892*795d594fSAndroid Build Coastguard Worker return os << "'" << name_ << "' (sig: " << sig_ << ")";
893*795d594fSAndroid Build Coastguard Worker }
894*795d594fSAndroid Build Coastguard Worker
ToStringopenjdkjvmti::__anond2bfe4210211::NameAndSignature895*795d594fSAndroid Build Coastguard Worker std::string ToString() const {
896*795d594fSAndroid Build Coastguard Worker std::ostringstream os;
897*795d594fSAndroid Build Coastguard Worker os << *this;
898*795d594fSAndroid Build Coastguard Worker return os.str();
899*795d594fSAndroid Build Coastguard Worker }
900*795d594fSAndroid Build Coastguard Worker
901*795d594fSAndroid Build Coastguard Worker std::string_view name_;
902*795d594fSAndroid Build Coastguard Worker SigType sig_;
903*795d594fSAndroid Build Coastguard Worker };
904*795d594fSAndroid Build Coastguard Worker
905*795d594fSAndroid Build Coastguard Worker template <typename T>
operator <<(std::ostream & os,const NameAndSignature<T> & nas)906*795d594fSAndroid Build Coastguard Worker std::ostream& operator<<(std::ostream& os, const NameAndSignature<T>& nas) {
907*795d594fSAndroid Build Coastguard Worker return nas.dump(os);
908*795d594fSAndroid Build Coastguard Worker }
909*795d594fSAndroid Build Coastguard Worker
910*795d594fSAndroid Build Coastguard Worker using FieldNameAndSignature = NameAndSignature<art::ArtField>;
911*795d594fSAndroid Build Coastguard Worker template <>
NameAndSignature(const art::DexFile * dex_file,uint32_t id)912*795d594fSAndroid Build Coastguard Worker FieldNameAndSignature::NameAndSignature(const art::DexFile* dex_file, uint32_t id)
913*795d594fSAndroid Build Coastguard Worker : FieldNameAndSignature(dex_file->GetFieldName(dex_file->GetFieldId(id)),
914*795d594fSAndroid Build Coastguard Worker dex_file->GetFieldTypeDescriptor(dex_file->GetFieldId(id))) {}
915*795d594fSAndroid Build Coastguard Worker
916*795d594fSAndroid Build Coastguard Worker using MethodNameAndSignature = NameAndSignature<art::ArtMethod>;
917*795d594fSAndroid Build Coastguard Worker template <>
NameAndSignature(const art::DexFile * dex_file,uint32_t id)918*795d594fSAndroid Build Coastguard Worker MethodNameAndSignature::NameAndSignature(const art::DexFile* dex_file, uint32_t id)
919*795d594fSAndroid Build Coastguard Worker : MethodNameAndSignature(dex_file->GetMethodName(dex_file->GetMethodId(id)),
920*795d594fSAndroid Build Coastguard Worker dex_file->GetMethodSignature(dex_file->GetMethodId(id))) {}
921*795d594fSAndroid Build Coastguard Worker
922*795d594fSAndroid Build Coastguard Worker } // namespace
923*795d594fSAndroid Build Coastguard Worker
RecordNewMethodAdded()924*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::RecordNewMethodAdded() {
925*795d594fSAndroid Build Coastguard Worker DCHECK(driver_->IsStructuralRedefinition());
926*795d594fSAndroid Build Coastguard Worker added_methods_ = true;
927*795d594fSAndroid Build Coastguard Worker }
RecordNewFieldAdded()928*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::RecordNewFieldAdded() {
929*795d594fSAndroid Build Coastguard Worker DCHECK(driver_->IsStructuralRedefinition());
930*795d594fSAndroid Build Coastguard Worker added_fields_ = true;
931*795d594fSAndroid Build Coastguard Worker }
932*795d594fSAndroid Build Coastguard Worker
CheckMethods()933*795d594fSAndroid Build Coastguard Worker bool Redefiner::ClassRedefinition::CheckMethods() {
934*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<1> hs(driver_->self_);
935*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
936*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
937*795d594fSAndroid Build Coastguard Worker
938*795d594fSAndroid Build Coastguard Worker // Make sure we have the same number of methods (or the same or greater if we're structural).
939*795d594fSAndroid Build Coastguard Worker art::ClassAccessor accessor(*dex_file_, dex_file_->GetClassDef(0));
940*795d594fSAndroid Build Coastguard Worker uint32_t num_new_method = accessor.NumMethods();
941*795d594fSAndroid Build Coastguard Worker uint32_t num_old_method = h_klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size();
942*795d594fSAndroid Build Coastguard Worker const bool is_structural = driver_->IsStructuralRedefinition();
943*795d594fSAndroid Build Coastguard Worker if (!is_structural && num_new_method != num_old_method) {
944*795d594fSAndroid Build Coastguard Worker bool bigger = num_new_method > num_old_method;
945*795d594fSAndroid Build Coastguard Worker RecordFailure(bigger ? ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED)
946*795d594fSAndroid Build Coastguard Worker : ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED),
947*795d594fSAndroid Build Coastguard Worker StringPrintf("Total number of declared methods changed from %d to %d",
948*795d594fSAndroid Build Coastguard Worker num_old_method,
949*795d594fSAndroid Build Coastguard Worker num_new_method));
950*795d594fSAndroid Build Coastguard Worker return false;
951*795d594fSAndroid Build Coastguard Worker }
952*795d594fSAndroid Build Coastguard Worker
953*795d594fSAndroid Build Coastguard Worker // Skip all of the fields. We should have already checked this.
954*795d594fSAndroid Build Coastguard Worker // Check each of the methods. NB we don't need to specifically check for removals since the 2 dex
955*795d594fSAndroid Build Coastguard Worker // files have the same number of methods, which means there must be an equal amount of additions
956*795d594fSAndroid Build Coastguard Worker // and removals. We should have already checked the fields.
957*795d594fSAndroid Build Coastguard Worker const art::DexFile& old_dex_file = h_klass->GetDexFile();
958*795d594fSAndroid Build Coastguard Worker art::ClassAccessor old_accessor(old_dex_file, *h_klass->GetClassDef());
959*795d594fSAndroid Build Coastguard Worker // We need this to check for methods going missing in structural cases.
960*795d594fSAndroid Build Coastguard Worker std::vector<bool> seen_old_methods(
961*795d594fSAndroid Build Coastguard Worker (kCheckAllMethodsSeenOnce || is_structural) ? old_accessor.NumMethods() : 0, false);
962*795d594fSAndroid Build Coastguard Worker const auto old_methods = old_accessor.GetMethods();
963*795d594fSAndroid Build Coastguard Worker for (const art::ClassAccessor::Method& new_method : accessor.GetMethods()) {
964*795d594fSAndroid Build Coastguard Worker // Get the data on the method we are searching for
965*795d594fSAndroid Build Coastguard Worker MethodNameAndSignature new_method_id(dex_file_.get(), new_method.GetIndex());
966*795d594fSAndroid Build Coastguard Worker const auto old_iter =
967*795d594fSAndroid Build Coastguard Worker std::find_if(old_methods.cbegin(), old_methods.cend(), [&](const auto& current_old_method) {
968*795d594fSAndroid Build Coastguard Worker MethodNameAndSignature old_method_id(&old_dex_file, current_old_method.GetIndex());
969*795d594fSAndroid Build Coastguard Worker return old_method_id == new_method_id;
970*795d594fSAndroid Build Coastguard Worker });
971*795d594fSAndroid Build Coastguard Worker
972*795d594fSAndroid Build Coastguard Worker if (!new_method.IsStaticOrDirect()) {
973*795d594fSAndroid Build Coastguard Worker RecordHasVirtualMembers();
974*795d594fSAndroid Build Coastguard Worker }
975*795d594fSAndroid Build Coastguard Worker if (old_iter == old_methods.cend()) {
976*795d594fSAndroid Build Coastguard Worker if (is_structural) {
977*795d594fSAndroid Build Coastguard Worker RecordNewMethodAdded();
978*795d594fSAndroid Build Coastguard Worker } else {
979*795d594fSAndroid Build Coastguard Worker RecordFailure(
980*795d594fSAndroid Build Coastguard Worker ERR(UNSUPPORTED_REDEFINITION_METHOD_ADDED),
981*795d594fSAndroid Build Coastguard Worker StringPrintf("Unknown virtual method %s was added!", new_method_id.ToString().c_str()));
982*795d594fSAndroid Build Coastguard Worker return false;
983*795d594fSAndroid Build Coastguard Worker }
984*795d594fSAndroid Build Coastguard Worker } else if (new_method.GetAccessFlags() != old_iter->GetAccessFlags()) {
985*795d594fSAndroid Build Coastguard Worker RecordFailure(
986*795d594fSAndroid Build Coastguard Worker ERR(UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED),
987*795d594fSAndroid Build Coastguard Worker StringPrintf("method %s had different access flags", new_method_id.ToString().c_str()));
988*795d594fSAndroid Build Coastguard Worker return false;
989*795d594fSAndroid Build Coastguard Worker } else if (kCheckAllMethodsSeenOnce || is_structural) {
990*795d594fSAndroid Build Coastguard Worker // We only need this if we are structural.
991*795d594fSAndroid Build Coastguard Worker size_t off = std::distance(old_methods.cbegin(), old_iter);
992*795d594fSAndroid Build Coastguard Worker DCHECK(!seen_old_methods[off])
993*795d594fSAndroid Build Coastguard Worker << "field at " << off << "("
994*795d594fSAndroid Build Coastguard Worker << MethodNameAndSignature(&old_dex_file, old_iter->GetIndex()) << ") already seen?";
995*795d594fSAndroid Build Coastguard Worker seen_old_methods[off] = true;
996*795d594fSAndroid Build Coastguard Worker }
997*795d594fSAndroid Build Coastguard Worker }
998*795d594fSAndroid Build Coastguard Worker if ((kCheckAllMethodsSeenOnce || is_structural) &&
999*795d594fSAndroid Build Coastguard Worker !std::all_of(seen_old_methods.cbegin(), seen_old_methods.cend(), [](auto x) { return x; })) {
1000*795d594fSAndroid Build Coastguard Worker DCHECK(is_structural) << "We should have hit an earlier failure before getting here!";
1001*795d594fSAndroid Build Coastguard Worker auto first_fail =
1002*795d594fSAndroid Build Coastguard Worker std::find_if(seen_old_methods.cbegin(), seen_old_methods.cend(), [](auto x) { return !x; });
1003*795d594fSAndroid Build Coastguard Worker auto off = std::distance(seen_old_methods.cbegin(), first_fail);
1004*795d594fSAndroid Build Coastguard Worker auto fail = old_methods.cbegin();
1005*795d594fSAndroid Build Coastguard Worker std::advance(fail, off);
1006*795d594fSAndroid Build Coastguard Worker RecordFailure(
1007*795d594fSAndroid Build Coastguard Worker ERR(UNSUPPORTED_REDEFINITION_METHOD_DELETED),
1008*795d594fSAndroid Build Coastguard Worker StringPrintf("Method %s missing!",
1009*795d594fSAndroid Build Coastguard Worker MethodNameAndSignature(&old_dex_file, fail->GetIndex()).ToString().c_str()));
1010*795d594fSAndroid Build Coastguard Worker return false;
1011*795d594fSAndroid Build Coastguard Worker }
1012*795d594fSAndroid Build Coastguard Worker return true;
1013*795d594fSAndroid Build Coastguard Worker }
1014*795d594fSAndroid Build Coastguard Worker
CheckFields()1015*795d594fSAndroid Build Coastguard Worker bool Redefiner::ClassRedefinition::CheckFields() {
1016*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<1> hs(driver_->self_);
1017*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
1018*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
1019*795d594fSAndroid Build Coastguard Worker art::ClassAccessor new_accessor(*dex_file_, dex_file_->GetClassDef(0));
1020*795d594fSAndroid Build Coastguard Worker
1021*795d594fSAndroid Build Coastguard Worker const art::DexFile& old_dex_file = h_klass->GetDexFile();
1022*795d594fSAndroid Build Coastguard Worker art::ClassAccessor old_accessor(old_dex_file, *h_klass->GetClassDef());
1023*795d594fSAndroid Build Coastguard Worker // Instance and static fields can be differentiated by their flags so no need to check them
1024*795d594fSAndroid Build Coastguard Worker // separately.
1025*795d594fSAndroid Build Coastguard Worker std::vector<bool> seen_old_fields(old_accessor.NumFields(), false);
1026*795d594fSAndroid Build Coastguard Worker const auto old_fields = old_accessor.GetFields();
1027*795d594fSAndroid Build Coastguard Worker for (const art::ClassAccessor::Field& new_field : new_accessor.GetFields()) {
1028*795d594fSAndroid Build Coastguard Worker // Get the data on the method we are searching for
1029*795d594fSAndroid Build Coastguard Worker FieldNameAndSignature new_field_id(dex_file_.get(), new_field.GetIndex());
1030*795d594fSAndroid Build Coastguard Worker const auto old_iter =
1031*795d594fSAndroid Build Coastguard Worker std::find_if(old_fields.cbegin(), old_fields.cend(), [&](const auto& old_iter) {
1032*795d594fSAndroid Build Coastguard Worker FieldNameAndSignature old_field_id(&old_dex_file, old_iter.GetIndex());
1033*795d594fSAndroid Build Coastguard Worker return old_field_id == new_field_id;
1034*795d594fSAndroid Build Coastguard Worker });
1035*795d594fSAndroid Build Coastguard Worker if (!new_field.IsStatic()) {
1036*795d594fSAndroid Build Coastguard Worker RecordHasVirtualMembers();
1037*795d594fSAndroid Build Coastguard Worker }
1038*795d594fSAndroid Build Coastguard Worker if (old_iter == old_fields.cend()) {
1039*795d594fSAndroid Build Coastguard Worker if (driver_->IsStructuralRedefinition()) {
1040*795d594fSAndroid Build Coastguard Worker RecordNewFieldAdded();
1041*795d594fSAndroid Build Coastguard Worker } else {
1042*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
1043*795d594fSAndroid Build Coastguard Worker StringPrintf("Unknown field %s added!", new_field_id.ToString().c_str()));
1044*795d594fSAndroid Build Coastguard Worker return false;
1045*795d594fSAndroid Build Coastguard Worker }
1046*795d594fSAndroid Build Coastguard Worker } else if (new_field.GetAccessFlags() != old_iter->GetAccessFlags()) {
1047*795d594fSAndroid Build Coastguard Worker RecordFailure(
1048*795d594fSAndroid Build Coastguard Worker ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
1049*795d594fSAndroid Build Coastguard Worker StringPrintf("Field %s had different access flags", new_field_id.ToString().c_str()));
1050*795d594fSAndroid Build Coastguard Worker return false;
1051*795d594fSAndroid Build Coastguard Worker } else {
1052*795d594fSAndroid Build Coastguard Worker size_t off = std::distance(old_fields.cbegin(), old_iter);
1053*795d594fSAndroid Build Coastguard Worker DCHECK(!seen_old_fields[off])
1054*795d594fSAndroid Build Coastguard Worker << "field at " << off << "(" << FieldNameAndSignature(&old_dex_file, old_iter->GetIndex())
1055*795d594fSAndroid Build Coastguard Worker << ") already seen?";
1056*795d594fSAndroid Build Coastguard Worker seen_old_fields[off] = true;
1057*795d594fSAndroid Build Coastguard Worker }
1058*795d594fSAndroid Build Coastguard Worker }
1059*795d594fSAndroid Build Coastguard Worker if (!std::all_of(seen_old_fields.cbegin(), seen_old_fields.cend(), [](auto x) { return x; })) {
1060*795d594fSAndroid Build Coastguard Worker auto first_fail =
1061*795d594fSAndroid Build Coastguard Worker std::find_if(seen_old_fields.cbegin(), seen_old_fields.cend(), [](auto x) { return !x; });
1062*795d594fSAndroid Build Coastguard Worker auto off = std::distance(seen_old_fields.cbegin(), first_fail);
1063*795d594fSAndroid Build Coastguard Worker auto fail = old_fields.cbegin();
1064*795d594fSAndroid Build Coastguard Worker std::advance(fail, off);
1065*795d594fSAndroid Build Coastguard Worker RecordFailure(
1066*795d594fSAndroid Build Coastguard Worker ERR(UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED),
1067*795d594fSAndroid Build Coastguard Worker StringPrintf("Field %s is missing!",
1068*795d594fSAndroid Build Coastguard Worker FieldNameAndSignature(&old_dex_file, fail->GetIndex()).ToString().c_str()));
1069*795d594fSAndroid Build Coastguard Worker return false;
1070*795d594fSAndroid Build Coastguard Worker }
1071*795d594fSAndroid Build Coastguard Worker return true;
1072*795d594fSAndroid Build Coastguard Worker }
1073*795d594fSAndroid Build Coastguard Worker
CheckClass()1074*795d594fSAndroid Build Coastguard Worker bool Redefiner::ClassRedefinition::CheckClass() {
1075*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<1> hs(driver_->self_);
1076*795d594fSAndroid Build Coastguard Worker // Easy check that only 1 class def is present.
1077*795d594fSAndroid Build Coastguard Worker if (dex_file_->NumClassDefs() != 1) {
1078*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(ILLEGAL_ARGUMENT),
1079*795d594fSAndroid Build Coastguard Worker StringPrintf("Expected 1 class def in dex file but found %d",
1080*795d594fSAndroid Build Coastguard Worker dex_file_->NumClassDefs()));
1081*795d594fSAndroid Build Coastguard Worker return false;
1082*795d594fSAndroid Build Coastguard Worker }
1083*795d594fSAndroid Build Coastguard Worker // Get the ClassDef from the new DexFile.
1084*795d594fSAndroid Build Coastguard Worker // Since the dex file has only a single class def the index is always 0.
1085*795d594fSAndroid Build Coastguard Worker const art::dex::ClassDef& def = dex_file_->GetClassDef(0);
1086*795d594fSAndroid Build Coastguard Worker // Get the class as it is now.
1087*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> current_class(hs.NewHandle(GetMirrorClass()));
1088*795d594fSAndroid Build Coastguard Worker
1089*795d594fSAndroid Build Coastguard Worker // Check the access flags didn't change.
1090*795d594fSAndroid Build Coastguard Worker if (def.GetJavaAccessFlags() != (current_class->GetAccessFlags() & art::kAccValidClassFlags)) {
1091*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED),
1092*795d594fSAndroid Build Coastguard Worker "Cannot change modifiers of class by redefinition");
1093*795d594fSAndroid Build Coastguard Worker return false;
1094*795d594fSAndroid Build Coastguard Worker }
1095*795d594fSAndroid Build Coastguard Worker
1096*795d594fSAndroid Build Coastguard Worker // Check class name.
1097*795d594fSAndroid Build Coastguard Worker // These should have been checked by the dexfile verifier on load.
1098*795d594fSAndroid Build Coastguard Worker DCHECK_NE(def.class_idx_, art::dex::TypeIndex::Invalid()) << "Invalid type index";
1099*795d594fSAndroid Build Coastguard Worker const std::string_view descriptor = dex_file_->GetTypeDescriptorView(def.class_idx_);
1100*795d594fSAndroid Build Coastguard Worker if (!current_class->DescriptorEquals(descriptor)) {
1101*795d594fSAndroid Build Coastguard Worker std::string storage;
1102*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(NAMES_DONT_MATCH),
1103*795d594fSAndroid Build Coastguard Worker StringPrintf("expected file to contain class called '%s' but found '%s'!",
1104*795d594fSAndroid Build Coastguard Worker current_class->GetDescriptor(&storage),
1105*795d594fSAndroid Build Coastguard Worker std::string(descriptor).c_str()));
1106*795d594fSAndroid Build Coastguard Worker return false;
1107*795d594fSAndroid Build Coastguard Worker }
1108*795d594fSAndroid Build Coastguard Worker if (current_class->IsObjectClass()) {
1109*795d594fSAndroid Build Coastguard Worker if (def.superclass_idx_ != art::dex::TypeIndex::Invalid()) {
1110*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass added!");
1111*795d594fSAndroid Build Coastguard Worker return false;
1112*795d594fSAndroid Build Coastguard Worker }
1113*795d594fSAndroid Build Coastguard Worker } else {
1114*795d594fSAndroid Build Coastguard Worker const std::string_view super_descriptor = dex_file_->GetTypeDescriptorView(def.superclass_idx_);
1115*795d594fSAndroid Build Coastguard Worker if (!current_class->GetSuperClass()->DescriptorEquals(super_descriptor)) {
1116*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Superclass changed");
1117*795d594fSAndroid Build Coastguard Worker return false;
1118*795d594fSAndroid Build Coastguard Worker }
1119*795d594fSAndroid Build Coastguard Worker }
1120*795d594fSAndroid Build Coastguard Worker const art::dex::TypeList* interfaces = dex_file_->GetInterfacesList(def);
1121*795d594fSAndroid Build Coastguard Worker if (interfaces == nullptr) {
1122*795d594fSAndroid Build Coastguard Worker if (current_class->NumDirectInterfaces() != 0) {
1123*795d594fSAndroid Build Coastguard Worker // TODO Support this for kStructural.
1124*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added");
1125*795d594fSAndroid Build Coastguard Worker return false;
1126*795d594fSAndroid Build Coastguard Worker }
1127*795d594fSAndroid Build Coastguard Worker } else {
1128*795d594fSAndroid Build Coastguard Worker DCHECK(!current_class->IsProxyClass());
1129*795d594fSAndroid Build Coastguard Worker const art::dex::TypeList* current_interfaces = current_class->GetInterfaceTypeList();
1130*795d594fSAndroid Build Coastguard Worker if (current_interfaces == nullptr || current_interfaces->Size() != interfaces->Size()) {
1131*795d594fSAndroid Build Coastguard Worker // TODO Support this for kStructural.
1132*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED), "Interfaces added or removed");
1133*795d594fSAndroid Build Coastguard Worker return false;
1134*795d594fSAndroid Build Coastguard Worker }
1135*795d594fSAndroid Build Coastguard Worker // The order of interfaces is (barely) meaningful so we error if it changes.
1136*795d594fSAndroid Build Coastguard Worker const art::DexFile& orig_dex_file = current_class->GetDexFile();
1137*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < interfaces->Size(); i++) {
1138*795d594fSAndroid Build Coastguard Worker if (dex_file_->GetTypeDescriptorView(interfaces->GetTypeItem(i).type_idx_) !=
1139*795d594fSAndroid Build Coastguard Worker orig_dex_file.GetTypeDescriptorView(current_interfaces->GetTypeItem(i).type_idx_)) {
1140*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED),
1141*795d594fSAndroid Build Coastguard Worker "Interfaces changed or re-ordered");
1142*795d594fSAndroid Build Coastguard Worker return false;
1143*795d594fSAndroid Build Coastguard Worker }
1144*795d594fSAndroid Build Coastguard Worker }
1145*795d594fSAndroid Build Coastguard Worker }
1146*795d594fSAndroid Build Coastguard Worker return true;
1147*795d594fSAndroid Build Coastguard Worker }
1148*795d594fSAndroid Build Coastguard Worker
CheckRedefinable()1149*795d594fSAndroid Build Coastguard Worker bool Redefiner::ClassRedefinition::CheckRedefinable() {
1150*795d594fSAndroid Build Coastguard Worker std::string err;
1151*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<1> hs(driver_->self_);
1152*795d594fSAndroid Build Coastguard Worker
1153*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> h_klass(hs.NewHandle(GetMirrorClass()));
1154*795d594fSAndroid Build Coastguard Worker jvmtiError res;
1155*795d594fSAndroid Build Coastguard Worker if (driver_->type_ == RedefinitionType::kStructural && this->IsStructuralRedefinition()) {
1156*795d594fSAndroid Build Coastguard Worker res = Redefiner::CanRedefineClass<RedefinitionType::kStructural>(h_klass, &err);
1157*795d594fSAndroid Build Coastguard Worker } else {
1158*795d594fSAndroid Build Coastguard Worker res = Redefiner::CanRedefineClass<RedefinitionType::kNormal>(h_klass, &err);
1159*795d594fSAndroid Build Coastguard Worker }
1160*795d594fSAndroid Build Coastguard Worker if (res != OK) {
1161*795d594fSAndroid Build Coastguard Worker RecordFailure(res, err);
1162*795d594fSAndroid Build Coastguard Worker return false;
1163*795d594fSAndroid Build Coastguard Worker } else {
1164*795d594fSAndroid Build Coastguard Worker return true;
1165*795d594fSAndroid Build Coastguard Worker }
1166*795d594fSAndroid Build Coastguard Worker }
1167*795d594fSAndroid Build Coastguard Worker
CheckRedefinitionIsValid()1168*795d594fSAndroid Build Coastguard Worker bool Redefiner::ClassRedefinition::CheckRedefinitionIsValid() {
1169*795d594fSAndroid Build Coastguard Worker return CheckClass() && CheckFields() && CheckMethods() && CheckRedefinable();
1170*795d594fSAndroid Build Coastguard Worker }
1171*795d594fSAndroid Build Coastguard Worker
1172*795d594fSAndroid Build Coastguard Worker class RedefinitionDataIter;
1173*795d594fSAndroid Build Coastguard Worker
1174*795d594fSAndroid Build Coastguard Worker // A wrapper that lets us hold onto the arbitrary sized data needed for redefinitions in a
1175*795d594fSAndroid Build Coastguard Worker // reasonable way. This adds no fields to the normal ObjectArray. By doing this we can avoid
1176*795d594fSAndroid Build Coastguard Worker // having to deal with the fact that we need to hold an arbitrary number of references live.
1177*795d594fSAndroid Build Coastguard Worker class RedefinitionDataHolder {
1178*795d594fSAndroid Build Coastguard Worker public:
1179*795d594fSAndroid Build Coastguard Worker enum DataSlot : int32_t {
1180*795d594fSAndroid Build Coastguard Worker kSlotSourceClassLoader = 0,
1181*795d594fSAndroid Build Coastguard Worker kSlotJavaDexFile = 1,
1182*795d594fSAndroid Build Coastguard Worker kSlotNewDexFileCookie = 2,
1183*795d594fSAndroid Build Coastguard Worker kSlotNewDexCache = 3,
1184*795d594fSAndroid Build Coastguard Worker kSlotMirrorClass = 4,
1185*795d594fSAndroid Build Coastguard Worker kSlotOrigDexFile = 5,
1186*795d594fSAndroid Build Coastguard Worker kSlotOldObsoleteMethods = 6,
1187*795d594fSAndroid Build Coastguard Worker kSlotOldDexCaches = 7,
1188*795d594fSAndroid Build Coastguard Worker kSlotNewClassObject = 8,
1189*795d594fSAndroid Build Coastguard Worker kSlotOldInstanceObjects = 9,
1190*795d594fSAndroid Build Coastguard Worker kSlotNewInstanceObjects = 10,
1191*795d594fSAndroid Build Coastguard Worker kSlotOldClasses = 11,
1192*795d594fSAndroid Build Coastguard Worker kSlotNewClasses = 12,
1193*795d594fSAndroid Build Coastguard Worker
1194*795d594fSAndroid Build Coastguard Worker // Must be last one.
1195*795d594fSAndroid Build Coastguard Worker kNumSlots = 13,
1196*795d594fSAndroid Build Coastguard Worker };
1197*795d594fSAndroid Build Coastguard Worker
1198*795d594fSAndroid Build Coastguard Worker // This needs to have a HandleScope passed in that is capable of creating a new Handle without
1199*795d594fSAndroid Build Coastguard Worker // overflowing. Only one handle will be created. This object has a lifetime identical to that of
1200*795d594fSAndroid Build Coastguard Worker // the passed in handle-scope.
RedefinitionDataHolder(art::StackHandleScope<1> * hs,art::Runtime * runtime,art::Thread * self,std::vector<Redefiner::ClassRedefinition> * redefinitions)1201*795d594fSAndroid Build Coastguard Worker RedefinitionDataHolder(art::StackHandleScope<1>* hs,
1202*795d594fSAndroid Build Coastguard Worker art::Runtime* runtime,
1203*795d594fSAndroid Build Coastguard Worker art::Thread* self,
1204*795d594fSAndroid Build Coastguard Worker std::vector<Redefiner::ClassRedefinition>* redefinitions)
1205*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) :
1206*795d594fSAndroid Build Coastguard Worker arr_(hs->NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
1207*795d594fSAndroid Build Coastguard Worker self,
1208*795d594fSAndroid Build Coastguard Worker art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Object>>(runtime->GetClassLinker()),
1209*795d594fSAndroid Build Coastguard Worker redefinitions->size() * kNumSlots))),
1210*795d594fSAndroid Build Coastguard Worker redefinitions_(redefinitions),
1211*795d594fSAndroid Build Coastguard Worker initialized_(redefinitions_->size(), false),
1212*795d594fSAndroid Build Coastguard Worker actually_structural_(redefinitions_->size(), false),
1213*795d594fSAndroid Build Coastguard Worker initial_structural_(redefinitions_->size(), false) {}
1214*795d594fSAndroid Build Coastguard Worker
1215*795d594fSAndroid Build Coastguard Worker ~RedefinitionDataHolder() REQUIRES_SHARED(art::Locks::mutator_lock_);
1216*795d594fSAndroid Build Coastguard Worker
IsNull() const1217*795d594fSAndroid Build Coastguard Worker bool IsNull() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1218*795d594fSAndroid Build Coastguard Worker return arr_.IsNull();
1219*795d594fSAndroid Build Coastguard Worker }
1220*795d594fSAndroid Build Coastguard Worker
GetSourceClassLoader(jint klass_index) const1221*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ClassLoader> GetSourceClassLoader(jint klass_index) const
1222*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1223*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::ClassLoader>::DownCast(
1224*795d594fSAndroid Build Coastguard Worker GetSlot(klass_index, kSlotSourceClassLoader));
1225*795d594fSAndroid Build Coastguard Worker }
GetJavaDexFile(jint klass_index) const1226*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> GetJavaDexFile(jint klass_index) const
1227*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1228*795d594fSAndroid Build Coastguard Worker return GetSlot(klass_index, kSlotJavaDexFile);
1229*795d594fSAndroid Build Coastguard Worker }
GetNewDexFileCookie(jint klass_index) const1230*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::LongArray> GetNewDexFileCookie(jint klass_index) const
1231*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1232*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::LongArray>::DownCast(
1233*795d594fSAndroid Build Coastguard Worker GetSlot(klass_index, kSlotNewDexFileCookie));
1234*795d594fSAndroid Build Coastguard Worker }
GetNewDexCache(jint klass_index) const1235*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::DexCache> GetNewDexCache(jint klass_index) const
1236*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1237*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::DexCache>::DownCast(GetSlot(klass_index, kSlotNewDexCache));
1238*795d594fSAndroid Build Coastguard Worker }
GetMirrorClass(jint klass_index) const1239*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> GetMirrorClass(jint klass_index) const
1240*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1241*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::Class>::DownCast(GetSlot(klass_index, kSlotMirrorClass));
1242*795d594fSAndroid Build Coastguard Worker }
1243*795d594fSAndroid Build Coastguard Worker
GetOriginalDexFile(jint klass_index) const1244*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> GetOriginalDexFile(jint klass_index) const
1245*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1246*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::Object>::DownCast(GetSlot(klass_index, kSlotOrigDexFile));
1247*795d594fSAndroid Build Coastguard Worker }
1248*795d594fSAndroid Build Coastguard Worker
GetOldObsoleteMethods(jint klass_index) const1249*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::PointerArray> GetOldObsoleteMethods(jint klass_index) const
1250*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1251*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::PointerArray>::DownCast(
1252*795d594fSAndroid Build Coastguard Worker GetSlot(klass_index, kSlotOldObsoleteMethods));
1253*795d594fSAndroid Build Coastguard Worker }
1254*795d594fSAndroid Build Coastguard Worker
GetOldDexCaches(jint klass_index) const1255*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> GetOldDexCaches(
1256*795d594fSAndroid Build Coastguard Worker jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1257*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>>::DownCast(
1258*795d594fSAndroid Build Coastguard Worker GetSlot(klass_index, kSlotOldDexCaches));
1259*795d594fSAndroid Build Coastguard Worker }
1260*795d594fSAndroid Build Coastguard Worker
GetNewClassObject(jint klass_index) const1261*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> GetNewClassObject(jint klass_index) const
1262*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1263*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::Class>::DownCast(GetSlot(klass_index, kSlotNewClassObject));
1264*795d594fSAndroid Build Coastguard Worker }
1265*795d594fSAndroid Build Coastguard Worker
GetOldInstanceObjects(jint klass_index) const1266*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetOldInstanceObjects(
1267*795d594fSAndroid Build Coastguard Worker jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1268*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>>::DownCast(
1269*795d594fSAndroid Build Coastguard Worker GetSlot(klass_index, kSlotOldInstanceObjects));
1270*795d594fSAndroid Build Coastguard Worker }
1271*795d594fSAndroid Build Coastguard Worker
GetNewInstanceObjects(jint klass_index) const1272*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetNewInstanceObjects(
1273*795d594fSAndroid Build Coastguard Worker jint klass_index) const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1274*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>>::DownCast(
1275*795d594fSAndroid Build Coastguard Worker GetSlot(klass_index, kSlotNewInstanceObjects));
1276*795d594fSAndroid Build Coastguard Worker }
GetOldClasses(jint klass_index) const1277*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetOldClasses(jint klass_index) const
1278*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1279*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>>::DownCast(
1280*795d594fSAndroid Build Coastguard Worker GetSlot(klass_index, kSlotOldClasses));
1281*795d594fSAndroid Build Coastguard Worker }
GetNewClasses(jint klass_index) const1282*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetNewClasses(jint klass_index) const
1283*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1284*795d594fSAndroid Build Coastguard Worker return art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>>::DownCast(
1285*795d594fSAndroid Build Coastguard Worker GetSlot(klass_index, kSlotNewClasses));
1286*795d594fSAndroid Build Coastguard Worker }
IsInitialized(jint klass_index)1287*795d594fSAndroid Build Coastguard Worker bool IsInitialized(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1288*795d594fSAndroid Build Coastguard Worker return initialized_[klass_index];
1289*795d594fSAndroid Build Coastguard Worker }
IsActuallyStructural(jint klass_index)1290*795d594fSAndroid Build Coastguard Worker bool IsActuallyStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1291*795d594fSAndroid Build Coastguard Worker return actually_structural_[klass_index];
1292*795d594fSAndroid Build Coastguard Worker }
1293*795d594fSAndroid Build Coastguard Worker
IsInitialStructural(jint klass_index)1294*795d594fSAndroid Build Coastguard Worker bool IsInitialStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1295*795d594fSAndroid Build Coastguard Worker return initial_structural_[klass_index];
1296*795d594fSAndroid Build Coastguard Worker }
1297*795d594fSAndroid Build Coastguard Worker
SetSourceClassLoader(jint klass_index,art::ObjPtr<art::mirror::ClassLoader> loader)1298*795d594fSAndroid Build Coastguard Worker void SetSourceClassLoader(jint klass_index, art::ObjPtr<art::mirror::ClassLoader> loader)
1299*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1300*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotSourceClassLoader, loader);
1301*795d594fSAndroid Build Coastguard Worker }
SetJavaDexFile(jint klass_index,art::ObjPtr<art::mirror::Object> dexfile)1302*795d594fSAndroid Build Coastguard Worker void SetJavaDexFile(jint klass_index, art::ObjPtr<art::mirror::Object> dexfile)
1303*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1304*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotJavaDexFile, dexfile);
1305*795d594fSAndroid Build Coastguard Worker }
SetNewDexFileCookie(jint klass_index,art::ObjPtr<art::mirror::LongArray> cookie)1306*795d594fSAndroid Build Coastguard Worker void SetNewDexFileCookie(jint klass_index, art::ObjPtr<art::mirror::LongArray> cookie)
1307*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1308*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotNewDexFileCookie, cookie);
1309*795d594fSAndroid Build Coastguard Worker }
SetNewDexCache(jint klass_index,art::ObjPtr<art::mirror::DexCache> cache)1310*795d594fSAndroid Build Coastguard Worker void SetNewDexCache(jint klass_index, art::ObjPtr<art::mirror::DexCache> cache)
1311*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1312*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotNewDexCache, cache);
1313*795d594fSAndroid Build Coastguard Worker }
SetMirrorClass(jint klass_index,art::ObjPtr<art::mirror::Class> klass)1314*795d594fSAndroid Build Coastguard Worker void SetMirrorClass(jint klass_index, art::ObjPtr<art::mirror::Class> klass)
1315*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1316*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotMirrorClass, klass);
1317*795d594fSAndroid Build Coastguard Worker }
SetOriginalDexFile(jint klass_index,art::ObjPtr<art::mirror::Object> bytes)1318*795d594fSAndroid Build Coastguard Worker void SetOriginalDexFile(jint klass_index, art::ObjPtr<art::mirror::Object> bytes)
1319*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1320*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotOrigDexFile, bytes);
1321*795d594fSAndroid Build Coastguard Worker }
SetOldObsoleteMethods(jint klass_index,art::ObjPtr<art::mirror::PointerArray> methods)1322*795d594fSAndroid Build Coastguard Worker void SetOldObsoleteMethods(jint klass_index, art::ObjPtr<art::mirror::PointerArray> methods)
1323*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1324*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotOldObsoleteMethods, methods);
1325*795d594fSAndroid Build Coastguard Worker }
SetOldDexCaches(jint klass_index,art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> caches)1326*795d594fSAndroid Build Coastguard Worker void SetOldDexCaches(jint klass_index,
1327*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> caches)
1328*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1329*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotOldDexCaches, caches);
1330*795d594fSAndroid Build Coastguard Worker }
1331*795d594fSAndroid Build Coastguard Worker
SetNewClassObject(jint klass_index,art::ObjPtr<art::mirror::Class> klass)1332*795d594fSAndroid Build Coastguard Worker void SetNewClassObject(jint klass_index, art::ObjPtr<art::mirror::Class> klass)
1333*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1334*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotNewClassObject, klass);
1335*795d594fSAndroid Build Coastguard Worker }
1336*795d594fSAndroid Build Coastguard Worker
SetOldInstanceObjects(jint klass_index,art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)1337*795d594fSAndroid Build Coastguard Worker void SetOldInstanceObjects(jint klass_index,
1338*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1339*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1340*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotOldInstanceObjects, objs);
1341*795d594fSAndroid Build Coastguard Worker }
SetNewInstanceObjects(jint klass_index,art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)1342*795d594fSAndroid Build Coastguard Worker void SetNewInstanceObjects(jint klass_index,
1343*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1344*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1345*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotNewInstanceObjects, objs);
1346*795d594fSAndroid Build Coastguard Worker }
SetOldClasses(jint klass_index,art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)1347*795d594fSAndroid Build Coastguard Worker void SetOldClasses(jint klass_index,
1348*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
1349*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1350*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotOldClasses, klasses);
1351*795d594fSAndroid Build Coastguard Worker }
SetNewClasses(jint klass_index,art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)1352*795d594fSAndroid Build Coastguard Worker void SetNewClasses(jint klass_index,
1353*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
1354*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1355*795d594fSAndroid Build Coastguard Worker SetSlot(klass_index, kSlotNewClasses, klasses);
1356*795d594fSAndroid Build Coastguard Worker }
SetInitialized(jint klass_index)1357*795d594fSAndroid Build Coastguard Worker void SetInitialized(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1358*795d594fSAndroid Build Coastguard Worker initialized_[klass_index] = true;
1359*795d594fSAndroid Build Coastguard Worker }
SetActuallyStructural(jint klass_index)1360*795d594fSAndroid Build Coastguard Worker void SetActuallyStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1361*795d594fSAndroid Build Coastguard Worker actually_structural_[klass_index] = true;
1362*795d594fSAndroid Build Coastguard Worker }
SetInitialStructural(jint klass_index)1363*795d594fSAndroid Build Coastguard Worker void SetInitialStructural(jint klass_index) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1364*795d594fSAndroid Build Coastguard Worker initial_structural_[klass_index] = true;
1365*795d594fSAndroid Build Coastguard Worker }
Length() const1366*795d594fSAndroid Build Coastguard Worker int32_t Length() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1367*795d594fSAndroid Build Coastguard Worker return arr_->GetLength() / kNumSlots;
1368*795d594fSAndroid Build Coastguard Worker }
1369*795d594fSAndroid Build Coastguard Worker
GetRedefinitions()1370*795d594fSAndroid Build Coastguard Worker std::vector<Redefiner::ClassRedefinition>* GetRedefinitions()
1371*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1372*795d594fSAndroid Build Coastguard Worker return redefinitions_;
1373*795d594fSAndroid Build Coastguard Worker }
1374*795d594fSAndroid Build Coastguard Worker
operator ==(const RedefinitionDataHolder & other) const1375*795d594fSAndroid Build Coastguard Worker bool operator==(const RedefinitionDataHolder& other) const
1376*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1377*795d594fSAndroid Build Coastguard Worker return arr_.Get() == other.arr_.Get();
1378*795d594fSAndroid Build Coastguard Worker }
1379*795d594fSAndroid Build Coastguard Worker
operator !=(const RedefinitionDataHolder & other) const1380*795d594fSAndroid Build Coastguard Worker bool operator!=(const RedefinitionDataHolder& other) const
1381*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1382*795d594fSAndroid Build Coastguard Worker return !(*this == other);
1383*795d594fSAndroid Build Coastguard Worker }
1384*795d594fSAndroid Build Coastguard Worker
1385*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter begin() REQUIRES_SHARED(art::Locks::mutator_lock_);
1386*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter end() REQUIRES_SHARED(art::Locks::mutator_lock_);
1387*795d594fSAndroid Build Coastguard Worker
1388*795d594fSAndroid Build Coastguard Worker private:
1389*795d594fSAndroid Build Coastguard Worker mutable art::Handle<art::mirror::ObjectArray<art::mirror::Object>> arr_;
1390*795d594fSAndroid Build Coastguard Worker std::vector<Redefiner::ClassRedefinition>* redefinitions_;
1391*795d594fSAndroid Build Coastguard Worker // Used to mark a particular redefinition as fully initialized.
1392*795d594fSAndroid Build Coastguard Worker std::vector<bool> initialized_;
1393*795d594fSAndroid Build Coastguard Worker // Used to mark a redefinition as 'actually' structural. That is either the redefinition is
1394*795d594fSAndroid Build Coastguard Worker // structural or a superclass is.
1395*795d594fSAndroid Build Coastguard Worker std::vector<bool> actually_structural_;
1396*795d594fSAndroid Build Coastguard Worker // Used to mark a redefinition as the initial structural redefinition. This redefinition will take
1397*795d594fSAndroid Build Coastguard Worker // care of updating all of its subtypes.
1398*795d594fSAndroid Build Coastguard Worker std::vector<bool> initial_structural_;
1399*795d594fSAndroid Build Coastguard Worker
GetSlot(jint klass_index,DataSlot slot) const1400*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> GetSlot(jint klass_index, DataSlot slot) const
1401*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1402*795d594fSAndroid Build Coastguard Worker DCHECK_LT(klass_index, Length());
1403*795d594fSAndroid Build Coastguard Worker return arr_->Get((kNumSlots * klass_index) + slot);
1404*795d594fSAndroid Build Coastguard Worker }
1405*795d594fSAndroid Build Coastguard Worker
SetSlot(jint klass_index,DataSlot slot,art::ObjPtr<art::mirror::Object> obj)1406*795d594fSAndroid Build Coastguard Worker void SetSlot(jint klass_index,
1407*795d594fSAndroid Build Coastguard Worker DataSlot slot,
1408*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1409*795d594fSAndroid Build Coastguard Worker DCHECK(!art::Runtime::Current()->IsActiveTransaction());
1410*795d594fSAndroid Build Coastguard Worker DCHECK_LT(klass_index, Length());
1411*795d594fSAndroid Build Coastguard Worker arr_->Set<false>((kNumSlots * klass_index) + slot, obj);
1412*795d594fSAndroid Build Coastguard Worker }
1413*795d594fSAndroid Build Coastguard Worker
1414*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(RedefinitionDataHolder);
1415*795d594fSAndroid Build Coastguard Worker };
1416*795d594fSAndroid Build Coastguard Worker
1417*795d594fSAndroid Build Coastguard Worker class RedefinitionDataIter {
1418*795d594fSAndroid Build Coastguard Worker public:
RedefinitionDataIter(int32_t idx,RedefinitionDataHolder & holder)1419*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter(int32_t idx, RedefinitionDataHolder& holder) : idx_(idx), holder_(holder) {}
1420*795d594fSAndroid Build Coastguard Worker
1421*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter(const RedefinitionDataIter&) = default;
1422*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter(RedefinitionDataIter&&) = default;
1423*795d594fSAndroid Build Coastguard Worker // Assignments are deleted because holder_ is a reference.
1424*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter& operator=(const RedefinitionDataIter&) = delete;
1425*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter& operator=(RedefinitionDataIter&&) = delete;
1426*795d594fSAndroid Build Coastguard Worker
operator ==(const RedefinitionDataIter & other) const1427*795d594fSAndroid Build Coastguard Worker bool operator==(const RedefinitionDataIter& other) const
1428*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1429*795d594fSAndroid Build Coastguard Worker return idx_ == other.idx_ && holder_ == other.holder_;
1430*795d594fSAndroid Build Coastguard Worker }
1431*795d594fSAndroid Build Coastguard Worker
operator !=(const RedefinitionDataIter & other) const1432*795d594fSAndroid Build Coastguard Worker bool operator!=(const RedefinitionDataIter& other) const
1433*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1434*795d594fSAndroid Build Coastguard Worker return !(*this == other);
1435*795d594fSAndroid Build Coastguard Worker }
1436*795d594fSAndroid Build Coastguard Worker
operator ++()1437*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter operator++() { // Value after modification.
1438*795d594fSAndroid Build Coastguard Worker idx_++;
1439*795d594fSAndroid Build Coastguard Worker return *this;
1440*795d594fSAndroid Build Coastguard Worker }
1441*795d594fSAndroid Build Coastguard Worker
operator ++(int)1442*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter operator++(int) {
1443*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter temp = *this;
1444*795d594fSAndroid Build Coastguard Worker idx_++;
1445*795d594fSAndroid Build Coastguard Worker return temp;
1446*795d594fSAndroid Build Coastguard Worker }
1447*795d594fSAndroid Build Coastguard Worker
operator +(ssize_t delta) const1448*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter operator+(ssize_t delta) const {
1449*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter temp = *this;
1450*795d594fSAndroid Build Coastguard Worker temp += delta;
1451*795d594fSAndroid Build Coastguard Worker return temp;
1452*795d594fSAndroid Build Coastguard Worker }
1453*795d594fSAndroid Build Coastguard Worker
operator +=(ssize_t delta)1454*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter& operator+=(ssize_t delta) {
1455*795d594fSAndroid Build Coastguard Worker idx_ += delta;
1456*795d594fSAndroid Build Coastguard Worker return *this;
1457*795d594fSAndroid Build Coastguard Worker }
1458*795d594fSAndroid Build Coastguard Worker
1459*795d594fSAndroid Build Coastguard Worker // Compat for STL iterators.
operator *()1460*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter& operator*() {
1461*795d594fSAndroid Build Coastguard Worker return *this;
1462*795d594fSAndroid Build Coastguard Worker }
1463*795d594fSAndroid Build Coastguard Worker
GetRedefinition()1464*795d594fSAndroid Build Coastguard Worker Redefiner::ClassRedefinition& GetRedefinition() REQUIRES_SHARED(art::Locks::mutator_lock_) {
1465*795d594fSAndroid Build Coastguard Worker return (*holder_.GetRedefinitions())[idx_];
1466*795d594fSAndroid Build Coastguard Worker }
1467*795d594fSAndroid Build Coastguard Worker
GetHolder()1468*795d594fSAndroid Build Coastguard Worker RedefinitionDataHolder& GetHolder() {
1469*795d594fSAndroid Build Coastguard Worker return holder_;
1470*795d594fSAndroid Build Coastguard Worker }
1471*795d594fSAndroid Build Coastguard Worker
GetSourceClassLoader() const1472*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ClassLoader> GetSourceClassLoader() const
1473*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1474*795d594fSAndroid Build Coastguard Worker return holder_.GetSourceClassLoader(idx_);
1475*795d594fSAndroid Build Coastguard Worker }
GetJavaDexFile() const1476*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> GetJavaDexFile() const
1477*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1478*795d594fSAndroid Build Coastguard Worker return holder_.GetJavaDexFile(idx_);
1479*795d594fSAndroid Build Coastguard Worker }
GetNewDexFileCookie() const1480*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::LongArray> GetNewDexFileCookie() const
1481*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1482*795d594fSAndroid Build Coastguard Worker return holder_.GetNewDexFileCookie(idx_);
1483*795d594fSAndroid Build Coastguard Worker }
GetNewDexCache() const1484*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::DexCache> GetNewDexCache() const
1485*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1486*795d594fSAndroid Build Coastguard Worker return holder_.GetNewDexCache(idx_);
1487*795d594fSAndroid Build Coastguard Worker }
GetMirrorClass() const1488*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> GetMirrorClass() const
1489*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1490*795d594fSAndroid Build Coastguard Worker return holder_.GetMirrorClass(idx_);
1491*795d594fSAndroid Build Coastguard Worker }
GetOriginalDexFile() const1492*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> GetOriginalDexFile() const
1493*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1494*795d594fSAndroid Build Coastguard Worker return holder_.GetOriginalDexFile(idx_);
1495*795d594fSAndroid Build Coastguard Worker }
GetOldObsoleteMethods() const1496*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::PointerArray> GetOldObsoleteMethods() const
1497*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1498*795d594fSAndroid Build Coastguard Worker return holder_.GetOldObsoleteMethods(idx_);
1499*795d594fSAndroid Build Coastguard Worker }
GetOldDexCaches() const1500*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> GetOldDexCaches() const
1501*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1502*795d594fSAndroid Build Coastguard Worker return holder_.GetOldDexCaches(idx_);
1503*795d594fSAndroid Build Coastguard Worker }
1504*795d594fSAndroid Build Coastguard Worker
GetNewClassObject() const1505*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> GetNewClassObject() const
1506*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1507*795d594fSAndroid Build Coastguard Worker return holder_.GetNewClassObject(idx_);
1508*795d594fSAndroid Build Coastguard Worker }
1509*795d594fSAndroid Build Coastguard Worker
GetOldInstanceObjects() const1510*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetOldInstanceObjects() const
1511*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1512*795d594fSAndroid Build Coastguard Worker return holder_.GetOldInstanceObjects(idx_);
1513*795d594fSAndroid Build Coastguard Worker }
GetNewInstanceObjects() const1514*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> GetNewInstanceObjects() const
1515*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1516*795d594fSAndroid Build Coastguard Worker return holder_.GetNewInstanceObjects(idx_);
1517*795d594fSAndroid Build Coastguard Worker }
GetOldClasses() const1518*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetOldClasses() const
1519*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1520*795d594fSAndroid Build Coastguard Worker return holder_.GetOldClasses(idx_);
1521*795d594fSAndroid Build Coastguard Worker }
GetNewClasses() const1522*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> GetNewClasses() const
1523*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1524*795d594fSAndroid Build Coastguard Worker return holder_.GetNewClasses(idx_);
1525*795d594fSAndroid Build Coastguard Worker }
IsInitialized() const1526*795d594fSAndroid Build Coastguard Worker bool IsInitialized() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1527*795d594fSAndroid Build Coastguard Worker return holder_.IsInitialized(idx_);
1528*795d594fSAndroid Build Coastguard Worker }
IsActuallyStructural() const1529*795d594fSAndroid Build Coastguard Worker bool IsActuallyStructural() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1530*795d594fSAndroid Build Coastguard Worker return holder_.IsActuallyStructural(idx_);
1531*795d594fSAndroid Build Coastguard Worker }
IsInitialStructural() const1532*795d594fSAndroid Build Coastguard Worker bool IsInitialStructural() const REQUIRES_SHARED(art::Locks::mutator_lock_) {
1533*795d594fSAndroid Build Coastguard Worker return holder_.IsInitialStructural(idx_);
1534*795d594fSAndroid Build Coastguard Worker }
GetIndex() const1535*795d594fSAndroid Build Coastguard Worker int32_t GetIndex() const {
1536*795d594fSAndroid Build Coastguard Worker return idx_;
1537*795d594fSAndroid Build Coastguard Worker }
1538*795d594fSAndroid Build Coastguard Worker
SetSourceClassLoader(art::mirror::ClassLoader * loader)1539*795d594fSAndroid Build Coastguard Worker void SetSourceClassLoader(art::mirror::ClassLoader* loader)
1540*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1541*795d594fSAndroid Build Coastguard Worker holder_.SetSourceClassLoader(idx_, loader);
1542*795d594fSAndroid Build Coastguard Worker }
SetJavaDexFile(art::ObjPtr<art::mirror::Object> dexfile)1543*795d594fSAndroid Build Coastguard Worker void SetJavaDexFile(art::ObjPtr<art::mirror::Object> dexfile)
1544*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1545*795d594fSAndroid Build Coastguard Worker holder_.SetJavaDexFile(idx_, dexfile);
1546*795d594fSAndroid Build Coastguard Worker }
SetNewDexFileCookie(art::ObjPtr<art::mirror::LongArray> cookie)1547*795d594fSAndroid Build Coastguard Worker void SetNewDexFileCookie(art::ObjPtr<art::mirror::LongArray> cookie)
1548*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1549*795d594fSAndroid Build Coastguard Worker holder_.SetNewDexFileCookie(idx_, cookie);
1550*795d594fSAndroid Build Coastguard Worker }
SetNewDexCache(art::ObjPtr<art::mirror::DexCache> cache)1551*795d594fSAndroid Build Coastguard Worker void SetNewDexCache(art::ObjPtr<art::mirror::DexCache> cache)
1552*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1553*795d594fSAndroid Build Coastguard Worker holder_.SetNewDexCache(idx_, cache);
1554*795d594fSAndroid Build Coastguard Worker }
SetMirrorClass(art::ObjPtr<art::mirror::Class> klass)1555*795d594fSAndroid Build Coastguard Worker void SetMirrorClass(art::ObjPtr<art::mirror::Class> klass)
1556*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1557*795d594fSAndroid Build Coastguard Worker holder_.SetMirrorClass(idx_, klass);
1558*795d594fSAndroid Build Coastguard Worker }
SetOriginalDexFile(art::ObjPtr<art::mirror::Object> bytes)1559*795d594fSAndroid Build Coastguard Worker void SetOriginalDexFile(art::ObjPtr<art::mirror::Object> bytes)
1560*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1561*795d594fSAndroid Build Coastguard Worker holder_.SetOriginalDexFile(idx_, bytes);
1562*795d594fSAndroid Build Coastguard Worker }
SetOldObsoleteMethods(art::ObjPtr<art::mirror::PointerArray> methods)1563*795d594fSAndroid Build Coastguard Worker void SetOldObsoleteMethods(art::ObjPtr<art::mirror::PointerArray> methods)
1564*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1565*795d594fSAndroid Build Coastguard Worker holder_.SetOldObsoleteMethods(idx_, methods);
1566*795d594fSAndroid Build Coastguard Worker }
SetOldDexCaches(art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> caches)1567*795d594fSAndroid Build Coastguard Worker void SetOldDexCaches(art::ObjPtr<art::mirror::ObjectArray<art::mirror::DexCache>> caches)
1568*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1569*795d594fSAndroid Build Coastguard Worker holder_.SetOldDexCaches(idx_, caches);
1570*795d594fSAndroid Build Coastguard Worker }
SetNewClassObject(art::ObjPtr<art::mirror::Class> klass)1571*795d594fSAndroid Build Coastguard Worker void SetNewClassObject(art::ObjPtr<art::mirror::Class> klass)
1572*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1573*795d594fSAndroid Build Coastguard Worker holder_.SetNewClassObject(idx_, klass);
1574*795d594fSAndroid Build Coastguard Worker }
SetOldInstanceObjects(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)1575*795d594fSAndroid Build Coastguard Worker void SetOldInstanceObjects(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1576*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1577*795d594fSAndroid Build Coastguard Worker holder_.SetOldInstanceObjects(idx_, objs);
1578*795d594fSAndroid Build Coastguard Worker }
SetNewInstanceObjects(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)1579*795d594fSAndroid Build Coastguard Worker void SetNewInstanceObjects(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> objs)
1580*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1581*795d594fSAndroid Build Coastguard Worker holder_.SetNewInstanceObjects(idx_, objs);
1582*795d594fSAndroid Build Coastguard Worker }
SetOldClasses(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)1583*795d594fSAndroid Build Coastguard Worker void SetOldClasses(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
1584*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1585*795d594fSAndroid Build Coastguard Worker holder_.SetOldClasses(idx_, klasses);
1586*795d594fSAndroid Build Coastguard Worker }
SetNewClasses(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)1587*795d594fSAndroid Build Coastguard Worker void SetNewClasses(art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> klasses)
1588*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1589*795d594fSAndroid Build Coastguard Worker holder_.SetNewClasses(idx_, klasses);
1590*795d594fSAndroid Build Coastguard Worker }
SetInitialized()1591*795d594fSAndroid Build Coastguard Worker void SetInitialized() REQUIRES_SHARED(art::Locks::mutator_lock_) {
1592*795d594fSAndroid Build Coastguard Worker holder_.SetInitialized(idx_);
1593*795d594fSAndroid Build Coastguard Worker }
SetActuallyStructural()1594*795d594fSAndroid Build Coastguard Worker void SetActuallyStructural() REQUIRES_SHARED(art::Locks::mutator_lock_) {
1595*795d594fSAndroid Build Coastguard Worker holder_.SetActuallyStructural(idx_);
1596*795d594fSAndroid Build Coastguard Worker }
SetInitialStructural()1597*795d594fSAndroid Build Coastguard Worker void SetInitialStructural() REQUIRES_SHARED(art::Locks::mutator_lock_) {
1598*795d594fSAndroid Build Coastguard Worker holder_.SetInitialStructural(idx_);
1599*795d594fSAndroid Build Coastguard Worker }
1600*795d594fSAndroid Build Coastguard Worker
1601*795d594fSAndroid Build Coastguard Worker private:
1602*795d594fSAndroid Build Coastguard Worker int32_t idx_;
1603*795d594fSAndroid Build Coastguard Worker RedefinitionDataHolder& holder_;
1604*795d594fSAndroid Build Coastguard Worker };
1605*795d594fSAndroid Build Coastguard Worker
begin()1606*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter RedefinitionDataHolder::begin() {
1607*795d594fSAndroid Build Coastguard Worker return RedefinitionDataIter(0, *this);
1608*795d594fSAndroid Build Coastguard Worker }
1609*795d594fSAndroid Build Coastguard Worker
end()1610*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter RedefinitionDataHolder::end() {
1611*795d594fSAndroid Build Coastguard Worker return RedefinitionDataIter(Length(), *this);
1612*795d594fSAndroid Build Coastguard Worker }
1613*795d594fSAndroid Build Coastguard Worker
~RedefinitionDataHolder()1614*795d594fSAndroid Build Coastguard Worker RedefinitionDataHolder::~RedefinitionDataHolder() {
1615*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
1616*795d594fSAndroid Build Coastguard Worker art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
1617*795d594fSAndroid Build Coastguard Worker for (RedefinitionDataIter data = begin(); data != end(); ++data) {
1618*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::DexCache> dex_cache = data.GetNewDexCache();
1619*795d594fSAndroid Build Coastguard Worker // When redefinition fails, the dex file will be deleted in the
1620*795d594fSAndroid Build Coastguard Worker // `ClassRedefinition` destructor. To avoid having a heap `DexCache` pointing
1621*795d594fSAndroid Build Coastguard Worker // to a dangling pointer, we clear the entries of those dex caches that are
1622*795d594fSAndroid Build Coastguard Worker // not registered in the runtime.
1623*795d594fSAndroid Build Coastguard Worker if (dex_cache != nullptr &&
1624*795d594fSAndroid Build Coastguard Worker dex_cache->GetDexFile() != nullptr &&
1625*795d594fSAndroid Build Coastguard Worker !cl->IsDexFileRegistered(self, *dex_cache->GetDexFile())) {
1626*795d594fSAndroid Build Coastguard Worker dex_cache->ResetNativeArrays();
1627*795d594fSAndroid Build Coastguard Worker dex_cache->SetDexFile(nullptr);
1628*795d594fSAndroid Build Coastguard Worker }
1629*795d594fSAndroid Build Coastguard Worker }
1630*795d594fSAndroid Build Coastguard Worker }
1631*795d594fSAndroid Build Coastguard Worker
CheckVerification(const RedefinitionDataIter & iter)1632*795d594fSAndroid Build Coastguard Worker bool Redefiner::ClassRedefinition::CheckVerification(const RedefinitionDataIter& iter) {
1633*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
1634*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<3> hs(driver_->self_);
1635*795d594fSAndroid Build Coastguard Worker std::string error;
1636*795d594fSAndroid Build Coastguard Worker // TODO Make verification log level lower
1637*795d594fSAndroid Build Coastguard Worker art::verifier::FailureKind failure =
1638*795d594fSAndroid Build Coastguard Worker art::verifier::ClassVerifier::VerifyClass(driver_->self_,
1639*795d594fSAndroid Build Coastguard Worker /*verifier_deps=*/nullptr,
1640*795d594fSAndroid Build Coastguard Worker dex_file_.get(),
1641*795d594fSAndroid Build Coastguard Worker hs.NewHandle(iter.GetNewClassObject() != nullptr
1642*795d594fSAndroid Build Coastguard Worker ? iter.GetNewClassObject()
1643*795d594fSAndroid Build Coastguard Worker : iter.GetMirrorClass()),
1644*795d594fSAndroid Build Coastguard Worker hs.NewHandle(iter.GetNewDexCache()),
1645*795d594fSAndroid Build Coastguard Worker hs.NewHandle(GetClassLoader()),
1646*795d594fSAndroid Build Coastguard Worker /*class_def=*/ dex_file_->GetClassDef(0),
1647*795d594fSAndroid Build Coastguard Worker /*callbacks=*/ nullptr,
1648*795d594fSAndroid Build Coastguard Worker /*log_level=*/
1649*795d594fSAndroid Build Coastguard Worker art::verifier::HardFailLogMode::kLogWarning,
1650*795d594fSAndroid Build Coastguard Worker art::Runtime::Current()->GetTargetSdkVersion(),
1651*795d594fSAndroid Build Coastguard Worker &error);
1652*795d594fSAndroid Build Coastguard Worker if (failure == art::verifier::FailureKind::kHardFailure) {
1653*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(FAILS_VERIFICATION), "Failed to verify class. Error was: " + error);
1654*795d594fSAndroid Build Coastguard Worker return false;
1655*795d594fSAndroid Build Coastguard Worker }
1656*795d594fSAndroid Build Coastguard Worker return true;
1657*795d594fSAndroid Build Coastguard Worker }
1658*795d594fSAndroid Build Coastguard Worker
1659*795d594fSAndroid Build Coastguard Worker // Looks through the previously allocated cookies to see if we need to update them with another new
1660*795d594fSAndroid Build Coastguard Worker // dexfile. This is so that even if multiple classes with the same classloader are redefined at
1661*795d594fSAndroid Build Coastguard Worker // once they are all added to the classloader.
AllocateAndRememberNewDexFileCookie(art::Handle<art::mirror::ClassLoader> source_class_loader,art::Handle<art::mirror::Object> dex_file_obj,RedefinitionDataIter * cur_data)1662*795d594fSAndroid Build Coastguard Worker bool Redefiner::ClassRedefinition::AllocateAndRememberNewDexFileCookie(
1663*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::ClassLoader> source_class_loader,
1664*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Object> dex_file_obj,
1665*795d594fSAndroid Build Coastguard Worker /*out*/RedefinitionDataIter* cur_data) {
1666*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<2> hs(driver_->self_);
1667*795d594fSAndroid Build Coastguard Worker art::MutableHandle<art::mirror::LongArray> old_cookie(
1668*795d594fSAndroid Build Coastguard Worker hs.NewHandle<art::mirror::LongArray>(nullptr));
1669*795d594fSAndroid Build Coastguard Worker bool has_older_cookie = false;
1670*795d594fSAndroid Build Coastguard Worker // See if we already have a cookie that a previous redefinition got from the same classloader
1671*795d594fSAndroid Build Coastguard Worker // and the same JavaDex file.
1672*795d594fSAndroid Build Coastguard Worker for (auto old_data = cur_data->GetHolder().begin(); old_data != *cur_data; ++old_data) {
1673*795d594fSAndroid Build Coastguard Worker if (old_data.GetSourceClassLoader() == source_class_loader.Get() &&
1674*795d594fSAndroid Build Coastguard Worker old_data.GetJavaDexFile() == dex_file_obj.Get()) {
1675*795d594fSAndroid Build Coastguard Worker // Since every instance of this JavaDex file should have the same cookie associated with it we
1676*795d594fSAndroid Build Coastguard Worker // can stop looking here.
1677*795d594fSAndroid Build Coastguard Worker has_older_cookie = true;
1678*795d594fSAndroid Build Coastguard Worker old_cookie.Assign(old_data.GetNewDexFileCookie());
1679*795d594fSAndroid Build Coastguard Worker break;
1680*795d594fSAndroid Build Coastguard Worker }
1681*795d594fSAndroid Build Coastguard Worker }
1682*795d594fSAndroid Build Coastguard Worker if (old_cookie.IsNull()) {
1683*795d594fSAndroid Build Coastguard Worker // No older cookie. Get it directly from the dex_file_obj
1684*795d594fSAndroid Build Coastguard Worker // We should not have seen this classloader elsewhere.
1685*795d594fSAndroid Build Coastguard Worker CHECK(!has_older_cookie);
1686*795d594fSAndroid Build Coastguard Worker old_cookie.Assign(ClassLoaderHelper::GetDexFileCookie(dex_file_obj));
1687*795d594fSAndroid Build Coastguard Worker }
1688*795d594fSAndroid Build Coastguard Worker // Use the old cookie to generate the new one with the new DexFile* added in.
1689*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::LongArray>
1690*795d594fSAndroid Build Coastguard Worker new_cookie(hs.NewHandle(ClassLoaderHelper::AllocateNewDexFileCookie(driver_->self_,
1691*795d594fSAndroid Build Coastguard Worker old_cookie,
1692*795d594fSAndroid Build Coastguard Worker dex_file_.get())));
1693*795d594fSAndroid Build Coastguard Worker // Make sure the allocation worked.
1694*795d594fSAndroid Build Coastguard Worker if (new_cookie.IsNull()) {
1695*795d594fSAndroid Build Coastguard Worker return false;
1696*795d594fSAndroid Build Coastguard Worker }
1697*795d594fSAndroid Build Coastguard Worker
1698*795d594fSAndroid Build Coastguard Worker // Save the cookie.
1699*795d594fSAndroid Build Coastguard Worker cur_data->SetNewDexFileCookie(new_cookie.Get());
1700*795d594fSAndroid Build Coastguard Worker // If there are other copies of the same classloader and the same JavaDex file we need to
1701*795d594fSAndroid Build Coastguard Worker // make sure that we all have the same cookie.
1702*795d594fSAndroid Build Coastguard Worker if (has_older_cookie) {
1703*795d594fSAndroid Build Coastguard Worker for (auto old_data = cur_data->GetHolder().begin(); old_data != *cur_data; ++old_data) {
1704*795d594fSAndroid Build Coastguard Worker // We will let the GC take care of the cookie we allocated for this one.
1705*795d594fSAndroid Build Coastguard Worker if (old_data.GetSourceClassLoader() == source_class_loader.Get() &&
1706*795d594fSAndroid Build Coastguard Worker old_data.GetJavaDexFile() == dex_file_obj.Get()) {
1707*795d594fSAndroid Build Coastguard Worker old_data.SetNewDexFileCookie(new_cookie.Get());
1708*795d594fSAndroid Build Coastguard Worker }
1709*795d594fSAndroid Build Coastguard Worker }
1710*795d594fSAndroid Build Coastguard Worker }
1711*795d594fSAndroid Build Coastguard Worker
1712*795d594fSAndroid Build Coastguard Worker return true;
1713*795d594fSAndroid Build Coastguard Worker }
1714*795d594fSAndroid Build Coastguard Worker
CompareClasses(art::ObjPtr<art::mirror::Class> l,art::ObjPtr<art::mirror::Class> r)1715*795d594fSAndroid Build Coastguard Worker bool CompareClasses(art::ObjPtr<art::mirror::Class> l, art::ObjPtr<art::mirror::Class> r)
1716*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1717*795d594fSAndroid Build Coastguard Worker auto parents = [](art::ObjPtr<art::mirror::Class> c) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1718*795d594fSAndroid Build Coastguard Worker uint32_t res = 0;
1719*795d594fSAndroid Build Coastguard Worker while (!c->IsObjectClass()) {
1720*795d594fSAndroid Build Coastguard Worker res++;
1721*795d594fSAndroid Build Coastguard Worker c = c->GetSuperClass();
1722*795d594fSAndroid Build Coastguard Worker }
1723*795d594fSAndroid Build Coastguard Worker return res;
1724*795d594fSAndroid Build Coastguard Worker };
1725*795d594fSAndroid Build Coastguard Worker return parents(l.Ptr()) < parents(r.Ptr());
1726*795d594fSAndroid Build Coastguard Worker }
1727*795d594fSAndroid Build Coastguard Worker
CollectAndCreateNewInstances(RedefinitionDataIter * cur_data)1728*795d594fSAndroid Build Coastguard Worker bool Redefiner::ClassRedefinition::CollectAndCreateNewInstances(
1729*795d594fSAndroid Build Coastguard Worker /*out*/ RedefinitionDataIter* cur_data) {
1730*795d594fSAndroid Build Coastguard Worker if (!cur_data->IsInitialStructural()) {
1731*795d594fSAndroid Build Coastguard Worker // An earlier structural redefinition already remade all the instances.
1732*795d594fSAndroid Build Coastguard Worker return true;
1733*795d594fSAndroid Build Coastguard Worker }
1734*795d594fSAndroid Build Coastguard Worker art::gc::Heap* heap = driver_->runtime_->GetHeap();
1735*795d594fSAndroid Build Coastguard Worker art::VariableSizedHandleScope hs(driver_->self_);
1736*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> old_klass(hs.NewHandle(cur_data->GetMirrorClass()));
1737*795d594fSAndroid Build Coastguard Worker std::vector<art::Handle<art::mirror::Object>> old_instances;
1738*795d594fSAndroid Build Coastguard Worker auto is_instance = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1739*795d594fSAndroid Build Coastguard Worker return obj->InstanceOf(old_klass.Get());
1740*795d594fSAndroid Build Coastguard Worker };
1741*795d594fSAndroid Build Coastguard Worker heap->VisitObjects([&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1742*795d594fSAndroid Build Coastguard Worker if (is_instance(obj)) {
1743*795d594fSAndroid Build Coastguard Worker old_instances.push_back(hs.NewHandle(obj));
1744*795d594fSAndroid Build Coastguard Worker }
1745*795d594fSAndroid Build Coastguard Worker });
1746*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Collected " << old_instances.size() << " instances to recreate!";
1747*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::ObjectArray<art::mirror::Class>> old_classes_arr(
1748*795d594fSAndroid Build Coastguard Worker hs.NewHandle(cur_data->GetOldClasses()));
1749*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::ObjectArray<art::mirror::Class>> new_classes_arr(
1750*795d594fSAndroid Build Coastguard Worker hs.NewHandle(cur_data->GetNewClasses()));
1751*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(old_classes_arr->GetLength(), new_classes_arr->GetLength());
1752*795d594fSAndroid Build Coastguard Worker DCHECK_GT(old_classes_arr->GetLength(), 0);
1753*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> obj_array_class(
1754*795d594fSAndroid Build Coastguard Worker hs.NewHandle(art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Object>>(
1755*795d594fSAndroid Build Coastguard Worker driver_->runtime_->GetClassLinker())));
1756*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::ObjectArray<art::mirror::Object>> old_instances_arr(
1757*795d594fSAndroid Build Coastguard Worker hs.NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
1758*795d594fSAndroid Build Coastguard Worker driver_->self_, obj_array_class.Get(), old_instances.size())));
1759*795d594fSAndroid Build Coastguard Worker if (old_instances_arr.IsNull()) {
1760*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
1761*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
1762*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate old_instance arrays!");
1763*795d594fSAndroid Build Coastguard Worker return false;
1764*795d594fSAndroid Build Coastguard Worker }
1765*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < old_instances.size(); ++i) {
1766*795d594fSAndroid Build Coastguard Worker old_instances_arr->Set(i, old_instances[i].Get());
1767*795d594fSAndroid Build Coastguard Worker }
1768*795d594fSAndroid Build Coastguard Worker cur_data->SetOldInstanceObjects(old_instances_arr.Get());
1769*795d594fSAndroid Build Coastguard Worker
1770*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::ObjectArray<art::mirror::Object>> new_instances_arr(
1771*795d594fSAndroid Build Coastguard Worker hs.NewHandle(art::mirror::ObjectArray<art::mirror::Object>::Alloc(
1772*795d594fSAndroid Build Coastguard Worker driver_->self_, obj_array_class.Get(), old_instances.size())));
1773*795d594fSAndroid Build Coastguard Worker if (new_instances_arr.IsNull()) {
1774*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
1775*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
1776*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate new_instance arrays!");
1777*795d594fSAndroid Build Coastguard Worker return false;
1778*795d594fSAndroid Build Coastguard Worker }
1779*795d594fSAndroid Build Coastguard Worker for (auto pair : art::ZipCount(art::IterationRange(old_instances.begin(), old_instances.end()))) {
1780*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Object> hinstance(pair.first);
1781*795d594fSAndroid Build Coastguard Worker int32_t i = pair.second;
1782*795d594fSAndroid Build Coastguard Worker auto iterator = art::ZipLeft(old_classes_arr.Iterate<art::mirror::Class>(),
1783*795d594fSAndroid Build Coastguard Worker new_classes_arr.Iterate<art::mirror::Class>());
1784*795d594fSAndroid Build Coastguard Worker auto it = std::find_if(iterator.begin(),
1785*795d594fSAndroid Build Coastguard Worker iterator.end(),
1786*795d594fSAndroid Build Coastguard Worker [&](auto class_pair) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1787*795d594fSAndroid Build Coastguard Worker return class_pair.first == hinstance->GetClass();
1788*795d594fSAndroid Build Coastguard Worker });
1789*795d594fSAndroid Build Coastguard Worker DCHECK(it != iterator.end()) << "Unable to find class pair for "
1790*795d594fSAndroid Build Coastguard Worker << hinstance->GetClass()->PrettyClass() << " (instance " << i
1791*795d594fSAndroid Build Coastguard Worker << ")";
1792*795d594fSAndroid Build Coastguard Worker auto [_, new_type] = *it;
1793*795d594fSAndroid Build Coastguard Worker // Make sure when allocating the new instance we don't add it's finalizer since we will directly
1794*795d594fSAndroid Build Coastguard Worker // replace the old object in the finalizer reference. If we added it here to we would call
1795*795d594fSAndroid Build Coastguard Worker // finalize twice.
1796*795d594fSAndroid Build Coastguard Worker // NB If a type is changed from being non-finalizable to finalizable the finalizers on any
1797*795d594fSAndroid Build Coastguard Worker // objects created before the redefine will never be called. This is (sort of) allowable by
1798*795d594fSAndroid Build Coastguard Worker // the spec and greatly simplifies implementation.
1799*795d594fSAndroid Build Coastguard Worker // TODO Make it so we will always call all finalizers, even if the object when it was created
1800*795d594fSAndroid Build Coastguard Worker // wasn't finalizable. To do this we need to be careful of handling failure correctly and making
1801*795d594fSAndroid Build Coastguard Worker // sure that objects aren't finalized multiple times and that instances of failed redefinitions
1802*795d594fSAndroid Build Coastguard Worker // aren't finalized.
1803*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> new_instance(
1804*795d594fSAndroid Build Coastguard Worker new_type->Alloc</*kIsInstrumented=*/true,
1805*795d594fSAndroid Build Coastguard Worker art::mirror::Class::AddFinalizer::kNoAddFinalizer,
1806*795d594fSAndroid Build Coastguard Worker /*kCheckAddFinalizer=*/false>(
1807*795d594fSAndroid Build Coastguard Worker driver_->self_, driver_->runtime_->GetHeap()->GetCurrentAllocator()));
1808*795d594fSAndroid Build Coastguard Worker if (new_instance.IsNull()) {
1809*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
1810*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
1811*795d594fSAndroid Build Coastguard Worker std::string msg(
1812*795d594fSAndroid Build Coastguard Worker StringPrintf("Could not allocate instance %d of %zu", i, old_instances.size()));
1813*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(OUT_OF_MEMORY), msg);
1814*795d594fSAndroid Build Coastguard Worker return false;
1815*795d594fSAndroid Build Coastguard Worker }
1816*795d594fSAndroid Build Coastguard Worker new_instances_arr->Set(i, new_instance);
1817*795d594fSAndroid Build Coastguard Worker }
1818*795d594fSAndroid Build Coastguard Worker cur_data->SetNewInstanceObjects(new_instances_arr.Get());
1819*795d594fSAndroid Build Coastguard Worker return true;
1820*795d594fSAndroid Build Coastguard Worker }
1821*795d594fSAndroid Build Coastguard Worker
FinishRemainingCommonAllocations(RedefinitionDataIter * cur_data)1822*795d594fSAndroid Build Coastguard Worker bool Redefiner::ClassRedefinition::FinishRemainingCommonAllocations(
1823*795d594fSAndroid Build Coastguard Worker /*out*/RedefinitionDataIter* cur_data) {
1824*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<2> hs(driver_->self_);
1825*795d594fSAndroid Build Coastguard Worker cur_data->SetMirrorClass(GetMirrorClass());
1826*795d594fSAndroid Build Coastguard Worker // This shouldn't allocate
1827*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::ClassLoader> loader(hs.NewHandle(GetClassLoader()));
1828*795d594fSAndroid Build Coastguard Worker // The bootclasspath is handled specially so it doesn't have a j.l.DexFile.
1829*795d594fSAndroid Build Coastguard Worker if (!art::ClassLinker::IsBootClassLoader(loader.Get())) {
1830*795d594fSAndroid Build Coastguard Worker cur_data->SetSourceClassLoader(loader.Get());
1831*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Object> dex_file_obj(hs.NewHandle(
1832*795d594fSAndroid Build Coastguard Worker ClassLoaderHelper::FindSourceDexFileObject(driver_->self_, loader)));
1833*795d594fSAndroid Build Coastguard Worker cur_data->SetJavaDexFile(dex_file_obj.Get());
1834*795d594fSAndroid Build Coastguard Worker if (dex_file_obj == nullptr) {
1835*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(INTERNAL), "Unable to find dex file!");
1836*795d594fSAndroid Build Coastguard Worker return false;
1837*795d594fSAndroid Build Coastguard Worker }
1838*795d594fSAndroid Build Coastguard Worker // Allocate the new dex file cookie.
1839*795d594fSAndroid Build Coastguard Worker if (!AllocateAndRememberNewDexFileCookie(loader, dex_file_obj, cur_data)) {
1840*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
1841*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
1842*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate dex file array for class loader");
1843*795d594fSAndroid Build Coastguard Worker return false;
1844*795d594fSAndroid Build Coastguard Worker }
1845*795d594fSAndroid Build Coastguard Worker }
1846*795d594fSAndroid Build Coastguard Worker cur_data->SetNewDexCache(CreateNewDexCache(loader));
1847*795d594fSAndroid Build Coastguard Worker if (cur_data->GetNewDexCache() == nullptr) {
1848*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingException();
1849*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
1850*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate DexCache");
1851*795d594fSAndroid Build Coastguard Worker return false;
1852*795d594fSAndroid Build Coastguard Worker }
1853*795d594fSAndroid Build Coastguard Worker
1854*795d594fSAndroid Build Coastguard Worker // We won't always need to set this field.
1855*795d594fSAndroid Build Coastguard Worker cur_data->SetOriginalDexFile(AllocateOrGetOriginalDexFile());
1856*795d594fSAndroid Build Coastguard Worker if (cur_data->GetOriginalDexFile() == nullptr) {
1857*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
1858*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
1859*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate array for original dex file");
1860*795d594fSAndroid Build Coastguard Worker return false;
1861*795d594fSAndroid Build Coastguard Worker }
1862*795d594fSAndroid Build Coastguard Worker return true;
1863*795d594fSAndroid Build Coastguard Worker }
1864*795d594fSAndroid Build Coastguard Worker
FinishNewClassAllocations(RedefinitionDataHolder & holder,RedefinitionDataIter * cur_data)1865*795d594fSAndroid Build Coastguard Worker bool Redefiner::ClassRedefinition::FinishNewClassAllocations(RedefinitionDataHolder &holder,
1866*795d594fSAndroid Build Coastguard Worker RedefinitionDataIter *cur_data) {
1867*795d594fSAndroid Build Coastguard Worker if (cur_data->IsInitialized() || !cur_data->IsActuallyStructural()) {
1868*795d594fSAndroid Build Coastguard Worker cur_data->SetInitialized();
1869*795d594fSAndroid Build Coastguard Worker return true;
1870*795d594fSAndroid Build Coastguard Worker }
1871*795d594fSAndroid Build Coastguard Worker
1872*795d594fSAndroid Build Coastguard Worker art::VariableSizedHandleScope hs(driver_->self_);
1873*795d594fSAndroid Build Coastguard Worker // If we weren't the lowest structural redef the superclass would have already initialized us.
1874*795d594fSAndroid Build Coastguard Worker CHECK(IsStructuralRedefinition());
1875*795d594fSAndroid Build Coastguard Worker CHECK(cur_data->IsInitialStructural()) << "Should have already been initialized by supertype";
1876*795d594fSAndroid Build Coastguard Worker auto setup_single_redefinition =
1877*795d594fSAndroid Build Coastguard Worker [this](RedefinitionDataIter* data, art::Handle<art::mirror::Class> super_class)
1878*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) -> art::ObjPtr<art::mirror::Class> {
1879*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<3> chs(driver_->self_);
1880*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> nc(
1881*795d594fSAndroid Build Coastguard Worker chs.NewHandle(AllocateNewClassObject(chs.NewHandle(data->GetMirrorClass()),
1882*795d594fSAndroid Build Coastguard Worker super_class,
1883*795d594fSAndroid Build Coastguard Worker chs.NewHandle(data->GetNewDexCache()),
1884*795d594fSAndroid Build Coastguard Worker /*dex_class_def_index*/ 0)));
1885*795d594fSAndroid Build Coastguard Worker if (nc.IsNull()) {
1886*795d594fSAndroid Build Coastguard Worker return nullptr;
1887*795d594fSAndroid Build Coastguard Worker }
1888*795d594fSAndroid Build Coastguard Worker
1889*795d594fSAndroid Build Coastguard Worker data->SetNewClassObject(nc.Get());
1890*795d594fSAndroid Build Coastguard Worker data->SetInitialized();
1891*795d594fSAndroid Build Coastguard Worker return nc.Get();
1892*795d594fSAndroid Build Coastguard Worker };
1893*795d594fSAndroid Build Coastguard Worker
1894*795d594fSAndroid Build Coastguard Worker std::vector<art::Handle<art::mirror::Class>> old_types;
1895*795d594fSAndroid Build Coastguard Worker {
1896*795d594fSAndroid Build Coastguard Worker art::gc::Heap* heap = driver_->runtime_->GetHeap();
1897*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class>
1898*795d594fSAndroid Build Coastguard Worker old_klass(hs.NewHandle(cur_data->GetMirrorClass()));
1899*795d594fSAndroid Build Coastguard Worker if (setup_single_redefinition(cur_data, hs.NewHandle(old_klass->GetSuperClass())).IsNull()) {
1900*795d594fSAndroid Build Coastguard Worker return false;
1901*795d594fSAndroid Build Coastguard Worker }
1902*795d594fSAndroid Build Coastguard Worker auto is_subtype = [&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1903*795d594fSAndroid Build Coastguard Worker // We've already waited for class defines to be finished and paused them. All classes should be
1904*795d594fSAndroid Build Coastguard Worker // either resolved or error. We don't need to do anything with error classes, since they cannot
1905*795d594fSAndroid Build Coastguard Worker // be accessed in any observable way.
1906*795d594fSAndroid Build Coastguard Worker return obj->IsClass() && obj->AsClass()->IsResolved() &&
1907*795d594fSAndroid Build Coastguard Worker old_klass->IsAssignableFrom(obj->AsClass());
1908*795d594fSAndroid Build Coastguard Worker };
1909*795d594fSAndroid Build Coastguard Worker heap->VisitObjects([&](art::mirror::Object* obj) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1910*795d594fSAndroid Build Coastguard Worker if (is_subtype(obj)) {
1911*795d594fSAndroid Build Coastguard Worker old_types.push_back(hs.NewHandle(obj->AsClass()));
1912*795d594fSAndroid Build Coastguard Worker }
1913*795d594fSAndroid Build Coastguard Worker });
1914*795d594fSAndroid Build Coastguard Worker DCHECK_GT(old_types.size(), 0u) << "Expected to find at least old_klass!";
1915*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Found " << old_types.size() << " types that are/are subtypes of "
1916*795d594fSAndroid Build Coastguard Worker << old_klass->PrettyClass();
1917*795d594fSAndroid Build Coastguard Worker }
1918*795d594fSAndroid Build Coastguard Worker
1919*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> cls_array_class(
1920*795d594fSAndroid Build Coastguard Worker hs.NewHandle(art::GetClassRoot<art::mirror::ObjectArray<art::mirror::Class>>(
1921*795d594fSAndroid Build Coastguard Worker driver_->runtime_->GetClassLinker())));
1922*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::ObjectArray<art::mirror::Class>> old_classes_arr(
1923*795d594fSAndroid Build Coastguard Worker hs.NewHandle(art::mirror::ObjectArray<art::mirror::Class>::Alloc(
1924*795d594fSAndroid Build Coastguard Worker driver_->self_, cls_array_class.Get(), old_types.size())));
1925*795d594fSAndroid Build Coastguard Worker if (old_classes_arr.IsNull()) {
1926*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
1927*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
1928*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate old_classes arrays!");
1929*795d594fSAndroid Build Coastguard Worker return false;
1930*795d594fSAndroid Build Coastguard Worker }
1931*795d594fSAndroid Build Coastguard Worker // Sort the old_types topologically.
1932*795d594fSAndroid Build Coastguard Worker {
1933*795d594fSAndroid Build Coastguard Worker art::ScopedAssertNoThreadSuspension sants("Sort classes");
1934*795d594fSAndroid Build Coastguard Worker // Sort them by the distance to the base-class. This ensures that any class occurs before any of
1935*795d594fSAndroid Build Coastguard Worker // its subtypes.
1936*795d594fSAndroid Build Coastguard Worker std::sort(old_types.begin(),
1937*795d594fSAndroid Build Coastguard Worker old_types.end(),
1938*795d594fSAndroid Build Coastguard Worker [](auto& l, auto& r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1939*795d594fSAndroid Build Coastguard Worker return CompareClasses(l.Get(), r.Get());
1940*795d594fSAndroid Build Coastguard Worker });
1941*795d594fSAndroid Build Coastguard Worker }
1942*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; i < old_types.size(); ++i) {
1943*795d594fSAndroid Build Coastguard Worker DCHECK(!old_types[i].IsNull()) << i;
1944*795d594fSAndroid Build Coastguard Worker old_classes_arr->Set(i, old_types[i].Get());
1945*795d594fSAndroid Build Coastguard Worker }
1946*795d594fSAndroid Build Coastguard Worker cur_data->SetOldClasses(old_classes_arr.Get());
1947*795d594fSAndroid Build Coastguard Worker DCHECK_GT(old_classes_arr->GetLength(), 0);
1948*795d594fSAndroid Build Coastguard Worker
1949*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::ObjectArray<art::mirror::Class>> new_classes_arr(
1950*795d594fSAndroid Build Coastguard Worker hs.NewHandle(art::mirror::ObjectArray<art::mirror::Class>::Alloc(
1951*795d594fSAndroid Build Coastguard Worker driver_->self_, cls_array_class.Get(), old_types.size())));
1952*795d594fSAndroid Build Coastguard Worker if (new_classes_arr.IsNull()) {
1953*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
1954*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
1955*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate new_classes arrays!");
1956*795d594fSAndroid Build Coastguard Worker return false;
1957*795d594fSAndroid Build Coastguard Worker }
1958*795d594fSAndroid Build Coastguard Worker
1959*795d594fSAndroid Build Coastguard Worker art::MutableHandle<art::mirror::DexCache> dch(hs.NewHandle<art::mirror::DexCache>(nullptr));
1960*795d594fSAndroid Build Coastguard Worker art::MutableHandle<art::mirror::Class> superclass(hs.NewHandle<art::mirror::Class>(nullptr));
1961*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < old_types.size(); i++) {
1962*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class>& old_type = old_types[i];
1963*795d594fSAndroid Build Coastguard Worker if (old_type.Get() == cur_data->GetMirrorClass()) {
1964*795d594fSAndroid Build Coastguard Worker CHECK_EQ(i, 0u) << "original class not at index 0. Bad sort!";
1965*795d594fSAndroid Build Coastguard Worker new_classes_arr->Set(i, cur_data->GetNewClassObject());
1966*795d594fSAndroid Build Coastguard Worker continue;
1967*795d594fSAndroid Build Coastguard Worker } else {
1968*795d594fSAndroid Build Coastguard Worker auto old_super = std::find_if(old_types.begin(),
1969*795d594fSAndroid Build Coastguard Worker old_types.begin() + i,
1970*795d594fSAndroid Build Coastguard Worker [&](art::Handle<art::mirror::Class>& v)
1971*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_) {
1972*795d594fSAndroid Build Coastguard Worker return v.Get() == old_type->GetSuperClass();
1973*795d594fSAndroid Build Coastguard Worker });
1974*795d594fSAndroid Build Coastguard Worker // Only the GetMirrorClass should not be in this list.
1975*795d594fSAndroid Build Coastguard Worker CHECK(old_super != old_types.begin() + i)
1976*795d594fSAndroid Build Coastguard Worker << "from first " << i << " could not find super of " << old_type->PrettyClass()
1977*795d594fSAndroid Build Coastguard Worker << " expected to find " << old_type->GetSuperClass()->PrettyClass();
1978*795d594fSAndroid Build Coastguard Worker superclass.Assign(new_classes_arr->Get(std::distance(old_types.begin(), old_super)));
1979*795d594fSAndroid Build Coastguard Worker auto new_redef = std::find_if(
1980*795d594fSAndroid Build Coastguard Worker *cur_data + 1, holder.end(), [&](auto it) REQUIRES_SHARED(art::Locks::mutator_lock_) {
1981*795d594fSAndroid Build Coastguard Worker return it.GetMirrorClass() == old_type.Get();
1982*795d594fSAndroid Build Coastguard Worker });
1983*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> new_type;
1984*795d594fSAndroid Build Coastguard Worker if (new_redef == holder.end()) {
1985*795d594fSAndroid Build Coastguard Worker // We aren't also redefining this subclass. Just allocate a new class and continue.
1986*795d594fSAndroid Build Coastguard Worker dch.Assign(old_type->GetDexCache());
1987*795d594fSAndroid Build Coastguard Worker new_type =
1988*795d594fSAndroid Build Coastguard Worker AllocateNewClassObject(old_type, superclass, dch, old_type->GetDexClassDefIndex());
1989*795d594fSAndroid Build Coastguard Worker } else {
1990*795d594fSAndroid Build Coastguard Worker // This subclass is also being redefined. We need to use its new dex-file to load the new
1991*795d594fSAndroid Build Coastguard Worker // class.
1992*795d594fSAndroid Build Coastguard Worker CHECK(new_redef.IsActuallyStructural());
1993*795d594fSAndroid Build Coastguard Worker CHECK(!new_redef.IsInitialStructural());
1994*795d594fSAndroid Build Coastguard Worker new_type = setup_single_redefinition(&new_redef, superclass);
1995*795d594fSAndroid Build Coastguard Worker }
1996*795d594fSAndroid Build Coastguard Worker if (new_type == nullptr) {
1997*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Failed to load new version of class " << old_type->PrettyClass()
1998*795d594fSAndroid Build Coastguard Worker << " for structural redefinition!";
1999*795d594fSAndroid Build Coastguard Worker return false;
2000*795d594fSAndroid Build Coastguard Worker }
2001*795d594fSAndroid Build Coastguard Worker new_classes_arr->Set(i, new_type);
2002*795d594fSAndroid Build Coastguard Worker }
2003*795d594fSAndroid Build Coastguard Worker }
2004*795d594fSAndroid Build Coastguard Worker cur_data->SetNewClasses(new_classes_arr.Get());
2005*795d594fSAndroid Build Coastguard Worker return true;
2006*795d594fSAndroid Build Coastguard Worker }
2007*795d594fSAndroid Build Coastguard Worker
GetNewClassSize(art::ClassAccessor & accessor)2008*795d594fSAndroid Build Coastguard Worker uint32_t Redefiner::ClassRedefinition::GetNewClassSize(art::ClassAccessor& accessor) {
2009*795d594fSAndroid Build Coastguard Worker uint32_t num_8bit_static_fields = 0;
2010*795d594fSAndroid Build Coastguard Worker uint32_t num_16bit_static_fields = 0;
2011*795d594fSAndroid Build Coastguard Worker uint32_t num_32bit_static_fields = 0;
2012*795d594fSAndroid Build Coastguard Worker uint32_t num_64bit_static_fields = 0;
2013*795d594fSAndroid Build Coastguard Worker uint32_t num_ref_static_fields = 0;
2014*795d594fSAndroid Build Coastguard Worker for (const art::ClassAccessor::Field& f : accessor.GetStaticFields()) {
2015*795d594fSAndroid Build Coastguard Worker std::string_view desc(accessor.GetDexFile().GetFieldTypeDescriptor(
2016*795d594fSAndroid Build Coastguard Worker accessor.GetDexFile().GetFieldId(f.GetIndex())));
2017*795d594fSAndroid Build Coastguard Worker if (desc[0] == 'L' || desc[0] == '[') {
2018*795d594fSAndroid Build Coastguard Worker num_ref_static_fields++;
2019*795d594fSAndroid Build Coastguard Worker } else if (desc == "Z" || desc == "B") {
2020*795d594fSAndroid Build Coastguard Worker num_8bit_static_fields++;
2021*795d594fSAndroid Build Coastguard Worker } else if (desc == "C" || desc == "S") {
2022*795d594fSAndroid Build Coastguard Worker num_16bit_static_fields++;
2023*795d594fSAndroid Build Coastguard Worker } else if (desc == "I" || desc == "F") {
2024*795d594fSAndroid Build Coastguard Worker num_32bit_static_fields++;
2025*795d594fSAndroid Build Coastguard Worker } else if (desc == "J" || desc == "D") {
2026*795d594fSAndroid Build Coastguard Worker num_64bit_static_fields++;
2027*795d594fSAndroid Build Coastguard Worker } else {
2028*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unknown type descriptor! " << desc;
2029*795d594fSAndroid Build Coastguard Worker }
2030*795d594fSAndroid Build Coastguard Worker }
2031*795d594fSAndroid Build Coastguard Worker
2032*795d594fSAndroid Build Coastguard Worker return art::mirror::Class::ComputeClassSize(/*has_embedded_vtable=*/false,
2033*795d594fSAndroid Build Coastguard Worker /*num_vtable_entries=*/0,
2034*795d594fSAndroid Build Coastguard Worker num_8bit_static_fields,
2035*795d594fSAndroid Build Coastguard Worker num_16bit_static_fields,
2036*795d594fSAndroid Build Coastguard Worker num_32bit_static_fields,
2037*795d594fSAndroid Build Coastguard Worker num_64bit_static_fields,
2038*795d594fSAndroid Build Coastguard Worker num_ref_static_fields,
2039*795d594fSAndroid Build Coastguard Worker /*num_ref_bitmap_entries=*/0,
2040*795d594fSAndroid Build Coastguard Worker art::kRuntimePointerSize);
2041*795d594fSAndroid Build Coastguard Worker }
2042*795d594fSAndroid Build Coastguard Worker
2043*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class>
AllocateNewClassObject(art::Handle<art::mirror::DexCache> cache)2044*795d594fSAndroid Build Coastguard Worker Redefiner::ClassRedefinition::AllocateNewClassObject(art::Handle<art::mirror::DexCache> cache) {
2045*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<2> hs(driver_->self_);
2046*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> old_class(hs.NewHandle(GetMirrorClass()));
2047*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> super_class(hs.NewHandle(old_class->GetSuperClass()));
2048*795d594fSAndroid Build Coastguard Worker return AllocateNewClassObject(old_class, super_class, cache, /*dex_class_def_index*/0);
2049*795d594fSAndroid Build Coastguard Worker }
2050*795d594fSAndroid Build Coastguard Worker
AllocateNewClassObject(art::Handle<art::mirror::Class> old_class,art::Handle<art::mirror::Class> super_class,art::Handle<art::mirror::DexCache> cache,uint16_t dex_class_def_index)2051*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::AllocateNewClassObject(
2052*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> old_class,
2053*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> super_class,
2054*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::DexCache> cache,
2055*795d594fSAndroid Build Coastguard Worker uint16_t dex_class_def_index) {
2056*795d594fSAndroid Build Coastguard Worker // This is a stripped down DefineClass. We don't want to use DefineClass directly because it needs
2057*795d594fSAndroid Build Coastguard Worker // to perform a lot of extra steps to tell the ClassTable and the jit and everything about a new
2058*795d594fSAndroid Build Coastguard Worker // class. For now we will need to rely on our tests catching any issues caused by changes in how
2059*795d594fSAndroid Build Coastguard Worker // class_linker sets up classes.
2060*795d594fSAndroid Build Coastguard Worker // TODO Unify/move this into ClassLinker maybe.
2061*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<3> hs(driver_->self_);
2062*795d594fSAndroid Build Coastguard Worker art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
2063*795d594fSAndroid Build Coastguard Worker const art::DexFile* dex_file = cache->GetDexFile();
2064*795d594fSAndroid Build Coastguard Worker art::ClassAccessor accessor(*dex_file, dex_class_def_index);
2065*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> new_class(hs.NewHandle(linker->AllocClass(
2066*795d594fSAndroid Build Coastguard Worker driver_->self_, GetNewClassSize(accessor))));
2067*795d594fSAndroid Build Coastguard Worker if (new_class.IsNull()) {
2068*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
2069*795d594fSAndroid Build Coastguard Worker RecordFailure(
2070*795d594fSAndroid Build Coastguard Worker ERR(OUT_OF_MEMORY),
2071*795d594fSAndroid Build Coastguard Worker "Unable to allocate class object for redefinition of " + old_class->PrettyClass());
2072*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
2073*795d594fSAndroid Build Coastguard Worker return nullptr;
2074*795d594fSAndroid Build Coastguard Worker }
2075*795d594fSAndroid Build Coastguard Worker new_class->SetDexCache(cache.Get());
2076*795d594fSAndroid Build Coastguard Worker linker->SetupClass(*dex_file,
2077*795d594fSAndroid Build Coastguard Worker dex_file->GetClassDef(dex_class_def_index),
2078*795d594fSAndroid Build Coastguard Worker new_class,
2079*795d594fSAndroid Build Coastguard Worker old_class->GetClassLoader());
2080*795d594fSAndroid Build Coastguard Worker
2081*795d594fSAndroid Build Coastguard Worker // Make sure we are ready for linking. The lock isn't really needed since this isn't visible to
2082*795d594fSAndroid Build Coastguard Worker // other threads but the linker expects it.
2083*795d594fSAndroid Build Coastguard Worker art::ObjectLock<art::mirror::Class> lock(driver_->self_, new_class);
2084*795d594fSAndroid Build Coastguard Worker new_class->SetClinitThreadId(driver_->self_->GetTid());
2085*795d594fSAndroid Build Coastguard Worker // Make sure we have a valid empty iftable even if there are errors.
2086*795d594fSAndroid Build Coastguard Worker new_class->SetIfTable(art::GetClassRoot<art::mirror::Object>(linker)->GetIfTable());
2087*795d594fSAndroid Build Coastguard Worker linker->LoadClass(
2088*795d594fSAndroid Build Coastguard Worker driver_->self_, *dex_file, dex_file->GetClassDef(dex_class_def_index), new_class);
2089*795d594fSAndroid Build Coastguard Worker // NB. We know the interfaces and supers didn't change! :)
2090*795d594fSAndroid Build Coastguard Worker art::MutableHandle<art::mirror::Class> linked_class(hs.NewHandle<art::mirror::Class>(nullptr));
2091*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::ObjectArray<art::mirror::Class>> proxy_ifaces(
2092*795d594fSAndroid Build Coastguard Worker hs.NewHandle<art::mirror::ObjectArray<art::mirror::Class>>(nullptr));
2093*795d594fSAndroid Build Coastguard Worker // No changing hierarchy so everything is loaded.
2094*795d594fSAndroid Build Coastguard Worker new_class->SetSuperClass(super_class.Get());
2095*795d594fSAndroid Build Coastguard Worker art::mirror::Class::SetStatus(new_class, art::ClassStatus::kLoaded, nullptr);
2096*795d594fSAndroid Build Coastguard Worker if (!linker->LinkClass(driver_->self_, nullptr, new_class, proxy_ifaces, &linked_class)) {
2097*795d594fSAndroid Build Coastguard Worker std::ostringstream oss;
2098*795d594fSAndroid Build Coastguard Worker oss << "failed to link class due to "
2099*795d594fSAndroid Build Coastguard Worker << (driver_->self_->IsExceptionPending() ? driver_->self_->GetException()->Dump()
2100*795d594fSAndroid Build Coastguard Worker : " unknown");
2101*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(INTERNAL), oss.str());
2102*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
2103*795d594fSAndroid Build Coastguard Worker return nullptr;
2104*795d594fSAndroid Build Coastguard Worker }
2105*795d594fSAndroid Build Coastguard Worker // Everything is already resolved.
2106*795d594fSAndroid Build Coastguard Worker art::ObjectLock<art::mirror::Class> objlock(driver_->self_, linked_class);
2107*795d594fSAndroid Build Coastguard Worker // Mark the class as initialized.
2108*795d594fSAndroid Build Coastguard Worker CHECK(old_class->IsResolved())
2109*795d594fSAndroid Build Coastguard Worker << "Attempting to redefine an unresolved class " << old_class->PrettyClass()
2110*795d594fSAndroid Build Coastguard Worker << " status=" << old_class->GetStatus();
2111*795d594fSAndroid Build Coastguard Worker CHECK(linked_class->IsResolved());
2112*795d594fSAndroid Build Coastguard Worker if (old_class->ShouldSkipHiddenApiChecks()) {
2113*795d594fSAndroid Build Coastguard Worker // Match skip hiddenapi flag
2114*795d594fSAndroid Build Coastguard Worker linked_class->SetSkipHiddenApiChecks();
2115*795d594fSAndroid Build Coastguard Worker }
2116*795d594fSAndroid Build Coastguard Worker if (old_class->IsInitialized()) {
2117*795d594fSAndroid Build Coastguard Worker // We already verified the class earlier. No need to do it again.
2118*795d594fSAndroid Build Coastguard Worker linker->ForceClassInitialized(driver_->self_, linked_class);
2119*795d594fSAndroid Build Coastguard Worker } else if (old_class->GetStatus() > linked_class->GetStatus()) {
2120*795d594fSAndroid Build Coastguard Worker // We want to match the old status.
2121*795d594fSAndroid Build Coastguard Worker art::mirror::Class::SetStatus(linked_class, old_class->GetStatus(), driver_->self_);
2122*795d594fSAndroid Build Coastguard Worker }
2123*795d594fSAndroid Build Coastguard Worker // Make sure we have ext-data space for method & field ids. We won't know if we need them until
2124*795d594fSAndroid Build Coastguard Worker // it's too late to create them.
2125*795d594fSAndroid Build Coastguard Worker // TODO We might want to remove these arrays if they're not needed.
2126*795d594fSAndroid Build Coastguard Worker if (!art::mirror::Class::EnsureInstanceFieldIds(linked_class) ||
2127*795d594fSAndroid Build Coastguard Worker !art::mirror::Class::EnsureStaticFieldIds(linked_class) ||
2128*795d594fSAndroid Build Coastguard Worker !art::mirror::Class::EnsureMethodIds(linked_class)) {
2129*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
2130*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
2131*795d594fSAndroid Build Coastguard Worker RecordFailure(
2132*795d594fSAndroid Build Coastguard Worker ERR(OUT_OF_MEMORY),
2133*795d594fSAndroid Build Coastguard Worker "Unable to allocate jni-id arrays for redefinition of " + old_class->PrettyClass());
2134*795d594fSAndroid Build Coastguard Worker return nullptr;
2135*795d594fSAndroid Build Coastguard Worker }
2136*795d594fSAndroid Build Coastguard Worker // Finish setting up methods.
2137*795d594fSAndroid Build Coastguard Worker linked_class->VisitMethods([&](art::ArtMethod* m) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2138*795d594fSAndroid Build Coastguard Worker driver_->runtime_->GetInstrumentation()->InitializeMethodsCode(m, /* aot_code= */ nullptr);
2139*795d594fSAndroid Build Coastguard Worker m->SetNotIntrinsic();
2140*795d594fSAndroid Build Coastguard Worker DCHECK(m->IsCopied() || m->GetDeclaringClass() == linked_class.Get())
2141*795d594fSAndroid Build Coastguard Worker << m->PrettyMethod()
2142*795d594fSAndroid Build Coastguard Worker << " m->GetDeclaringClass(): " << m->GetDeclaringClass()->PrettyClass()
2143*795d594fSAndroid Build Coastguard Worker << " != linked_class.Get(): " << linked_class->PrettyClass();
2144*795d594fSAndroid Build Coastguard Worker }, art::kRuntimePointerSize);
2145*795d594fSAndroid Build Coastguard Worker if (art::kIsDebugBuild) {
2146*795d594fSAndroid Build Coastguard Worker linked_class->VisitFields([&](art::ArtField* f) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2147*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(f->GetDeclaringClass(), linked_class.Get());
2148*795d594fSAndroid Build Coastguard Worker });
2149*795d594fSAndroid Build Coastguard Worker }
2150*795d594fSAndroid Build Coastguard Worker // Reset ClinitThreadId back to the thread that loaded the old class. This is needed if we are in
2151*795d594fSAndroid Build Coastguard Worker // the middle of initializing a class.
2152*795d594fSAndroid Build Coastguard Worker linked_class->SetClinitThreadId(old_class->GetClinitThreadId());
2153*795d594fSAndroid Build Coastguard Worker return linked_class.Get();
2154*795d594fSAndroid Build Coastguard Worker }
2155*795d594fSAndroid Build Coastguard Worker
UnregisterJvmtiBreakpoints()2156*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::UnregisterJvmtiBreakpoints() {
2157*795d594fSAndroid Build Coastguard Worker BreakpointUtil::RemoveBreakpointsInClass(driver_->env_, GetMirrorClass().Ptr());
2158*795d594fSAndroid Build Coastguard Worker }
2159*795d594fSAndroid Build Coastguard Worker
UnregisterAllBreakpoints()2160*795d594fSAndroid Build Coastguard Worker void Redefiner::UnregisterAllBreakpoints() {
2161*795d594fSAndroid Build Coastguard Worker for (Redefiner::ClassRedefinition& redef : redefinitions_) {
2162*795d594fSAndroid Build Coastguard Worker redef.UnregisterJvmtiBreakpoints();
2163*795d594fSAndroid Build Coastguard Worker }
2164*795d594fSAndroid Build Coastguard Worker }
2165*795d594fSAndroid Build Coastguard Worker
CheckAllRedefinitionAreValid()2166*795d594fSAndroid Build Coastguard Worker bool Redefiner::CheckAllRedefinitionAreValid() {
2167*795d594fSAndroid Build Coastguard Worker for (Redefiner::ClassRedefinition& redef : redefinitions_) {
2168*795d594fSAndroid Build Coastguard Worker if (!redef.CheckRedefinitionIsValid()) {
2169*795d594fSAndroid Build Coastguard Worker return false;
2170*795d594fSAndroid Build Coastguard Worker }
2171*795d594fSAndroid Build Coastguard Worker }
2172*795d594fSAndroid Build Coastguard Worker return true;
2173*795d594fSAndroid Build Coastguard Worker }
2174*795d594fSAndroid Build Coastguard Worker
RestoreObsoleteMethodMapsIfUnneeded(RedefinitionDataHolder & holder)2175*795d594fSAndroid Build Coastguard Worker void Redefiner::RestoreObsoleteMethodMapsIfUnneeded(RedefinitionDataHolder& holder) {
2176*795d594fSAndroid Build Coastguard Worker for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2177*795d594fSAndroid Build Coastguard Worker data.GetRedefinition().RestoreObsoleteMethodMapsIfUnneeded(&data);
2178*795d594fSAndroid Build Coastguard Worker }
2179*795d594fSAndroid Build Coastguard Worker }
2180*795d594fSAndroid Build Coastguard Worker
MarkStructuralChanges(RedefinitionDataHolder & holder)2181*795d594fSAndroid Build Coastguard Worker void Redefiner::MarkStructuralChanges(RedefinitionDataHolder& holder) {
2182*795d594fSAndroid Build Coastguard Worker for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2183*795d594fSAndroid Build Coastguard Worker if (data.IsActuallyStructural()) {
2184*795d594fSAndroid Build Coastguard Worker // A superclass was structural and it marked all subclasses already. No need to do anything.
2185*795d594fSAndroid Build Coastguard Worker CHECK(!data.IsInitialStructural());
2186*795d594fSAndroid Build Coastguard Worker } else if (data.GetRedefinition().IsStructuralRedefinition()) {
2187*795d594fSAndroid Build Coastguard Worker data.SetActuallyStructural();
2188*795d594fSAndroid Build Coastguard Worker data.SetInitialStructural();
2189*795d594fSAndroid Build Coastguard Worker // Go over all potential subtypes and mark any that are actually subclasses as structural.
2190*795d594fSAndroid Build Coastguard Worker for (RedefinitionDataIter sub_data = data + 1; sub_data != holder.end(); ++sub_data) {
2191*795d594fSAndroid Build Coastguard Worker if (sub_data.GetRedefinition().GetMirrorClass()->IsSubClass(
2192*795d594fSAndroid Build Coastguard Worker data.GetRedefinition().GetMirrorClass())) {
2193*795d594fSAndroid Build Coastguard Worker sub_data.SetActuallyStructural();
2194*795d594fSAndroid Build Coastguard Worker }
2195*795d594fSAndroid Build Coastguard Worker }
2196*795d594fSAndroid Build Coastguard Worker }
2197*795d594fSAndroid Build Coastguard Worker }
2198*795d594fSAndroid Build Coastguard Worker }
2199*795d594fSAndroid Build Coastguard Worker
EnsureAllClassAllocationsFinished(RedefinitionDataHolder & holder)2200*795d594fSAndroid Build Coastguard Worker bool Redefiner::EnsureAllClassAllocationsFinished(RedefinitionDataHolder& holder) {
2201*795d594fSAndroid Build Coastguard Worker for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2202*795d594fSAndroid Build Coastguard Worker if (!data.GetRedefinition().EnsureClassAllocationsFinished(&data)) {
2203*795d594fSAndroid Build Coastguard Worker return false;
2204*795d594fSAndroid Build Coastguard Worker }
2205*795d594fSAndroid Build Coastguard Worker }
2206*795d594fSAndroid Build Coastguard Worker return true;
2207*795d594fSAndroid Build Coastguard Worker }
2208*795d594fSAndroid Build Coastguard Worker
CollectAndCreateNewInstances(RedefinitionDataHolder & holder)2209*795d594fSAndroid Build Coastguard Worker bool Redefiner::CollectAndCreateNewInstances(RedefinitionDataHolder& holder) {
2210*795d594fSAndroid Build Coastguard Worker for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2211*795d594fSAndroid Build Coastguard Worker // Allocate the data this redefinition requires.
2212*795d594fSAndroid Build Coastguard Worker if (!data.GetRedefinition().CollectAndCreateNewInstances(&data)) {
2213*795d594fSAndroid Build Coastguard Worker return false;
2214*795d594fSAndroid Build Coastguard Worker }
2215*795d594fSAndroid Build Coastguard Worker }
2216*795d594fSAndroid Build Coastguard Worker return true;
2217*795d594fSAndroid Build Coastguard Worker }
2218*795d594fSAndroid Build Coastguard Worker
FinishAllNewClassAllocations(RedefinitionDataHolder & holder)2219*795d594fSAndroid Build Coastguard Worker bool Redefiner::FinishAllNewClassAllocations(RedefinitionDataHolder& holder) {
2220*795d594fSAndroid Build Coastguard Worker for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2221*795d594fSAndroid Build Coastguard Worker // Allocate the data this redefinition requires.
2222*795d594fSAndroid Build Coastguard Worker if (!data.GetRedefinition().FinishNewClassAllocations(holder, &data)) {
2223*795d594fSAndroid Build Coastguard Worker return false;
2224*795d594fSAndroid Build Coastguard Worker }
2225*795d594fSAndroid Build Coastguard Worker }
2226*795d594fSAndroid Build Coastguard Worker return true;
2227*795d594fSAndroid Build Coastguard Worker }
2228*795d594fSAndroid Build Coastguard Worker
FinishAllRemainingCommonAllocations(RedefinitionDataHolder & holder)2229*795d594fSAndroid Build Coastguard Worker bool Redefiner::FinishAllRemainingCommonAllocations(RedefinitionDataHolder& holder) {
2230*795d594fSAndroid Build Coastguard Worker for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2231*795d594fSAndroid Build Coastguard Worker // Allocate the data this redefinition requires.
2232*795d594fSAndroid Build Coastguard Worker if (!data.GetRedefinition().FinishRemainingCommonAllocations(&data)) {
2233*795d594fSAndroid Build Coastguard Worker return false;
2234*795d594fSAndroid Build Coastguard Worker }
2235*795d594fSAndroid Build Coastguard Worker }
2236*795d594fSAndroid Build Coastguard Worker return true;
2237*795d594fSAndroid Build Coastguard Worker }
2238*795d594fSAndroid Build Coastguard Worker
ReleaseDexFile()2239*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::ReleaseDexFile() {
2240*795d594fSAndroid Build Coastguard Worker if (art::kIsDebugBuild) {
2241*795d594fSAndroid Build Coastguard Worker art::Thread* self = art::Thread::Current();
2242*795d594fSAndroid Build Coastguard Worker art::ClassLinker* cl = art::Runtime::Current()->GetClassLinker();
2243*795d594fSAndroid Build Coastguard Worker CHECK(cl->IsDexFileRegistered(self, *dex_file_));
2244*795d594fSAndroid Build Coastguard Worker }
2245*795d594fSAndroid Build Coastguard Worker dex_file_.release(); // NOLINT b/117926937
2246*795d594fSAndroid Build Coastguard Worker }
2247*795d594fSAndroid Build Coastguard Worker
ReleaseAllDexFiles()2248*795d594fSAndroid Build Coastguard Worker void Redefiner::ReleaseAllDexFiles() {
2249*795d594fSAndroid Build Coastguard Worker for (Redefiner::ClassRedefinition& redef : redefinitions_) {
2250*795d594fSAndroid Build Coastguard Worker redef.ReleaseDexFile();
2251*795d594fSAndroid Build Coastguard Worker }
2252*795d594fSAndroid Build Coastguard Worker }
2253*795d594fSAndroid Build Coastguard Worker
CheckAllClassesAreVerified(RedefinitionDataHolder & holder)2254*795d594fSAndroid Build Coastguard Worker bool Redefiner::CheckAllClassesAreVerified(RedefinitionDataHolder& holder) {
2255*795d594fSAndroid Build Coastguard Worker for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2256*795d594fSAndroid Build Coastguard Worker if (!data.GetRedefinition().CheckVerification(data)) {
2257*795d594fSAndroid Build Coastguard Worker return false;
2258*795d594fSAndroid Build Coastguard Worker }
2259*795d594fSAndroid Build Coastguard Worker }
2260*795d594fSAndroid Build Coastguard Worker return true;
2261*795d594fSAndroid Build Coastguard Worker }
2262*795d594fSAndroid Build Coastguard Worker
2263*795d594fSAndroid Build Coastguard Worker class ScopedDisableConcurrentAndMovingGc {
2264*795d594fSAndroid Build Coastguard Worker public:
ScopedDisableConcurrentAndMovingGc(art::gc::Heap * heap,art::Thread * self)2265*795d594fSAndroid Build Coastguard Worker ScopedDisableConcurrentAndMovingGc(art::gc::Heap* heap, art::Thread* self)
2266*795d594fSAndroid Build Coastguard Worker : heap_(heap), self_(self) {
2267*795d594fSAndroid Build Coastguard Worker if (heap_->IsGcConcurrentAndMoving()) {
2268*795d594fSAndroid Build Coastguard Worker heap_->IncrementDisableMovingGC(self_);
2269*795d594fSAndroid Build Coastguard Worker }
2270*795d594fSAndroid Build Coastguard Worker }
2271*795d594fSAndroid Build Coastguard Worker
~ScopedDisableConcurrentAndMovingGc()2272*795d594fSAndroid Build Coastguard Worker ~ScopedDisableConcurrentAndMovingGc() {
2273*795d594fSAndroid Build Coastguard Worker if (heap_->IsGcConcurrentAndMoving()) {
2274*795d594fSAndroid Build Coastguard Worker heap_->DecrementDisableMovingGC(self_);
2275*795d594fSAndroid Build Coastguard Worker }
2276*795d594fSAndroid Build Coastguard Worker }
2277*795d594fSAndroid Build Coastguard Worker private:
2278*795d594fSAndroid Build Coastguard Worker art::gc::Heap* heap_;
2279*795d594fSAndroid Build Coastguard Worker art::Thread* self_;
2280*795d594fSAndroid Build Coastguard Worker };
2281*795d594fSAndroid Build Coastguard Worker
2282*795d594fSAndroid Build Coastguard Worker class ClassDefinitionPauser : public art::ClassLoadCallback {
2283*795d594fSAndroid Build Coastguard Worker public:
REQUIRES_SHARED(art::Locks::mutator_lock_)2284*795d594fSAndroid Build Coastguard Worker explicit ClassDefinitionPauser(art::Thread* self) REQUIRES_SHARED(art::Locks::mutator_lock_)
2285*795d594fSAndroid Build Coastguard Worker : self_(self),
2286*795d594fSAndroid Build Coastguard Worker is_running_(false),
2287*795d594fSAndroid Build Coastguard Worker barrier_(0),
2288*795d594fSAndroid Build Coastguard Worker release_mu_("SuspendClassDefinition lock", art::kGenericBottomLock),
2289*795d594fSAndroid Build Coastguard Worker release_barrier_(0),
2290*795d594fSAndroid Build Coastguard Worker release_cond_("SuspendClassDefinition condvar", release_mu_),
2291*795d594fSAndroid Build Coastguard Worker count_(0),
2292*795d594fSAndroid Build Coastguard Worker release_(false) {
2293*795d594fSAndroid Build Coastguard Worker art::Locks::mutator_lock_->AssertSharedHeld(self_);
2294*795d594fSAndroid Build Coastguard Worker }
REQUIRES_SHARED(art::Locks::mutator_lock_)2295*795d594fSAndroid Build Coastguard Worker ~ClassDefinitionPauser() REQUIRES_SHARED(art::Locks::mutator_lock_) {
2296*795d594fSAndroid Build Coastguard Worker art::Locks::mutator_lock_->AssertSharedHeld(self_);
2297*795d594fSAndroid Build Coastguard Worker CHECK(release_) << "Must call Release()";
2298*795d594fSAndroid Build Coastguard Worker }
Release()2299*795d594fSAndroid Build Coastguard Worker void Release() REQUIRES(art::Locks::mutator_lock_) {
2300*795d594fSAndroid Build Coastguard Worker if (is_running_) {
2301*795d594fSAndroid Build Coastguard Worker art::Locks::mutator_lock_->AssertExclusiveHeld(self_);
2302*795d594fSAndroid Build Coastguard Worker uint32_t count;
2303*795d594fSAndroid Build Coastguard Worker // Wake up everything.
2304*795d594fSAndroid Build Coastguard Worker {
2305*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(self_, release_mu_);
2306*795d594fSAndroid Build Coastguard Worker release_ = true;
2307*795d594fSAndroid Build Coastguard Worker // We have an exclusive mutator so all threads must be suspended and therefore they've
2308*795d594fSAndroid Build Coastguard Worker // either already incremented this count_ or they are stuck somewhere before it.
2309*795d594fSAndroid Build Coastguard Worker count = count_;
2310*795d594fSAndroid Build Coastguard Worker release_cond_.Broadcast(self_);
2311*795d594fSAndroid Build Coastguard Worker }
2312*795d594fSAndroid Build Coastguard Worker // Wait for all threads to leave this structs code.
2313*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Resuming " << count << " threads paused before class-allocation!";
2314*795d594fSAndroid Build Coastguard Worker release_barrier_.Increment</*locks=*/art::Barrier::kAllowHoldingLocks>(self_, count);
2315*795d594fSAndroid Build Coastguard Worker } else {
2316*795d594fSAndroid Build Coastguard Worker release_ = true;
2317*795d594fSAndroid Build Coastguard Worker }
2318*795d594fSAndroid Build Coastguard Worker }
BeginDefineClass()2319*795d594fSAndroid Build Coastguard Worker void BeginDefineClass() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
2320*795d594fSAndroid Build Coastguard Worker art::Thread* this_thread = art::Thread::Current();
2321*795d594fSAndroid Build Coastguard Worker if (this_thread == self_) {
2322*795d594fSAndroid Build Coastguard Worker // Allow the redefining thread to do whatever.
2323*795d594fSAndroid Build Coastguard Worker return;
2324*795d594fSAndroid Build Coastguard Worker }
2325*795d594fSAndroid Build Coastguard Worker if (this_thread->GetDefineClassCount() != 0) {
2326*795d594fSAndroid Build Coastguard Worker // We are in the middle of a recursive define-class. Don't suspend now allow it to finish.
2327*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Recursive DefineClass in " << *this_thread
2328*795d594fSAndroid Build Coastguard Worker << " allowed to proceed despite class-def pause initiated by " << *self_;
2329*795d594fSAndroid Build Coastguard Worker return;
2330*795d594fSAndroid Build Coastguard Worker }
2331*795d594fSAndroid Build Coastguard Worker // If we are suspended (no mutator-lock) then the pausing thread could do everything before the
2332*795d594fSAndroid Build Coastguard Worker // count_++ including destroying this object, causing UAF/deadlock.
2333*795d594fSAndroid Build Coastguard Worker art::Locks::mutator_lock_->AssertSharedHeld(this_thread);
2334*795d594fSAndroid Build Coastguard Worker ++count_;
2335*795d594fSAndroid Build Coastguard Worker art::ScopedThreadSuspension sts(this_thread, art::ThreadState::kSuspended);
2336*795d594fSAndroid Build Coastguard Worker {
2337*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(this_thread, release_mu_);
2338*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Suspending " << *this_thread << " due to class definition. class-def pause "
2339*795d594fSAndroid Build Coastguard Worker << "initiated by " << *self_;
2340*795d594fSAndroid Build Coastguard Worker while (!release_) {
2341*795d594fSAndroid Build Coastguard Worker release_cond_.Wait(this_thread);
2342*795d594fSAndroid Build Coastguard Worker }
2343*795d594fSAndroid Build Coastguard Worker }
2344*795d594fSAndroid Build Coastguard Worker release_barrier_.Pass(this_thread);
2345*795d594fSAndroid Build Coastguard Worker }
2346*795d594fSAndroid Build Coastguard Worker
EndDefineClass()2347*795d594fSAndroid Build Coastguard Worker void EndDefineClass() override REQUIRES_SHARED(art::Locks::mutator_lock_) {
2348*795d594fSAndroid Build Coastguard Worker art::Thread* this_thread = art::Thread::Current();
2349*795d594fSAndroid Build Coastguard Worker if (this_thread == self_) {
2350*795d594fSAndroid Build Coastguard Worker // Allow the redefining thread to do whatever.
2351*795d594fSAndroid Build Coastguard Worker return;
2352*795d594fSAndroid Build Coastguard Worker }
2353*795d594fSAndroid Build Coastguard Worker if (this_thread->GetDefineClassCount() == 0) {
2354*795d594fSAndroid Build Coastguard Worker // We are done with defining classes.
2355*795d594fSAndroid Build Coastguard Worker barrier_.Pass(this_thread);
2356*795d594fSAndroid Build Coastguard Worker }
2357*795d594fSAndroid Build Coastguard Worker }
2358*795d594fSAndroid Build Coastguard Worker
ClassLoad(art::Handle<art::mirror::Class> klass)2359*795d594fSAndroid Build Coastguard Worker void ClassLoad([[maybe_unused]] art::Handle<art::mirror::Class> klass) override {}
ClassPrepare(art::Handle<art::mirror::Class> klass1,art::Handle<art::mirror::Class> klass2)2360*795d594fSAndroid Build Coastguard Worker void ClassPrepare([[maybe_unused]] art::Handle<art::mirror::Class> klass1,
2361*795d594fSAndroid Build Coastguard Worker [[maybe_unused]] art::Handle<art::mirror::Class> klass2) override {}
2362*795d594fSAndroid Build Coastguard Worker
SetRunning()2363*795d594fSAndroid Build Coastguard Worker void SetRunning() {
2364*795d594fSAndroid Build Coastguard Worker is_running_ = true;
2365*795d594fSAndroid Build Coastguard Worker }
WaitFor(uint32_t t)2366*795d594fSAndroid Build Coastguard Worker void WaitFor(uint32_t t) REQUIRES(!art::Locks::mutator_lock_) {
2367*795d594fSAndroid Build Coastguard Worker barrier_.Increment(self_, t);
2368*795d594fSAndroid Build Coastguard Worker }
2369*795d594fSAndroid Build Coastguard Worker
2370*795d594fSAndroid Build Coastguard Worker private:
2371*795d594fSAndroid Build Coastguard Worker art::Thread* self_;
2372*795d594fSAndroid Build Coastguard Worker bool is_running_;
2373*795d594fSAndroid Build Coastguard Worker art::Barrier barrier_;
2374*795d594fSAndroid Build Coastguard Worker art::Mutex release_mu_;
2375*795d594fSAndroid Build Coastguard Worker art::Barrier release_barrier_;
2376*795d594fSAndroid Build Coastguard Worker art::ConditionVariable release_cond_;
2377*795d594fSAndroid Build Coastguard Worker std::atomic<uint32_t> count_;
2378*795d594fSAndroid Build Coastguard Worker bool release_;
2379*795d594fSAndroid Build Coastguard Worker };
2380*795d594fSAndroid Build Coastguard Worker
2381*795d594fSAndroid Build Coastguard Worker class ScopedSuspendClassLoading {
2382*795d594fSAndroid Build Coastguard Worker public:
ScopedSuspendClassLoading(art::Thread * self,art::Runtime * runtime,RedefinitionDataHolder & h)2383*795d594fSAndroid Build Coastguard Worker ScopedSuspendClassLoading(art::Thread* self, art::Runtime* runtime, RedefinitionDataHolder& h)
2384*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_)
2385*795d594fSAndroid Build Coastguard Worker : self_(self), runtime_(runtime), pauser_() {
2386*795d594fSAndroid Build Coastguard Worker if (std::any_of(h.begin(), h.end(), [](auto r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2387*795d594fSAndroid Build Coastguard Worker return r.GetRedefinition().IsStructuralRedefinition();
2388*795d594fSAndroid Build Coastguard Worker })) {
2389*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Pausing Class loading for structural redefinition.";
2390*795d594fSAndroid Build Coastguard Worker pauser_.emplace(self);
2391*795d594fSAndroid Build Coastguard Worker {
2392*795d594fSAndroid Build Coastguard Worker art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative);
2393*795d594fSAndroid Build Coastguard Worker uint32_t in_progress_defines = 0;
2394*795d594fSAndroid Build Coastguard Worker {
2395*795d594fSAndroid Build Coastguard Worker art::ScopedSuspendAll ssa(__FUNCTION__);
2396*795d594fSAndroid Build Coastguard Worker pauser_->SetRunning();
2397*795d594fSAndroid Build Coastguard Worker runtime_->GetRuntimeCallbacks()->AddClassLoadCallback(&pauser_.value());
2398*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(self_, *art::Locks::thread_list_lock_);
2399*795d594fSAndroid Build Coastguard Worker runtime_->GetThreadList()->ForEach([&](art::Thread* t) {
2400*795d594fSAndroid Build Coastguard Worker if (t != self_ && t->GetDefineClassCount() != 0) {
2401*795d594fSAndroid Build Coastguard Worker in_progress_defines++;
2402*795d594fSAndroid Build Coastguard Worker }
2403*795d594fSAndroid Build Coastguard Worker });
2404*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Waiting for " << in_progress_defines
2405*795d594fSAndroid Build Coastguard Worker << " in progress class-loads to finish";
2406*795d594fSAndroid Build Coastguard Worker }
2407*795d594fSAndroid Build Coastguard Worker pauser_->WaitFor(in_progress_defines);
2408*795d594fSAndroid Build Coastguard Worker }
2409*795d594fSAndroid Build Coastguard Worker }
2410*795d594fSAndroid Build Coastguard Worker }
~ScopedSuspendClassLoading()2411*795d594fSAndroid Build Coastguard Worker ~ScopedSuspendClassLoading() {
2412*795d594fSAndroid Build Coastguard Worker if (pauser_.has_value()) {
2413*795d594fSAndroid Build Coastguard Worker art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative);
2414*795d594fSAndroid Build Coastguard Worker art::ScopedSuspendAll ssa(__FUNCTION__);
2415*795d594fSAndroid Build Coastguard Worker pauser_->Release();
2416*795d594fSAndroid Build Coastguard Worker runtime_->GetRuntimeCallbacks()->RemoveClassLoadCallback(&pauser_.value());
2417*795d594fSAndroid Build Coastguard Worker }
2418*795d594fSAndroid Build Coastguard Worker }
2419*795d594fSAndroid Build Coastguard Worker
2420*795d594fSAndroid Build Coastguard Worker private:
2421*795d594fSAndroid Build Coastguard Worker art::Thread* self_;
2422*795d594fSAndroid Build Coastguard Worker art::Runtime* runtime_;
2423*795d594fSAndroid Build Coastguard Worker std::optional<ClassDefinitionPauser> pauser_;
2424*795d594fSAndroid Build Coastguard Worker };
2425*795d594fSAndroid Build Coastguard Worker
2426*795d594fSAndroid Build Coastguard Worker class ScopedSuspendAllocations {
2427*795d594fSAndroid Build Coastguard Worker public:
ScopedSuspendAllocations(art::Runtime * runtime,RedefinitionDataHolder & h)2428*795d594fSAndroid Build Coastguard Worker ScopedSuspendAllocations(art::Runtime* runtime, RedefinitionDataHolder& h)
2429*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(art::Locks::mutator_lock_)
2430*795d594fSAndroid Build Coastguard Worker : paused_(false) {
2431*795d594fSAndroid Build Coastguard Worker if (std::any_of(h.begin(),
2432*795d594fSAndroid Build Coastguard Worker h.end(),
2433*795d594fSAndroid Build Coastguard Worker [](auto r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2434*795d594fSAndroid Build Coastguard Worker return r.GetRedefinition().IsStructuralRedefinition();
2435*795d594fSAndroid Build Coastguard Worker })) {
2436*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Pausing allocations for structural redefinition.";
2437*795d594fSAndroid Build Coastguard Worker paused_ = true;
2438*795d594fSAndroid Build Coastguard Worker AllocationManager::Get()->PauseAllocations(art::Thread::Current());
2439*795d594fSAndroid Build Coastguard Worker // Collect garbage so we don't need to recreate as much.
2440*795d594fSAndroid Build Coastguard Worker runtime->GetHeap()->CollectGarbage(/*clear_soft_references=*/false);
2441*795d594fSAndroid Build Coastguard Worker }
2442*795d594fSAndroid Build Coastguard Worker }
2443*795d594fSAndroid Build Coastguard Worker
REQUIRES_SHARED(art::Locks::mutator_lock_)2444*795d594fSAndroid Build Coastguard Worker ~ScopedSuspendAllocations() REQUIRES_SHARED(art::Locks::mutator_lock_) {
2445*795d594fSAndroid Build Coastguard Worker if (paused_) {
2446*795d594fSAndroid Build Coastguard Worker AllocationManager::Get()->ResumeAllocations(art::Thread::Current());
2447*795d594fSAndroid Build Coastguard Worker }
2448*795d594fSAndroid Build Coastguard Worker }
2449*795d594fSAndroid Build Coastguard Worker
2450*795d594fSAndroid Build Coastguard Worker private:
2451*795d594fSAndroid Build Coastguard Worker bool paused_;
2452*795d594fSAndroid Build Coastguard Worker
2453*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ScopedSuspendAllocations);
2454*795d594fSAndroid Build Coastguard Worker };
2455*795d594fSAndroid Build Coastguard Worker
Run()2456*795d594fSAndroid Build Coastguard Worker jvmtiError Redefiner::Run() {
2457*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<1> hs(self_);
2458*795d594fSAndroid Build Coastguard Worker // Sort the redefinitions_ array topologically by class. This makes later steps easier since we
2459*795d594fSAndroid Build Coastguard Worker // know that every class precedes all of its supertypes.
2460*795d594fSAndroid Build Coastguard Worker std::sort(redefinitions_.begin(),
2461*795d594fSAndroid Build Coastguard Worker redefinitions_.end(),
2462*795d594fSAndroid Build Coastguard Worker [&](auto& l, auto& r) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2463*795d594fSAndroid Build Coastguard Worker return CompareClasses(l.GetMirrorClass(), r.GetMirrorClass());
2464*795d594fSAndroid Build Coastguard Worker });
2465*795d594fSAndroid Build Coastguard Worker // Allocate an array to hold onto all java temporary objects associated with this
2466*795d594fSAndroid Build Coastguard Worker // redefinition. We will let this be collected after the end of this function.
2467*795d594fSAndroid Build Coastguard Worker RedefinitionDataHolder holder(&hs, runtime_, self_, &redefinitions_);
2468*795d594fSAndroid Build Coastguard Worker if (holder.IsNull()) {
2469*795d594fSAndroid Build Coastguard Worker self_->AssertPendingOOMException();
2470*795d594fSAndroid Build Coastguard Worker self_->ClearException();
2471*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate storage for temporaries");
2472*795d594fSAndroid Build Coastguard Worker return result_;
2473*795d594fSAndroid Build Coastguard Worker }
2474*795d594fSAndroid Build Coastguard Worker
2475*795d594fSAndroid Build Coastguard Worker // First we just allocate the ClassExt and its fields that we need. These can be updated
2476*795d594fSAndroid Build Coastguard Worker // atomically without any issues (since we allocate the map arrays as empty).
2477*795d594fSAndroid Build Coastguard Worker if (!CheckAllRedefinitionAreValid()) {
2478*795d594fSAndroid Build Coastguard Worker return result_;
2479*795d594fSAndroid Build Coastguard Worker }
2480*795d594fSAndroid Build Coastguard Worker // Mark structural changes.
2481*795d594fSAndroid Build Coastguard Worker MarkStructuralChanges(holder);
2482*795d594fSAndroid Build Coastguard Worker // Now we pause class loading. If we are doing a structural redefinition we will need to get an
2483*795d594fSAndroid Build Coastguard Worker // accurate picture of the classes loaded and having loads in the middle would make that
2484*795d594fSAndroid Build Coastguard Worker // impossible. This only pauses class-loading if we actually have at least one structural
2485*795d594fSAndroid Build Coastguard Worker // redefinition.
2486*795d594fSAndroid Build Coastguard Worker ScopedSuspendClassLoading suspend_class_load(self_, runtime_, holder);
2487*795d594fSAndroid Build Coastguard Worker if (!EnsureAllClassAllocationsFinished(holder) ||
2488*795d594fSAndroid Build Coastguard Worker !FinishAllRemainingCommonAllocations(holder) ||
2489*795d594fSAndroid Build Coastguard Worker !FinishAllNewClassAllocations(holder) ||
2490*795d594fSAndroid Build Coastguard Worker !CheckAllClassesAreVerified(holder)) {
2491*795d594fSAndroid Build Coastguard Worker return result_;
2492*795d594fSAndroid Build Coastguard Worker }
2493*795d594fSAndroid Build Coastguard Worker
2494*795d594fSAndroid Build Coastguard Worker ScopedSuspendAllocations suspend_alloc(runtime_, holder);
2495*795d594fSAndroid Build Coastguard Worker if (!CollectAndCreateNewInstances(holder)) {
2496*795d594fSAndroid Build Coastguard Worker return result_;
2497*795d594fSAndroid Build Coastguard Worker }
2498*795d594fSAndroid Build Coastguard Worker
2499*795d594fSAndroid Build Coastguard Worker // At this point we can no longer fail without corrupting the runtime state.
2500*795d594fSAndroid Build Coastguard Worker for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2501*795d594fSAndroid Build Coastguard Worker art::ClassLinker* cl = runtime_->GetClassLinker();
2502*795d594fSAndroid Build Coastguard Worker if (data.GetSourceClassLoader() == nullptr) {
2503*795d594fSAndroid Build Coastguard Worker // AppendToBootClassPath includes dex file registration.
2504*795d594fSAndroid Build Coastguard Worker const art::DexFile& dex_file = data.GetRedefinition().GetDexFile();
2505*795d594fSAndroid Build Coastguard Worker runtime_->AppendToBootClassPath(
2506*795d594fSAndroid Build Coastguard Worker dex_file.GetLocation(), dex_file.GetLocation(), {{&dex_file, data.GetNewDexCache()}});
2507*795d594fSAndroid Build Coastguard Worker } else {
2508*795d594fSAndroid Build Coastguard Worker cl->RegisterExistingDexCache(data.GetNewDexCache(), data.GetSourceClassLoader());
2509*795d594fSAndroid Build Coastguard Worker }
2510*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(cl->FindDexCache(self_, data.GetRedefinition().GetDexFile()), data.GetNewDexCache());
2511*795d594fSAndroid Build Coastguard Worker }
2512*795d594fSAndroid Build Coastguard Worker UnregisterAllBreakpoints();
2513*795d594fSAndroid Build Coastguard Worker
2514*795d594fSAndroid Build Coastguard Worker {
2515*795d594fSAndroid Build Coastguard Worker // Disable GC and wait for it to be done if we are a moving GC. This is fine since we are done
2516*795d594fSAndroid Build Coastguard Worker // allocating so no deadlocks.
2517*795d594fSAndroid Build Coastguard Worker ScopedDisableConcurrentAndMovingGc sdcamgc(runtime_->GetHeap(), self_);
2518*795d594fSAndroid Build Coastguard Worker
2519*795d594fSAndroid Build Coastguard Worker // Do transition to final suspension
2520*795d594fSAndroid Build Coastguard Worker // TODO We might want to give this its own suspended state!
2521*795d594fSAndroid Build Coastguard Worker // TODO This isn't right. We need to change state without any chance of suspend ideally!
2522*795d594fSAndroid Build Coastguard Worker art::ScopedThreadSuspension sts(self_, art::ThreadState::kNative);
2523*795d594fSAndroid Build Coastguard Worker art::ScopedSuspendAll ssa("Final installation of redefined Classes!", /*long_suspend=*/true);
2524*795d594fSAndroid Build Coastguard Worker for (RedefinitionDataIter data = holder.begin(); data != holder.end(); ++data) {
2525*795d594fSAndroid Build Coastguard Worker art::ScopedAssertNoThreadSuspension nts("Updating runtime objects for redefinition");
2526*795d594fSAndroid Build Coastguard Worker ClassRedefinition& redef = data.GetRedefinition();
2527*795d594fSAndroid Build Coastguard Worker if (data.GetSourceClassLoader() != nullptr) {
2528*795d594fSAndroid Build Coastguard Worker ClassLoaderHelper::UpdateJavaDexFile(data.GetJavaDexFile(), data.GetNewDexFileCookie());
2529*795d594fSAndroid Build Coastguard Worker }
2530*795d594fSAndroid Build Coastguard Worker redef.UpdateClass(data);
2531*795d594fSAndroid Build Coastguard Worker }
2532*795d594fSAndroid Build Coastguard Worker RestoreObsoleteMethodMapsIfUnneeded(holder);
2533*795d594fSAndroid Build Coastguard Worker // TODO We should check for if any of the redefined methods are intrinsic methods here and, if
2534*795d594fSAndroid Build Coastguard Worker // any are, force a full-world deoptimization before finishing redefinition. If we don't do this
2535*795d594fSAndroid Build Coastguard Worker // then methods that have been jitted prior to the current redefinition being applied might
2536*795d594fSAndroid Build Coastguard Worker // continue to use the old versions of the intrinsics!
2537*795d594fSAndroid Build Coastguard Worker // TODO Do the dex_file release at a more reasonable place. This works but it muddles who really
2538*795d594fSAndroid Build Coastguard Worker // owns the DexFile and when ownership is transferred.
2539*795d594fSAndroid Build Coastguard Worker ReleaseAllDexFiles();
2540*795d594fSAndroid Build Coastguard Worker }
2541*795d594fSAndroid Build Coastguard Worker return OK;
2542*795d594fSAndroid Build Coastguard Worker }
2543*795d594fSAndroid Build Coastguard Worker
UpdateMethods(art::ObjPtr<art::mirror::Class> mclass,const art::dex::ClassDef & class_def)2544*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::UpdateMethods(art::ObjPtr<art::mirror::Class> mclass,
2545*795d594fSAndroid Build Coastguard Worker const art::dex::ClassDef& class_def) {
2546*795d594fSAndroid Build Coastguard Worker art::ClassLinker* linker = driver_->runtime_->GetClassLinker();
2547*795d594fSAndroid Build Coastguard Worker art::PointerSize image_pointer_size = linker->GetImagePointerSize();
2548*795d594fSAndroid Build Coastguard Worker const art::dex::TypeId& declaring_class_id = dex_file_->GetTypeId(class_def.class_idx_);
2549*795d594fSAndroid Build Coastguard Worker const art::DexFile& old_dex_file = mclass->GetDexFile();
2550*795d594fSAndroid Build Coastguard Worker // Update methods.
2551*795d594fSAndroid Build Coastguard Worker for (art::ArtMethod& method : mclass->GetDeclaredMethods(image_pointer_size)) {
2552*795d594fSAndroid Build Coastguard Worker // Reinitialize the method by calling `CopyFrom`. This ensures for example
2553*795d594fSAndroid Build Coastguard Worker // the entrypoint and the hotness are reset.
2554*795d594fSAndroid Build Coastguard Worker method.CopyFrom(&method, image_pointer_size);
2555*795d594fSAndroid Build Coastguard Worker const art::dex::StringId* new_name_id = dex_file_->FindStringId(method.GetName());
2556*795d594fSAndroid Build Coastguard Worker art::dex::TypeIndex method_return_idx =
2557*795d594fSAndroid Build Coastguard Worker dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(method.GetReturnTypeDescriptorView()));
2558*795d594fSAndroid Build Coastguard Worker const auto* old_type_list = method.GetParameterTypeList();
2559*795d594fSAndroid Build Coastguard Worker std::vector<art::dex::TypeIndex> new_type_list;
2560*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; old_type_list != nullptr && i < old_type_list->Size(); i++) {
2561*795d594fSAndroid Build Coastguard Worker new_type_list.push_back(
2562*795d594fSAndroid Build Coastguard Worker dex_file_->GetIndexForTypeId(
2563*795d594fSAndroid Build Coastguard Worker *dex_file_->FindTypeId(
2564*795d594fSAndroid Build Coastguard Worker old_dex_file.GetTypeDescriptorView(
2565*795d594fSAndroid Build Coastguard Worker old_dex_file.GetTypeId(
2566*795d594fSAndroid Build Coastguard Worker old_type_list->GetTypeItem(i).type_idx_)))));
2567*795d594fSAndroid Build Coastguard Worker }
2568*795d594fSAndroid Build Coastguard Worker const art::dex::ProtoId* proto_id = dex_file_->FindProtoId(method_return_idx, new_type_list);
2569*795d594fSAndroid Build Coastguard Worker CHECK(proto_id != nullptr || old_type_list == nullptr);
2570*795d594fSAndroid Build Coastguard Worker const art::dex::MethodId* method_id = dex_file_->FindMethodId(declaring_class_id,
2571*795d594fSAndroid Build Coastguard Worker *new_name_id,
2572*795d594fSAndroid Build Coastguard Worker *proto_id);
2573*795d594fSAndroid Build Coastguard Worker CHECK(method_id != nullptr);
2574*795d594fSAndroid Build Coastguard Worker uint32_t dex_method_idx = dex_file_->GetIndexForMethodId(*method_id);
2575*795d594fSAndroid Build Coastguard Worker method.SetDexMethodIndex(dex_method_idx);
2576*795d594fSAndroid Build Coastguard Worker driver_->runtime_->GetInstrumentation()->InitializeMethodsCode(&method, /*aot_code=*/ nullptr);
2577*795d594fSAndroid Build Coastguard Worker if (method.HasCodeItem()) {
2578*795d594fSAndroid Build Coastguard Worker method.SetCodeItem(
2579*795d594fSAndroid Build Coastguard Worker dex_file_->GetCodeItem(dex_file_->FindCodeItemOffset(class_def, dex_method_idx)),
2580*795d594fSAndroid Build Coastguard Worker dex_file_->IsCompactDexFile());
2581*795d594fSAndroid Build Coastguard Worker }
2582*795d594fSAndroid Build Coastguard Worker // Clear all the intrinsics related flags.
2583*795d594fSAndroid Build Coastguard Worker method.SetNotIntrinsic();
2584*795d594fSAndroid Build Coastguard Worker }
2585*795d594fSAndroid Build Coastguard Worker }
2586*795d594fSAndroid Build Coastguard Worker
UpdateFields(art::ObjPtr<art::mirror::Class> mclass)2587*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::UpdateFields(art::ObjPtr<art::mirror::Class> mclass) {
2588*795d594fSAndroid Build Coastguard Worker // TODO The IFields & SFields pointers should be combined like the methods_ arrays were.
2589*795d594fSAndroid Build Coastguard Worker for (auto fields_iter : {mclass->GetIFields(), mclass->GetSFields()}) {
2590*795d594fSAndroid Build Coastguard Worker for (art::ArtField& field : fields_iter) {
2591*795d594fSAndroid Build Coastguard Worker const art::dex::TypeId* new_declaring_id =
2592*795d594fSAndroid Build Coastguard Worker dex_file_->FindTypeId(field.GetDeclaringClassDescriptorView());
2593*795d594fSAndroid Build Coastguard Worker const art::dex::StringId* new_name_id = dex_file_->FindStringId(field.GetName());
2594*795d594fSAndroid Build Coastguard Worker const art::dex::TypeId* new_type_id = dex_file_->FindTypeId(field.GetTypeDescriptorView());
2595*795d594fSAndroid Build Coastguard Worker CHECK(new_name_id != nullptr && new_type_id != nullptr && new_declaring_id != nullptr);
2596*795d594fSAndroid Build Coastguard Worker const art::dex::FieldId* new_field_id =
2597*795d594fSAndroid Build Coastguard Worker dex_file_->FindFieldId(*new_declaring_id, *new_name_id, *new_type_id);
2598*795d594fSAndroid Build Coastguard Worker CHECK(new_field_id != nullptr);
2599*795d594fSAndroid Build Coastguard Worker uint32_t new_field_index = dex_file_->GetIndexForFieldId(*new_field_id);
2600*795d594fSAndroid Build Coastguard Worker // We only need to update the index since the other data in the ArtField cannot be updated.
2601*795d594fSAndroid Build Coastguard Worker field.SetDexFieldIndex(new_field_index);
2602*795d594fSAndroid Build Coastguard Worker }
2603*795d594fSAndroid Build Coastguard Worker }
2604*795d594fSAndroid Build Coastguard Worker }
2605*795d594fSAndroid Build Coastguard Worker
CollectNewFieldAndMethodMappings(const RedefinitionDataIter & data,std::map<art::ArtMethod *,art::ArtMethod * > * method_map,std::map<art::ArtField *,art::ArtField * > * field_map)2606*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::CollectNewFieldAndMethodMappings(
2607*795d594fSAndroid Build Coastguard Worker const RedefinitionDataIter& data,
2608*795d594fSAndroid Build Coastguard Worker std::map<art::ArtMethod*, art::ArtMethod*>* method_map,
2609*795d594fSAndroid Build Coastguard Worker std::map<art::ArtField*, art::ArtField*>* field_map) {
2610*795d594fSAndroid Build Coastguard Worker for (auto [new_cls, old_cls] :
2611*795d594fSAndroid Build Coastguard Worker art::ZipLeft(data.GetNewClasses()->Iterate(), data.GetOldClasses()->Iterate())) {
2612*795d594fSAndroid Build Coastguard Worker for (art::ArtField& f : old_cls->GetSFields()) {
2613*795d594fSAndroid Build Coastguard Worker (*field_map)[&f] = new_cls->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor());
2614*795d594fSAndroid Build Coastguard Worker }
2615*795d594fSAndroid Build Coastguard Worker for (art::ArtField& f : old_cls->GetIFields()) {
2616*795d594fSAndroid Build Coastguard Worker (*field_map)[&f] = new_cls->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor());
2617*795d594fSAndroid Build Coastguard Worker }
2618*795d594fSAndroid Build Coastguard Worker auto new_methods = new_cls->GetMethods(art::kRuntimePointerSize);
2619*795d594fSAndroid Build Coastguard Worker for (art::ArtMethod& m : old_cls->GetMethods(art::kRuntimePointerSize)) {
2620*795d594fSAndroid Build Coastguard Worker // No support for finding methods in this way since it's generally not needed. Just do it the
2621*795d594fSAndroid Build Coastguard Worker // easy way.
2622*795d594fSAndroid Build Coastguard Worker auto nm_iter = std::find_if(
2623*795d594fSAndroid Build Coastguard Worker new_methods.begin(),
2624*795d594fSAndroid Build Coastguard Worker new_methods.end(),
2625*795d594fSAndroid Build Coastguard Worker [&](art::ArtMethod& cand) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2626*795d594fSAndroid Build Coastguard Worker return cand.GetNameView() == m.GetNameView() && cand.GetSignature() == m.GetSignature();
2627*795d594fSAndroid Build Coastguard Worker });
2628*795d594fSAndroid Build Coastguard Worker CHECK(nm_iter != new_methods.end())
2629*795d594fSAndroid Build Coastguard Worker << "Could not find redefined version of " << m.PrettyMethod();
2630*795d594fSAndroid Build Coastguard Worker (*method_map)[&m] = &(*nm_iter);
2631*795d594fSAndroid Build Coastguard Worker }
2632*795d594fSAndroid Build Coastguard Worker }
2633*795d594fSAndroid Build Coastguard Worker }
2634*795d594fSAndroid Build Coastguard Worker
CopyField(art::ObjPtr<art::mirror::Object> target,art::ArtField * new_field,art::ObjPtr<art::mirror::Object> source,art::ArtField & old_field)2635*795d594fSAndroid Build Coastguard Worker static void CopyField(art::ObjPtr<art::mirror::Object> target,
2636*795d594fSAndroid Build Coastguard Worker art::ArtField* new_field,
2637*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> source,
2638*795d594fSAndroid Build Coastguard Worker art::ArtField& old_field) REQUIRES(art::Locks::mutator_lock_) {
2639*795d594fSAndroid Build Coastguard Worker art::Primitive::Type ftype = old_field.GetTypeAsPrimitiveType();
2640*795d594fSAndroid Build Coastguard Worker CHECK_EQ(ftype, new_field->GetTypeAsPrimitiveType())
2641*795d594fSAndroid Build Coastguard Worker << old_field.PrettyField() << " vs " << new_field->PrettyField();
2642*795d594fSAndroid Build Coastguard Worker if (ftype == art::Primitive::kPrimNot) {
2643*795d594fSAndroid Build Coastguard Worker new_field->SetObject<false>(target, old_field.GetObject(source));
2644*795d594fSAndroid Build Coastguard Worker } else {
2645*795d594fSAndroid Build Coastguard Worker switch (ftype) {
2646*795d594fSAndroid Build Coastguard Worker #define UPDATE_FIELD(TYPE) \
2647*795d594fSAndroid Build Coastguard Worker case art::Primitive::kPrim##TYPE: \
2648*795d594fSAndroid Build Coastguard Worker new_field->Set##TYPE<false>(target, old_field.Get##TYPE(source)); \
2649*795d594fSAndroid Build Coastguard Worker break
2650*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Int);
2651*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Float);
2652*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Long);
2653*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Double);
2654*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Short);
2655*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Char);
2656*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Byte);
2657*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Boolean);
2658*795d594fSAndroid Build Coastguard Worker case art::Primitive::kPrimNot:
2659*795d594fSAndroid Build Coastguard Worker case art::Primitive::kPrimVoid:
2660*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected field with type " << ftype << " found!";
2661*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
2662*795d594fSAndroid Build Coastguard Worker #undef UPDATE_FIELD
2663*795d594fSAndroid Build Coastguard Worker }
2664*795d594fSAndroid Build Coastguard Worker }
2665*795d594fSAndroid Build Coastguard Worker }
2666*795d594fSAndroid Build Coastguard Worker
CopyFields(bool is_static,art::ObjPtr<art::mirror::Object> target,art::ObjPtr<art::mirror::Class> target_class,art::ObjPtr<art::mirror::Object> source,art::ObjPtr<art::mirror::Class> source_class)2667*795d594fSAndroid Build Coastguard Worker static void CopyFields(bool is_static,
2668*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> target,
2669*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> target_class,
2670*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> source,
2671*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> source_class)
2672*795d594fSAndroid Build Coastguard Worker REQUIRES(art::Locks::mutator_lock_) {
2673*795d594fSAndroid Build Coastguard Worker DCHECK(!source_class->IsObjectClass() && !target_class->IsObjectClass())
2674*795d594fSAndroid Build Coastguard Worker << "Should not be overriding object class fields. Target: " << target_class->PrettyClass()
2675*795d594fSAndroid Build Coastguard Worker << " Source: " << source_class->PrettyClass();
2676*795d594fSAndroid Build Coastguard Worker for (art::ArtField& f : (is_static ? source_class->GetSFields() : source_class->GetIFields())) {
2677*795d594fSAndroid Build Coastguard Worker art::ArtField* new_field =
2678*795d594fSAndroid Build Coastguard Worker (is_static ? target_class->FindDeclaredStaticField(f.GetName(), f.GetTypeDescriptor())
2679*795d594fSAndroid Build Coastguard Worker : target_class->FindDeclaredInstanceField(f.GetName(), f.GetTypeDescriptor()));
2680*795d594fSAndroid Build Coastguard Worker CHECK(new_field != nullptr) << "could not find new version of " << f.PrettyField();
2681*795d594fSAndroid Build Coastguard Worker CopyField(target, new_field, source, f);
2682*795d594fSAndroid Build Coastguard Worker }
2683*795d594fSAndroid Build Coastguard Worker if (!is_static && !target_class->GetSuperClass()->IsObjectClass()) {
2684*795d594fSAndroid Build Coastguard Worker CopyFields(
2685*795d594fSAndroid Build Coastguard Worker is_static, target, target_class->GetSuperClass(), source, source_class->GetSuperClass());
2686*795d594fSAndroid Build Coastguard Worker }
2687*795d594fSAndroid Build Coastguard Worker }
2688*795d594fSAndroid Build Coastguard Worker
ClearField(art::ObjPtr<art::mirror::Object> target,art::ArtField & field)2689*795d594fSAndroid Build Coastguard Worker static void ClearField(art::ObjPtr<art::mirror::Object> target, art::ArtField& field)
2690*795d594fSAndroid Build Coastguard Worker REQUIRES(art::Locks::mutator_lock_) {
2691*795d594fSAndroid Build Coastguard Worker art::Primitive::Type ftype = field.GetTypeAsPrimitiveType();
2692*795d594fSAndroid Build Coastguard Worker if (ftype == art::Primitive::kPrimNot) {
2693*795d594fSAndroid Build Coastguard Worker field.SetObject<false>(target, nullptr);
2694*795d594fSAndroid Build Coastguard Worker } else {
2695*795d594fSAndroid Build Coastguard Worker switch (ftype) {
2696*795d594fSAndroid Build Coastguard Worker #define UPDATE_FIELD(TYPE) \
2697*795d594fSAndroid Build Coastguard Worker case art::Primitive::kPrim##TYPE: \
2698*795d594fSAndroid Build Coastguard Worker field.Set##TYPE<false>(target, 0); \
2699*795d594fSAndroid Build Coastguard Worker break
2700*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Int);
2701*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Float);
2702*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Long);
2703*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Double);
2704*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Short);
2705*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Char);
2706*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Byte);
2707*795d594fSAndroid Build Coastguard Worker UPDATE_FIELD(Boolean);
2708*795d594fSAndroid Build Coastguard Worker case art::Primitive::kPrimNot:
2709*795d594fSAndroid Build Coastguard Worker case art::Primitive::kPrimVoid:
2710*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Unexpected field with type " << ftype << " found!";
2711*795d594fSAndroid Build Coastguard Worker UNREACHABLE();
2712*795d594fSAndroid Build Coastguard Worker #undef UPDATE_FIELD
2713*795d594fSAndroid Build Coastguard Worker }
2714*795d594fSAndroid Build Coastguard Worker }
2715*795d594fSAndroid Build Coastguard Worker }
2716*795d594fSAndroid Build Coastguard Worker
ClearFields(bool is_static,art::ObjPtr<art::mirror::Object> target,art::ObjPtr<art::mirror::Class> target_class)2717*795d594fSAndroid Build Coastguard Worker static void ClearFields(bool is_static,
2718*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> target,
2719*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> target_class)
2720*795d594fSAndroid Build Coastguard Worker REQUIRES(art::Locks::mutator_lock_) {
2721*795d594fSAndroid Build Coastguard Worker DCHECK(!target_class->IsObjectClass());
2722*795d594fSAndroid Build Coastguard Worker for (art::ArtField& f : (is_static ? target_class->GetSFields() : target_class->GetIFields())) {
2723*795d594fSAndroid Build Coastguard Worker ClearField(target, f);
2724*795d594fSAndroid Build Coastguard Worker }
2725*795d594fSAndroid Build Coastguard Worker if (!is_static && !target_class->GetSuperClass()->IsObjectClass()) {
2726*795d594fSAndroid Build Coastguard Worker ClearFields(is_static, target, target_class->GetSuperClass());
2727*795d594fSAndroid Build Coastguard Worker }
2728*795d594fSAndroid Build Coastguard Worker }
2729*795d594fSAndroid Build Coastguard Worker
CopyAndClearFields(bool is_static,art::ObjPtr<art::mirror::Object> target,art::ObjPtr<art::mirror::Class> target_class,art::ObjPtr<art::mirror::Object> source,art::ObjPtr<art::mirror::Class> source_class)2730*795d594fSAndroid Build Coastguard Worker static void CopyAndClearFields(bool is_static,
2731*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> target,
2732*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> target_class,
2733*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> source,
2734*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> source_class)
2735*795d594fSAndroid Build Coastguard Worker REQUIRES(art::Locks::mutator_lock_) {
2736*795d594fSAndroid Build Coastguard Worker // Copy all non-j.l.Object fields
2737*795d594fSAndroid Build Coastguard Worker CopyFields(is_static, target, target_class, source, source_class);
2738*795d594fSAndroid Build Coastguard Worker // Copy the lock-word.
2739*795d594fSAndroid Build Coastguard Worker target->SetLockWord(source->GetLockWord(false), false);
2740*795d594fSAndroid Build Coastguard Worker // Clear (reset) the old one.
2741*795d594fSAndroid Build Coastguard Worker source->SetLockWord(art::LockWord::Default(), false);
2742*795d594fSAndroid Build Coastguard Worker art::WriteBarrier::ForEveryFieldWrite(target);
2743*795d594fSAndroid Build Coastguard Worker
2744*795d594fSAndroid Build Coastguard Worker // Clear the fields from the old class. We don't need it anymore.
2745*795d594fSAndroid Build Coastguard Worker ClearFields(is_static, source, source_class);
2746*795d594fSAndroid Build Coastguard Worker art::WriteBarrier::ForEveryFieldWrite(source);
2747*795d594fSAndroid Build Coastguard Worker }
2748*795d594fSAndroid Build Coastguard Worker
UpdateClassStructurally(const RedefinitionDataIter & holder)2749*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::UpdateClassStructurally(const RedefinitionDataIter& holder) {
2750*795d594fSAndroid Build Coastguard Worker DCHECK(holder.IsActuallyStructural());
2751*795d594fSAndroid Build Coastguard Worker DCHECK(holder.IsInitialStructural());
2752*795d594fSAndroid Build Coastguard Worker // LETS GO. We've got all new class structures so no need to do all the updating of the stacks.
2753*795d594fSAndroid Build Coastguard Worker // Instead we need to update everything else.
2754*795d594fSAndroid Build Coastguard Worker // Just replace the class and be done with it.
2755*795d594fSAndroid Build Coastguard Worker art::Locks::mutator_lock_->AssertExclusiveHeld(driver_->self_);
2756*795d594fSAndroid Build Coastguard Worker art::ClassLinker* cl = driver_->runtime_->GetClassLinker();
2757*795d594fSAndroid Build Coastguard Worker art::ScopedAssertNoThreadSuspension sants(__FUNCTION__);
2758*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> new_classes(holder.GetNewClasses());
2759*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Class>> old_classes(holder.GetOldClasses());
2760*795d594fSAndroid Build Coastguard Worker // Collect mappings from old to new fields/methods
2761*795d594fSAndroid Build Coastguard Worker std::map<art::ArtMethod*, art::ArtMethod*> method_map;
2762*795d594fSAndroid Build Coastguard Worker std::map<art::ArtField*, art::ArtField*> field_map;
2763*795d594fSAndroid Build Coastguard Worker CollectNewFieldAndMethodMappings(holder, &method_map, &field_map);
2764*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> new_instances(
2765*795d594fSAndroid Build Coastguard Worker holder.GetNewInstanceObjects());
2766*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ObjectArray<art::mirror::Object>> old_instances(
2767*795d594fSAndroid Build Coastguard Worker holder.GetOldInstanceObjects());
2768*795d594fSAndroid Build Coastguard Worker // Once we do the ReplaceReferences old_classes will have the new_classes in it. We want to keep
2769*795d594fSAndroid Build Coastguard Worker // ahold of the old classes so copy them now.
2770*795d594fSAndroid Build Coastguard Worker std::vector<art::ObjPtr<art::mirror::Class>> old_classes_vec(old_classes->Iterate().begin(),
2771*795d594fSAndroid Build Coastguard Worker old_classes->Iterate().end());
2772*795d594fSAndroid Build Coastguard Worker // Copy over the static fields of the class and all the instance fields.
2773*795d594fSAndroid Build Coastguard Worker for (auto [new_class, old_class] : art::ZipLeft(new_classes->Iterate(), old_classes->Iterate())) {
2774*795d594fSAndroid Build Coastguard Worker CHECK(!new_class.IsNull());
2775*795d594fSAndroid Build Coastguard Worker CHECK(!old_class.IsNull());
2776*795d594fSAndroid Build Coastguard Worker CHECK(!old_class->IsErroneous());
2777*795d594fSAndroid Build Coastguard Worker if (old_class->GetStatus() > new_class->GetStatus()) {
2778*795d594fSAndroid Build Coastguard Worker // Some verification/initialization step happened during interval between
2779*795d594fSAndroid Build Coastguard Worker // creating the new class and now. Just copy the new status.
2780*795d594fSAndroid Build Coastguard Worker new_class->SetStatusLocked(old_class->GetStatus());
2781*795d594fSAndroid Build Coastguard Worker }
2782*795d594fSAndroid Build Coastguard Worker CopyAndClearFields(true, new_class, new_class, old_class, old_class);
2783*795d594fSAndroid Build Coastguard Worker }
2784*795d594fSAndroid Build Coastguard Worker
2785*795d594fSAndroid Build Coastguard Worker // Copy and clear the fields of the old-instances.
2786*795d594fSAndroid Build Coastguard Worker for (auto [new_instance, old_instance] :
2787*795d594fSAndroid Build Coastguard Worker art::ZipLeft(new_instances->Iterate(), old_instances->Iterate())) {
2788*795d594fSAndroid Build Coastguard Worker CopyAndClearFields(/*is_static=*/false,
2789*795d594fSAndroid Build Coastguard Worker new_instance,
2790*795d594fSAndroid Build Coastguard Worker new_instance->GetClass(),
2791*795d594fSAndroid Build Coastguard Worker old_instance,
2792*795d594fSAndroid Build Coastguard Worker old_instance->GetClass());
2793*795d594fSAndroid Build Coastguard Worker }
2794*795d594fSAndroid Build Coastguard Worker // Mark old class and methods obsolete. Copy over any native implementation as well.
2795*795d594fSAndroid Build Coastguard Worker for (auto [old_class, new_class] : art::ZipLeft(old_classes->Iterate(), new_classes->Iterate())) {
2796*795d594fSAndroid Build Coastguard Worker old_class->SetObsoleteObject();
2797*795d594fSAndroid Build Coastguard Worker // Mark methods obsolete and copy native implementation. We need to wait
2798*795d594fSAndroid Build Coastguard Worker // until later to actually clear the jit data. We copy the native
2799*795d594fSAndroid Build Coastguard Worker // implementation here since we don't want to race with any threads doing
2800*795d594fSAndroid Build Coastguard Worker // RegisterNatives.
2801*795d594fSAndroid Build Coastguard Worker for (art::ArtMethod& m : old_class->GetMethods(art::kRuntimePointerSize)) {
2802*795d594fSAndroid Build Coastguard Worker if (m.IsNative()) {
2803*795d594fSAndroid Build Coastguard Worker art::ArtMethod* new_method =
2804*795d594fSAndroid Build Coastguard Worker new_class->FindClassMethod(m.GetNameView(), m.GetSignature(), art::kRuntimePointerSize);
2805*795d594fSAndroid Build Coastguard Worker DCHECK(new_class->GetMethodsSlice(art::kRuntimePointerSize).Contains(new_method))
2806*795d594fSAndroid Build Coastguard Worker << "Could not find method " << m.PrettyMethod() << " declared in new class!";
2807*795d594fSAndroid Build Coastguard Worker DCHECK(new_method->IsNative());
2808*795d594fSAndroid Build Coastguard Worker new_method->SetEntryPointFromJni(m.GetEntryPointFromJni());
2809*795d594fSAndroid Build Coastguard Worker }
2810*795d594fSAndroid Build Coastguard Worker m.SetIsObsolete();
2811*795d594fSAndroid Build Coastguard Worker cl->SetEntryPointsForObsoleteMethod(&m);
2812*795d594fSAndroid Build Coastguard Worker if (m.IsInvokable()) {
2813*795d594fSAndroid Build Coastguard Worker m.SetDontCompile();
2814*795d594fSAndroid Build Coastguard Worker }
2815*795d594fSAndroid Build Coastguard Worker }
2816*795d594fSAndroid Build Coastguard Worker }
2817*795d594fSAndroid Build Coastguard Worker // Update live pointers in ART code.
2818*795d594fSAndroid Build Coastguard Worker auto could_change_resolution_of = [&](auto* field_or_method,
2819*795d594fSAndroid Build Coastguard Worker const auto& info) REQUIRES(art::Locks::mutator_lock_) {
2820*795d594fSAndroid Build Coastguard Worker constexpr bool is_method = std::is_same_v<art::ArtMethod*, decltype(field_or_method)>;
2821*795d594fSAndroid Build Coastguard Worker static_assert(is_method || std::is_same_v<art::ArtField*, decltype(field_or_method)>,
2822*795d594fSAndroid Build Coastguard Worker "Input is not field or method!");
2823*795d594fSAndroid Build Coastguard Worker // Only dex-cache is used for resolution
2824*795d594fSAndroid Build Coastguard Worker if (LIKELY(info.GetType() != art::ReflectionSourceType::kSourceDexCacheResolvedField &&
2825*795d594fSAndroid Build Coastguard Worker info.GetType() != art::ReflectionSourceType::kSourceDexCacheResolvedMethod)) {
2826*795d594fSAndroid Build Coastguard Worker return false;
2827*795d594fSAndroid Build Coastguard Worker }
2828*795d594fSAndroid Build Coastguard Worker if constexpr (is_method) {
2829*795d594fSAndroid Build Coastguard Worker // Only direct methods are used without further indirection through a vtable/IFTable.
2830*795d594fSAndroid Build Coastguard Worker // Constructors cannot be shadowed.
2831*795d594fSAndroid Build Coastguard Worker if (LIKELY(!field_or_method->IsDirect() || field_or_method->IsConstructor())) {
2832*795d594fSAndroid Build Coastguard Worker return false;
2833*795d594fSAndroid Build Coastguard Worker }
2834*795d594fSAndroid Build Coastguard Worker } else {
2835*795d594fSAndroid Build Coastguard Worker // Only non-private fields can be shadowed in a manner that's visible.
2836*795d594fSAndroid Build Coastguard Worker if (LIKELY(field_or_method->IsPrivate())) {
2837*795d594fSAndroid Build Coastguard Worker return false;
2838*795d594fSAndroid Build Coastguard Worker }
2839*795d594fSAndroid Build Coastguard Worker }
2840*795d594fSAndroid Build Coastguard Worker // We can only shadow things from our superclasses
2841*795d594fSAndroid Build Coastguard Worker auto orig_classes_iter = old_classes->Iterate();
2842*795d594fSAndroid Build Coastguard Worker auto replacement_classes_iter = new_classes->Iterate();
2843*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> f_or_m_class = field_or_method->GetDeclaringClass();
2844*795d594fSAndroid Build Coastguard Worker if (LIKELY(!f_or_m_class->IsAssignableFrom(holder.GetMirrorClass()) &&
2845*795d594fSAndroid Build Coastguard Worker std::find(orig_classes_iter.begin(), orig_classes_iter.end(), f_or_m_class) ==
2846*795d594fSAndroid Build Coastguard Worker orig_classes_iter.end())) {
2847*795d594fSAndroid Build Coastguard Worker return false;
2848*795d594fSAndroid Build Coastguard Worker }
2849*795d594fSAndroid Build Coastguard Worker if constexpr (is_method) {
2850*795d594fSAndroid Build Coastguard Worker return std::any_of(
2851*795d594fSAndroid Build Coastguard Worker replacement_classes_iter.begin(),
2852*795d594fSAndroid Build Coastguard Worker replacement_classes_iter.end(),
2853*795d594fSAndroid Build Coastguard Worker [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
2854*795d594fSAndroid Build Coastguard Worker auto direct_methods = cand->GetDirectMethods(art::kRuntimePointerSize);
2855*795d594fSAndroid Build Coastguard Worker return std::find_if(direct_methods.begin(),
2856*795d594fSAndroid Build Coastguard Worker direct_methods.end(),
2857*795d594fSAndroid Build Coastguard Worker [&](art::ArtMethod& m) REQUIRES(art::Locks::mutator_lock_) {
2858*795d594fSAndroid Build Coastguard Worker return UNLIKELY(m.HasSameNameAndSignature(field_or_method));
2859*795d594fSAndroid Build Coastguard Worker }) != direct_methods.end();
2860*795d594fSAndroid Build Coastguard Worker });
2861*795d594fSAndroid Build Coastguard Worker } else {
2862*795d594fSAndroid Build Coastguard Worker auto pred = [&](art::ArtField& f) REQUIRES(art::Locks::mutator_lock_) {
2863*795d594fSAndroid Build Coastguard Worker return std::string_view(f.GetName()) == std::string_view(field_or_method->GetName()) &&
2864*795d594fSAndroid Build Coastguard Worker std::string_view(f.GetTypeDescriptor()) ==
2865*795d594fSAndroid Build Coastguard Worker std::string_view(field_or_method->GetTypeDescriptor());
2866*795d594fSAndroid Build Coastguard Worker };
2867*795d594fSAndroid Build Coastguard Worker if (field_or_method->IsStatic()) {
2868*795d594fSAndroid Build Coastguard Worker return std::any_of(
2869*795d594fSAndroid Build Coastguard Worker replacement_classes_iter.begin(),
2870*795d594fSAndroid Build Coastguard Worker replacement_classes_iter.end(),
2871*795d594fSAndroid Build Coastguard Worker [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
2872*795d594fSAndroid Build Coastguard Worker auto sfields = cand->GetSFields();
2873*795d594fSAndroid Build Coastguard Worker return std::find_if(sfields.begin(), sfields.end(), pred) != sfields.end();
2874*795d594fSAndroid Build Coastguard Worker });
2875*795d594fSAndroid Build Coastguard Worker } else {
2876*795d594fSAndroid Build Coastguard Worker return std::any_of(
2877*795d594fSAndroid Build Coastguard Worker replacement_classes_iter.begin(),
2878*795d594fSAndroid Build Coastguard Worker replacement_classes_iter.end(),
2879*795d594fSAndroid Build Coastguard Worker [&](art::ObjPtr<art::mirror::Class> cand) REQUIRES(art::Locks::mutator_lock_) {
2880*795d594fSAndroid Build Coastguard Worker auto ifields = cand->GetIFields();
2881*795d594fSAndroid Build Coastguard Worker return std::find_if(ifields.begin(), ifields.end(), pred) != ifields.end();
2882*795d594fSAndroid Build Coastguard Worker });
2883*795d594fSAndroid Build Coastguard Worker }
2884*795d594fSAndroid Build Coastguard Worker }
2885*795d594fSAndroid Build Coastguard Worker };
2886*795d594fSAndroid Build Coastguard Worker // TODO Performing 2 stack-walks back to back isn't the greatest. We might want to try to combine
2887*795d594fSAndroid Build Coastguard Worker // it with the one ReplaceReferences does. Doing so would be rather complicated though.
2888*795d594fSAndroid Build Coastguard Worker driver_->runtime_->VisitReflectiveTargets(
2889*795d594fSAndroid Build Coastguard Worker [&](art::ArtField* f, const auto& info) REQUIRES(art::Locks::mutator_lock_) {
2890*795d594fSAndroid Build Coastguard Worker DCHECK(f != nullptr) << info;
2891*795d594fSAndroid Build Coastguard Worker auto it = field_map.find(f);
2892*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(could_change_resolution_of(f, info))) {
2893*795d594fSAndroid Build Coastguard Worker // Dex-cache Resolution might change. Just clear the resolved value.
2894*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Clearing resolution " << info << " for (field) " << f->PrettyField();
2895*795d594fSAndroid Build Coastguard Worker return static_cast<art::ArtField*>(nullptr);
2896*795d594fSAndroid Build Coastguard Worker } else if (it != field_map.end()) {
2897*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Updating " << info << " object for (field) "
2898*795d594fSAndroid Build Coastguard Worker << it->second->PrettyField();
2899*795d594fSAndroid Build Coastguard Worker return it->second;
2900*795d594fSAndroid Build Coastguard Worker }
2901*795d594fSAndroid Build Coastguard Worker return f;
2902*795d594fSAndroid Build Coastguard Worker },
2903*795d594fSAndroid Build Coastguard Worker [&](art::ArtMethod* m, const auto& info) REQUIRES(art::Locks::mutator_lock_) {
2904*795d594fSAndroid Build Coastguard Worker DCHECK(m != nullptr) << info;
2905*795d594fSAndroid Build Coastguard Worker auto it = method_map.find(m);
2906*795d594fSAndroid Build Coastguard Worker if (UNLIKELY(could_change_resolution_of(m, info))) {
2907*795d594fSAndroid Build Coastguard Worker // Dex-cache Resolution might change. Just clear the resolved value.
2908*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Clearing resolution " << info << " for (method) " << m->PrettyMethod();
2909*795d594fSAndroid Build Coastguard Worker return static_cast<art::ArtMethod*>(nullptr);
2910*795d594fSAndroid Build Coastguard Worker } else if (it != method_map.end()) {
2911*795d594fSAndroid Build Coastguard Worker VLOG(plugin) << "Updating " << info << " object for (method) "
2912*795d594fSAndroid Build Coastguard Worker << it->second->PrettyMethod();
2913*795d594fSAndroid Build Coastguard Worker return it->second;
2914*795d594fSAndroid Build Coastguard Worker }
2915*795d594fSAndroid Build Coastguard Worker return m;
2916*795d594fSAndroid Build Coastguard Worker });
2917*795d594fSAndroid Build Coastguard Worker
2918*795d594fSAndroid Build Coastguard Worker // Force every frame of every thread to deoptimize (any frame might have eg offsets compiled in).
2919*795d594fSAndroid Build Coastguard Worker driver_->runtime_->GetInstrumentation()->DeoptimizeAllThreadFrames();
2920*795d594fSAndroid Build Coastguard Worker
2921*795d594fSAndroid Build Coastguard Worker std::unordered_map<art::ObjPtr<art::mirror::Object>,
2922*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object>,
2923*795d594fSAndroid Build Coastguard Worker art::HashObjPtr> map;
2924*795d594fSAndroid Build Coastguard Worker for (auto [new_class, old_class] : art::ZipLeft(new_classes->Iterate(), old_classes->Iterate())) {
2925*795d594fSAndroid Build Coastguard Worker map.emplace(old_class, new_class);
2926*795d594fSAndroid Build Coastguard Worker }
2927*795d594fSAndroid Build Coastguard Worker for (auto [new_instance, old_instance] :
2928*795d594fSAndroid Build Coastguard Worker art::ZipLeft(new_instances->Iterate(), old_instances->Iterate())) {
2929*795d594fSAndroid Build Coastguard Worker map.emplace(old_instance, new_instance);
2930*795d594fSAndroid Build Coastguard Worker // Bare-bones check that the mapping is correct.
2931*795d594fSAndroid Build Coastguard Worker CHECK(new_instance->GetClass() == map[old_instance->GetClass()]->AsClass())
2932*795d594fSAndroid Build Coastguard Worker << new_instance->GetClass()->PrettyClass() << " vs "
2933*795d594fSAndroid Build Coastguard Worker << map[old_instance->GetClass()]->AsClass()->PrettyClass();
2934*795d594fSAndroid Build Coastguard Worker }
2935*795d594fSAndroid Build Coastguard Worker
2936*795d594fSAndroid Build Coastguard Worker // Actually perform the general replacement. This doesn't affect ArtMethod/ArtFields. It does
2937*795d594fSAndroid Build Coastguard Worker // affect the declaring_class field of all the obsolete objects, which is unfortunate and needs to
2938*795d594fSAndroid Build Coastguard Worker // be undone. This replaces the mirror::Class in 'holder' as well. It's magic!
2939*795d594fSAndroid Build Coastguard Worker HeapExtensions::ReplaceReferences(driver_->self_, map);
2940*795d594fSAndroid Build Coastguard Worker
2941*795d594fSAndroid Build Coastguard Worker // Undo the replacement of old_class with new_class for the methods / fields on the old_class.
2942*795d594fSAndroid Build Coastguard Worker // It is hard to ensure that we don't replace the declaring class of the old class field / methods
2943*795d594fSAndroid Build Coastguard Worker // isn't impacted by ReplaceReferences. It is just simpler to undo the replacement here.
2944*795d594fSAndroid Build Coastguard Worker std::for_each(
2945*795d594fSAndroid Build Coastguard Worker old_classes_vec.cbegin(),
2946*795d594fSAndroid Build Coastguard Worker old_classes_vec.cend(),
2947*795d594fSAndroid Build Coastguard Worker [](art::ObjPtr<art::mirror::Class> orig) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2948*795d594fSAndroid Build Coastguard Worker orig->VisitMethods(
2949*795d594fSAndroid Build Coastguard Worker [&](art::ArtMethod* method) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2950*795d594fSAndroid Build Coastguard Worker if (method->IsCopied()) {
2951*795d594fSAndroid Build Coastguard Worker // Copied methods have interfaces as their declaring class.
2952*795d594fSAndroid Build Coastguard Worker return;
2953*795d594fSAndroid Build Coastguard Worker }
2954*795d594fSAndroid Build Coastguard Worker method->SetDeclaringClass(orig);
2955*795d594fSAndroid Build Coastguard Worker },
2956*795d594fSAndroid Build Coastguard Worker art::kRuntimePointerSize);
2957*795d594fSAndroid Build Coastguard Worker orig->VisitFields([&](art::ArtField* field) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2958*795d594fSAndroid Build Coastguard Worker field->SetDeclaringClass(orig);
2959*795d594fSAndroid Build Coastguard Worker });
2960*795d594fSAndroid Build Coastguard Worker });
2961*795d594fSAndroid Build Coastguard Worker
2962*795d594fSAndroid Build Coastguard Worker // Save the old class so that the JIT gc doesn't get confused by it being collected before the
2963*795d594fSAndroid Build Coastguard Worker // jit code. This is also needed to keep the dex-caches of any obsolete methods live.
2964*795d594fSAndroid Build Coastguard Worker for (auto [new_class, old_class] :
2965*795d594fSAndroid Build Coastguard Worker art::ZipLeft(new_classes->Iterate(), art::MakeIterationRange(old_classes_vec))) {
2966*795d594fSAndroid Build Coastguard Worker new_class->GetExtData()->SetObsoleteClass(old_class);
2967*795d594fSAndroid Build Coastguard Worker }
2968*795d594fSAndroid Build Coastguard Worker
2969*795d594fSAndroid Build Coastguard Worker art::jit::Jit* jit = driver_->runtime_->GetJit();
2970*795d594fSAndroid Build Coastguard Worker if (jit != nullptr) {
2971*795d594fSAndroid Build Coastguard Worker // Clear jit.
2972*795d594fSAndroid Build Coastguard Worker // TODO We might want to have some way to tell the JIT not to wait the kJitSamplesBatchSize
2973*795d594fSAndroid Build Coastguard Worker // invokes to start compiling things again.
2974*795d594fSAndroid Build Coastguard Worker jit->GetCodeCache()->InvalidateAllCompiledCode();
2975*795d594fSAndroid Build Coastguard Worker }
2976*795d594fSAndroid Build Coastguard Worker
2977*795d594fSAndroid Build Coastguard Worker // Clear thread caches
2978*795d594fSAndroid Build Coastguard Worker {
2979*795d594fSAndroid Build Coastguard Worker // TODO We might be able to avoid doing this but given the rather unstructured nature of the
2980*795d594fSAndroid Build Coastguard Worker // interpreter cache it's probably not worth the effort.
2981*795d594fSAndroid Build Coastguard Worker art::MutexLock mu(driver_->self_, *art::Locks::thread_list_lock_);
2982*795d594fSAndroid Build Coastguard Worker driver_->runtime_->GetThreadList()->ForEach(
2983*795d594fSAndroid Build Coastguard Worker [](art::Thread* t) { t->GetInterpreterCache()->Clear(t); });
2984*795d594fSAndroid Build Coastguard Worker }
2985*795d594fSAndroid Build Coastguard Worker
2986*795d594fSAndroid Build Coastguard Worker if (art::kIsDebugBuild) {
2987*795d594fSAndroid Build Coastguard Worker // Just make sure we didn't screw up any of the now obsolete methods or fields. We need their
2988*795d594fSAndroid Build Coastguard Worker // declaring-class to still be the obolete class
2989*795d594fSAndroid Build Coastguard Worker std::for_each(
2990*795d594fSAndroid Build Coastguard Worker old_classes_vec.cbegin(),
2991*795d594fSAndroid Build Coastguard Worker old_classes_vec.cend(),
2992*795d594fSAndroid Build Coastguard Worker [](art::ObjPtr<art::mirror::Class> orig) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2993*795d594fSAndroid Build Coastguard Worker orig->VisitMethods(
2994*795d594fSAndroid Build Coastguard Worker [&](art::ArtMethod* method) REQUIRES_SHARED(art::Locks::mutator_lock_) {
2995*795d594fSAndroid Build Coastguard Worker if (method->IsCopied()) {
2996*795d594fSAndroid Build Coastguard Worker // Copied methods have interfaces as their declaring class.
2997*795d594fSAndroid Build Coastguard Worker return;
2998*795d594fSAndroid Build Coastguard Worker }
2999*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(method->GetDeclaringClass(), orig)
3000*795d594fSAndroid Build Coastguard Worker << method->GetDeclaringClass()->PrettyClass() << " vs " << orig->PrettyClass();
3001*795d594fSAndroid Build Coastguard Worker },
3002*795d594fSAndroid Build Coastguard Worker art::kRuntimePointerSize);
3003*795d594fSAndroid Build Coastguard Worker orig->VisitFields([&](art::ArtField* field) REQUIRES_SHARED(art::Locks::mutator_lock_) {
3004*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(field->GetDeclaringClass(), orig)
3005*795d594fSAndroid Build Coastguard Worker << field->GetDeclaringClass()->PrettyClass() << " vs " << orig->PrettyClass();
3006*795d594fSAndroid Build Coastguard Worker });
3007*795d594fSAndroid Build Coastguard Worker });
3008*795d594fSAndroid Build Coastguard Worker }
3009*795d594fSAndroid Build Coastguard Worker }
3010*795d594fSAndroid Build Coastguard Worker
3011*795d594fSAndroid Build Coastguard Worker // Redefines the class in place
UpdateClassInPlace(const RedefinitionDataIter & holder)3012*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::UpdateClassInPlace(const RedefinitionDataIter& holder) {
3013*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> mclass(holder.GetMirrorClass());
3014*795d594fSAndroid Build Coastguard Worker // TODO Rewrite so we don't do a stack walk for each and every class.
3015*795d594fSAndroid Build Coastguard Worker FindAndAllocateObsoleteMethods(mclass);
3016*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::DexCache> new_dex_cache(holder.GetNewDexCache());
3017*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Object> original_dex_file(holder.GetOriginalDexFile());
3018*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(dex_file_->NumClassDefs(), 1u);
3019*795d594fSAndroid Build Coastguard Worker const art::dex::ClassDef& class_def = dex_file_->GetClassDef(0);
3020*795d594fSAndroid Build Coastguard Worker UpdateMethods(mclass, class_def);
3021*795d594fSAndroid Build Coastguard Worker UpdateFields(mclass);
3022*795d594fSAndroid Build Coastguard Worker
3023*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ClassExt> ext(mclass->GetExtData());
3024*795d594fSAndroid Build Coastguard Worker CHECK(!ext.IsNull());
3025*795d594fSAndroid Build Coastguard Worker ext->SetOriginalDexFile(original_dex_file);
3026*795d594fSAndroid Build Coastguard Worker
3027*795d594fSAndroid Build Coastguard Worker // If this is the first time the class is being redefined, store
3028*795d594fSAndroid Build Coastguard Worker // the native DexFile pointer and initial ClassDef index in ClassExt.
3029*795d594fSAndroid Build Coastguard Worker // This preserves the pointer for hiddenapi access checks which need
3030*795d594fSAndroid Build Coastguard Worker // to read access flags from the initial DexFile.
3031*795d594fSAndroid Build Coastguard Worker if (ext->GetPreRedefineDexFile() == nullptr) {
3032*795d594fSAndroid Build Coastguard Worker ext->SetPreRedefineDexFile(&mclass->GetDexFile());
3033*795d594fSAndroid Build Coastguard Worker ext->SetPreRedefineClassDefIndex(mclass->GetDexClassDefIndex());
3034*795d594fSAndroid Build Coastguard Worker }
3035*795d594fSAndroid Build Coastguard Worker
3036*795d594fSAndroid Build Coastguard Worker // Update the class fields.
3037*795d594fSAndroid Build Coastguard Worker // Need to update class last since the ArtMethod gets its DexFile from the class (which is needed
3038*795d594fSAndroid Build Coastguard Worker // to call GetReturnTypeDescriptor and GetParameterTypeList above).
3039*795d594fSAndroid Build Coastguard Worker mclass->SetDexCache(new_dex_cache.Ptr());
3040*795d594fSAndroid Build Coastguard Worker mclass->SetDexClassDefIndex(dex_file_->GetIndexForClassDef(class_def));
3041*795d594fSAndroid Build Coastguard Worker mclass->SetDexTypeIndex(dex_file_->GetIndexForTypeId(*dex_file_->FindTypeId(class_sig_.c_str())));
3042*795d594fSAndroid Build Coastguard Worker
3043*795d594fSAndroid Build Coastguard Worker // Notify the jit that all the methods in this class were redefined. Need to do this last since
3044*795d594fSAndroid Build Coastguard Worker // the jit relies on the dex_file_ being correct (for native methods at least) to find the method
3045*795d594fSAndroid Build Coastguard Worker // meta-data.
3046*795d594fSAndroid Build Coastguard Worker art::jit::Jit* jit = driver_->runtime_->GetJit();
3047*795d594fSAndroid Build Coastguard Worker if (jit != nullptr) {
3048*795d594fSAndroid Build Coastguard Worker art::PointerSize image_pointer_size =
3049*795d594fSAndroid Build Coastguard Worker driver_->runtime_->GetClassLinker()->GetImagePointerSize();
3050*795d594fSAndroid Build Coastguard Worker auto code_cache = jit->GetCodeCache();
3051*795d594fSAndroid Build Coastguard Worker // Non-invokable methods don't have any JIT data associated with them so we don't need to tell
3052*795d594fSAndroid Build Coastguard Worker // the jit about them.
3053*795d594fSAndroid Build Coastguard Worker for (art::ArtMethod& method : mclass->GetDeclaredMethods(image_pointer_size)) {
3054*795d594fSAndroid Build Coastguard Worker if (method.IsInvokable()) {
3055*795d594fSAndroid Build Coastguard Worker code_cache->NotifyMethodRedefined(&method);
3056*795d594fSAndroid Build Coastguard Worker }
3057*795d594fSAndroid Build Coastguard Worker }
3058*795d594fSAndroid Build Coastguard Worker }
3059*795d594fSAndroid Build Coastguard Worker }
3060*795d594fSAndroid Build Coastguard Worker
3061*795d594fSAndroid Build Coastguard Worker // Performs final updates to class for redefinition.
UpdateClass(const RedefinitionDataIter & holder)3062*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::UpdateClass(const RedefinitionDataIter& holder) {
3063*795d594fSAndroid Build Coastguard Worker CHECK(holder.IsInitialized());
3064*795d594fSAndroid Build Coastguard Worker if (holder.IsInitialStructural()) {
3065*795d594fSAndroid Build Coastguard Worker UpdateClassStructurally(holder);
3066*795d594fSAndroid Build Coastguard Worker } else if (!holder.IsActuallyStructural()) {
3067*795d594fSAndroid Build Coastguard Worker UpdateClassInPlace(holder);
3068*795d594fSAndroid Build Coastguard Worker }
3069*795d594fSAndroid Build Coastguard Worker }
3070*795d594fSAndroid Build Coastguard Worker
3071*795d594fSAndroid Build Coastguard Worker // Restores the old obsolete methods maps if it turns out they weren't needed (ie there were no new
3072*795d594fSAndroid Build Coastguard Worker // obsolete methods).
RestoreObsoleteMethodMapsIfUnneeded(const RedefinitionDataIter * cur_data)3073*795d594fSAndroid Build Coastguard Worker void Redefiner::ClassRedefinition::RestoreObsoleteMethodMapsIfUnneeded(
3074*795d594fSAndroid Build Coastguard Worker const RedefinitionDataIter* cur_data) {
3075*795d594fSAndroid Build Coastguard Worker if (cur_data->IsActuallyStructural()) {
3076*795d594fSAndroid Build Coastguard Worker // We didn't touch these in this case.
3077*795d594fSAndroid Build Coastguard Worker return;
3078*795d594fSAndroid Build Coastguard Worker }
3079*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::Class> klass = GetMirrorClass();
3080*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::ClassExt> ext = klass->GetExtData();
3081*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::PointerArray> methods = ext->GetObsoleteMethods();
3082*795d594fSAndroid Build Coastguard Worker art::ObjPtr<art::mirror::PointerArray> old_methods = cur_data->GetOldObsoleteMethods();
3083*795d594fSAndroid Build Coastguard Worker int32_t old_length = old_methods == nullptr ? 0 : old_methods->GetLength();
3084*795d594fSAndroid Build Coastguard Worker int32_t expected_length =
3085*795d594fSAndroid Build Coastguard Worker old_length + klass->NumDirectMethods() + klass->NumDeclaredVirtualMethods();
3086*795d594fSAndroid Build Coastguard Worker // Check to make sure we are only undoing this one.
3087*795d594fSAndroid Build Coastguard Worker if (methods.IsNull()) {
3088*795d594fSAndroid Build Coastguard Worker // No new obsolete methods! We can get rid of the maps.
3089*795d594fSAndroid Build Coastguard Worker ext->SetObsoleteArrays(cur_data->GetOldObsoleteMethods(), cur_data->GetOldDexCaches());
3090*795d594fSAndroid Build Coastguard Worker } else if (expected_length == methods->GetLength()) {
3091*795d594fSAndroid Build Coastguard Worker for (int32_t i = 0; i < expected_length; i++) {
3092*795d594fSAndroid Build Coastguard Worker art::ArtMethod* expected = nullptr;
3093*795d594fSAndroid Build Coastguard Worker if (i < old_length) {
3094*795d594fSAndroid Build Coastguard Worker expected = old_methods->GetElementPtrSize<art::ArtMethod*>(i, art::kRuntimePointerSize);
3095*795d594fSAndroid Build Coastguard Worker }
3096*795d594fSAndroid Build Coastguard Worker if (methods->GetElementPtrSize<art::ArtMethod*>(i, art::kRuntimePointerSize) != expected) {
3097*795d594fSAndroid Build Coastguard Worker // We actually have some new obsolete methods. Just abort since we cannot safely shrink the
3098*795d594fSAndroid Build Coastguard Worker // obsolete methods array.
3099*795d594fSAndroid Build Coastguard Worker return;
3100*795d594fSAndroid Build Coastguard Worker }
3101*795d594fSAndroid Build Coastguard Worker }
3102*795d594fSAndroid Build Coastguard Worker // No new obsolete methods! We can get rid of the maps.
3103*795d594fSAndroid Build Coastguard Worker ext->SetObsoleteArrays(cur_data->GetOldObsoleteMethods(), cur_data->GetOldDexCaches());
3104*795d594fSAndroid Build Coastguard Worker }
3105*795d594fSAndroid Build Coastguard Worker }
3106*795d594fSAndroid Build Coastguard Worker
3107*795d594fSAndroid Build Coastguard Worker // This function does all (java) allocations we need to do for the Class being redefined.
3108*795d594fSAndroid Build Coastguard Worker // TODO Change this name maybe?
EnsureClassAllocationsFinished(RedefinitionDataIter * cur_data)3109*795d594fSAndroid Build Coastguard Worker bool Redefiner::ClassRedefinition::EnsureClassAllocationsFinished(
3110*795d594fSAndroid Build Coastguard Worker /*out*/RedefinitionDataIter* cur_data) {
3111*795d594fSAndroid Build Coastguard Worker art::StackHandleScope<2> hs(driver_->self_);
3112*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::Class> klass(hs.NewHandle(
3113*795d594fSAndroid Build Coastguard Worker driver_->self_->DecodeJObject(klass_)->AsClass()));
3114*795d594fSAndroid Build Coastguard Worker if (klass == nullptr) {
3115*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(INVALID_CLASS), "Unable to decode class argument!");
3116*795d594fSAndroid Build Coastguard Worker return false;
3117*795d594fSAndroid Build Coastguard Worker }
3118*795d594fSAndroid Build Coastguard Worker // Allocate the classExt
3119*795d594fSAndroid Build Coastguard Worker art::Handle<art::mirror::ClassExt> ext =
3120*795d594fSAndroid Build Coastguard Worker hs.NewHandle(art::mirror::Class::EnsureExtDataPresent(klass, driver_->self_));
3121*795d594fSAndroid Build Coastguard Worker if (ext == nullptr) {
3122*795d594fSAndroid Build Coastguard Worker // No memory. Clear exception (it's not useful) and return error.
3123*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
3124*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
3125*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(OUT_OF_MEMORY), "Could not allocate ClassExt");
3126*795d594fSAndroid Build Coastguard Worker return false;
3127*795d594fSAndroid Build Coastguard Worker }
3128*795d594fSAndroid Build Coastguard Worker if (!cur_data->IsActuallyStructural()) {
3129*795d594fSAndroid Build Coastguard Worker CHECK(!IsStructuralRedefinition());
3130*795d594fSAndroid Build Coastguard Worker // First save the old values of the 2 arrays that make up the obsolete methods maps. Then
3131*795d594fSAndroid Build Coastguard Worker // allocate the 2 arrays that make up the obsolete methods map. Since the contents of the arrays
3132*795d594fSAndroid Build Coastguard Worker // are only modified when all threads (other than the modifying one) are suspended we don't need
3133*795d594fSAndroid Build Coastguard Worker // to worry about missing the unsynchronized writes to the array. We do synchronize when setting
3134*795d594fSAndroid Build Coastguard Worker // it however, since that can happen at any time.
3135*795d594fSAndroid Build Coastguard Worker cur_data->SetOldObsoleteMethods(ext->GetObsoleteMethods());
3136*795d594fSAndroid Build Coastguard Worker cur_data->SetOldDexCaches(ext->GetObsoleteDexCaches());
3137*795d594fSAndroid Build Coastguard Worker // FIXME: The `ClassExt::ExtendObsoleteArrays()` is non-atomic and does not ensure proper
3138*795d594fSAndroid Build Coastguard Worker // memory visibility, so it can race with `ArtMethod::GetObsoleteDexCache()`.
3139*795d594fSAndroid Build Coastguard Worker // We should allocate the new arrays here but record it in the redefinition data and set the
3140*795d594fSAndroid Build Coastguard Worker // new arrays in `ClassExt` later with all other threads suspended.
3141*795d594fSAndroid Build Coastguard Worker if (!art::mirror::ClassExt::ExtendObsoleteArrays(
3142*795d594fSAndroid Build Coastguard Worker ext, driver_->self_, klass->GetDeclaredMethodsSlice(art::kRuntimePointerSize).size())) {
3143*795d594fSAndroid Build Coastguard Worker // OOM. Clear exception and return error.
3144*795d594fSAndroid Build Coastguard Worker driver_->self_->AssertPendingOOMException();
3145*795d594fSAndroid Build Coastguard Worker driver_->self_->ClearException();
3146*795d594fSAndroid Build Coastguard Worker RecordFailure(ERR(OUT_OF_MEMORY), "Unable to allocate/extend obsolete methods map");
3147*795d594fSAndroid Build Coastguard Worker return false;
3148*795d594fSAndroid Build Coastguard Worker }
3149*795d594fSAndroid Build Coastguard Worker }
3150*795d594fSAndroid Build Coastguard Worker return true;
3151*795d594fSAndroid Build Coastguard Worker }
3152*795d594fSAndroid Build Coastguard Worker
3153*795d594fSAndroid Build Coastguard Worker } // namespace openjdkjvmti
3154