xref: /aosp_15_r20/art/dex2oat/interpreter/interpreter_switch_impl1.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker // The interpreter function takes considerable time to compile and link.
18*795d594fSAndroid Build Coastguard Worker // We compile the explicit definitions separately to speed up the build.
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "interpreter/interpreter_switch_impl-inl.h"
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "aot_class_linker.h"
23*795d594fSAndroid Build Coastguard Worker #include "transaction.h"
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
26*795d594fSAndroid Build Coastguard Worker namespace interpreter {
27*795d594fSAndroid Build Coastguard Worker 
28*795d594fSAndroid Build Coastguard Worker class ActiveTransactionChecker {
29*795d594fSAndroid Build Coastguard Worker  public:
WriteConstraint(Thread * self,ObjPtr<mirror::Object> obj)30*795d594fSAndroid Build Coastguard Worker   static inline bool WriteConstraint(Thread* self, ObjPtr<mirror::Object> obj)
31*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
32*795d594fSAndroid Build Coastguard Worker     return GetClassLinker()->TransactionWriteConstraint(self, obj);
33*795d594fSAndroid Build Coastguard Worker   }
34*795d594fSAndroid Build Coastguard Worker 
WriteValueConstraint(Thread * self,ObjPtr<mirror::Object> value)35*795d594fSAndroid Build Coastguard Worker   static inline bool WriteValueConstraint(Thread* self, ObjPtr<mirror::Object> value)
36*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
37*795d594fSAndroid Build Coastguard Worker     return GetClassLinker()->TransactionWriteValueConstraint(self, value);
38*795d594fSAndroid Build Coastguard Worker   }
39*795d594fSAndroid Build Coastguard Worker 
ReadConstraint(Thread * self,ObjPtr<mirror::Object> obj)40*795d594fSAndroid Build Coastguard Worker   static inline bool ReadConstraint(Thread* self, ObjPtr<mirror::Object> obj)
41*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
42*795d594fSAndroid Build Coastguard Worker     return GetClassLinker()->TransactionReadConstraint(self, obj);
43*795d594fSAndroid Build Coastguard Worker   }
44*795d594fSAndroid Build Coastguard Worker 
AllocationConstraint(Thread * self,ObjPtr<mirror::Class> klass)45*795d594fSAndroid Build Coastguard Worker   static inline bool AllocationConstraint(Thread* self, ObjPtr<mirror::Class> klass)
46*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
47*795d594fSAndroid Build Coastguard Worker     return GetClassLinker()->TransactionAllocationConstraint(self, klass);
48*795d594fSAndroid Build Coastguard Worker   }
49*795d594fSAndroid Build Coastguard Worker 
IsTransactionAborted()50*795d594fSAndroid Build Coastguard Worker   static inline bool IsTransactionAborted() {
51*795d594fSAndroid Build Coastguard Worker     return GetClassLinker()->IsTransactionAborted();
52*795d594fSAndroid Build Coastguard Worker   }
53*795d594fSAndroid Build Coastguard Worker 
54*795d594fSAndroid Build Coastguard Worker   static void RecordArrayElementsInTransaction(ObjPtr<mirror::Object> array, int32_t count)
55*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
56*795d594fSAndroid Build Coastguard Worker 
RecordNewObject(ObjPtr<mirror::Object> new_object)57*795d594fSAndroid Build Coastguard Worker   static void RecordNewObject(ObjPtr<mirror::Object> new_object)
58*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
59*795d594fSAndroid Build Coastguard Worker     GetClassLinker()->GetTransaction()->RecordNewObject(new_object);
60*795d594fSAndroid Build Coastguard Worker   }
61*795d594fSAndroid Build Coastguard Worker 
RecordNewArray(ObjPtr<mirror::Array> new_object)62*795d594fSAndroid Build Coastguard Worker   static void RecordNewArray(ObjPtr<mirror::Array> new_object)
63*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
64*795d594fSAndroid Build Coastguard Worker     GetClassLinker()->GetTransaction()->RecordNewArray(new_object);
65*795d594fSAndroid Build Coastguard Worker   }
66*795d594fSAndroid Build Coastguard Worker 
67*795d594fSAndroid Build Coastguard Worker  private:
GetClassLinker()68*795d594fSAndroid Build Coastguard Worker   static AotClassLinker* GetClassLinker() {
69*795d594fSAndroid Build Coastguard Worker     return down_cast<AotClassLinker*>(Runtime::Current()->GetClassLinker());
70*795d594fSAndroid Build Coastguard Worker   }
71*795d594fSAndroid Build Coastguard Worker };
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker // TODO: Use ObjPtr here.
74*795d594fSAndroid Build Coastguard Worker template<typename T>
RecordArrayElementsInTransactionImpl(Transaction * transaction,ObjPtr<mirror::PrimitiveArray<T>> array,int32_t count)75*795d594fSAndroid Build Coastguard Worker static void RecordArrayElementsInTransactionImpl(Transaction* transaction,
76*795d594fSAndroid Build Coastguard Worker                                                  ObjPtr<mirror::PrimitiveArray<T>> array,
77*795d594fSAndroid Build Coastguard Worker                                                  int32_t count)
78*795d594fSAndroid Build Coastguard Worker     REQUIRES_SHARED(Locks::mutator_lock_) {
79*795d594fSAndroid Build Coastguard Worker   for (int32_t i = 0; i < count; ++i) {
80*795d594fSAndroid Build Coastguard Worker     transaction->RecordWriteArray(array.Ptr(), i, array->GetWithoutChecks(i));
81*795d594fSAndroid Build Coastguard Worker   }
82*795d594fSAndroid Build Coastguard Worker }
83*795d594fSAndroid Build Coastguard Worker 
RecordArrayElementsInTransaction(ObjPtr<mirror::Object> array,int32_t count)84*795d594fSAndroid Build Coastguard Worker void ActiveTransactionChecker::RecordArrayElementsInTransaction(ObjPtr<mirror::Object> array,
85*795d594fSAndroid Build Coastguard Worker                                                                 int32_t count) {
86*795d594fSAndroid Build Coastguard Worker   DCHECK(Runtime::Current()->IsActiveTransaction());
87*795d594fSAndroid Build Coastguard Worker   if (array == nullptr) {
88*795d594fSAndroid Build Coastguard Worker     return;  // The interpreter shall throw NPE.
89*795d594fSAndroid Build Coastguard Worker   }
90*795d594fSAndroid Build Coastguard Worker   DCHECK(array->IsArrayInstance());
91*795d594fSAndroid Build Coastguard Worker   DCHECK_LE(count, array->AsArray()->GetLength());
92*795d594fSAndroid Build Coastguard Worker   Transaction* transaction = GetClassLinker()->GetTransaction();
93*795d594fSAndroid Build Coastguard Worker   if (!transaction->ArrayNeedsTransactionRecords(array->AsArray())) {
94*795d594fSAndroid Build Coastguard Worker     return;
95*795d594fSAndroid Build Coastguard Worker   }
96*795d594fSAndroid Build Coastguard Worker   // No read barrier is needed for reading a chain of constant references
97*795d594fSAndroid Build Coastguard Worker   // for reading a constant primitive value, see `ReadBarrierOption`.
98*795d594fSAndroid Build Coastguard Worker   Primitive::Type primitive_component_type =
99*795d594fSAndroid Build Coastguard Worker       array->GetClass<kDefaultVerifyFlags, kWithoutReadBarrier>()
100*795d594fSAndroid Build Coastguard Worker           ->GetComponentType<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetPrimitiveType();
101*795d594fSAndroid Build Coastguard Worker   switch (primitive_component_type) {
102*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimBoolean:
103*795d594fSAndroid Build Coastguard Worker       RecordArrayElementsInTransactionImpl(transaction, array->AsBooleanArray(), count);
104*795d594fSAndroid Build Coastguard Worker       break;
105*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimByte:
106*795d594fSAndroid Build Coastguard Worker       RecordArrayElementsInTransactionImpl(transaction, array->AsByteArray(), count);
107*795d594fSAndroid Build Coastguard Worker       break;
108*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimChar:
109*795d594fSAndroid Build Coastguard Worker       RecordArrayElementsInTransactionImpl(transaction, array->AsCharArray(), count);
110*795d594fSAndroid Build Coastguard Worker       break;
111*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimShort:
112*795d594fSAndroid Build Coastguard Worker       RecordArrayElementsInTransactionImpl(transaction, array->AsShortArray(), count);
113*795d594fSAndroid Build Coastguard Worker       break;
114*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimInt:
115*795d594fSAndroid Build Coastguard Worker       RecordArrayElementsInTransactionImpl(transaction, array->AsIntArray(), count);
116*795d594fSAndroid Build Coastguard Worker       break;
117*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimFloat:
118*795d594fSAndroid Build Coastguard Worker       RecordArrayElementsInTransactionImpl(transaction, array->AsFloatArray(), count);
119*795d594fSAndroid Build Coastguard Worker       break;
120*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimLong:
121*795d594fSAndroid Build Coastguard Worker       RecordArrayElementsInTransactionImpl(transaction, array->AsLongArray(), count);
122*795d594fSAndroid Build Coastguard Worker       break;
123*795d594fSAndroid Build Coastguard Worker     case Primitive::kPrimDouble:
124*795d594fSAndroid Build Coastguard Worker       RecordArrayElementsInTransactionImpl(transaction, array->AsDoubleArray(), count);
125*795d594fSAndroid Build Coastguard Worker       break;
126*795d594fSAndroid Build Coastguard Worker     default:
127*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "Unsupported primitive type " << primitive_component_type
128*795d594fSAndroid Build Coastguard Worker                  << " in fill-array-data";
129*795d594fSAndroid Build Coastguard Worker       UNREACHABLE();
130*795d594fSAndroid Build Coastguard Worker   }
131*795d594fSAndroid Build Coastguard Worker }
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker class InactiveInstrumentationHandler {
134*795d594fSAndroid Build Coastguard Worker  public:
135*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE WARN_UNUSED
HasFieldReadListeners(const instrumentation::Instrumentation * instrumentation)136*795d594fSAndroid Build Coastguard Worker   static bool HasFieldReadListeners(const instrumentation::Instrumentation* instrumentation)
137*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
138*795d594fSAndroid Build Coastguard Worker     DCHECK(!instrumentation->HasFieldReadListeners());
139*795d594fSAndroid Build Coastguard Worker     return false;
140*795d594fSAndroid Build Coastguard Worker   }
141*795d594fSAndroid Build Coastguard Worker 
142*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE WARN_UNUSED
HasFieldWriteListeners(const instrumentation::Instrumentation * instrumentation)143*795d594fSAndroid Build Coastguard Worker   static bool HasFieldWriteListeners(const instrumentation::Instrumentation* instrumentation)
144*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
145*795d594fSAndroid Build Coastguard Worker     DCHECK(!instrumentation->HasFieldWriteListeners());
146*795d594fSAndroid Build Coastguard Worker     return false;
147*795d594fSAndroid Build Coastguard Worker   }
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE WARN_UNUSED
HasBranchListeners(const instrumentation::Instrumentation * instrumentation)150*795d594fSAndroid Build Coastguard Worker   static bool HasBranchListeners(const instrumentation::Instrumentation* instrumentation)
151*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
152*795d594fSAndroid Build Coastguard Worker     DCHECK(!instrumentation->HasBranchListeners());
153*795d594fSAndroid Build Coastguard Worker     return false;
154*795d594fSAndroid Build Coastguard Worker   }
155*795d594fSAndroid Build Coastguard Worker 
156*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE WARN_UNUSED
NeedsDexPcEvents(ShadowFrame & shadow_frame)157*795d594fSAndroid Build Coastguard Worker   static bool NeedsDexPcEvents(ShadowFrame& shadow_frame)
158*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
159*795d594fSAndroid Build Coastguard Worker     DCHECK(!shadow_frame.GetNotifyDexPcMoveEvents());
160*795d594fSAndroid Build Coastguard Worker     DCHECK(!Runtime::Current()->GetInstrumentation()->HasDexPcListeners());
161*795d594fSAndroid Build Coastguard Worker     return false;
162*795d594fSAndroid Build Coastguard Worker   }
163*795d594fSAndroid Build Coastguard Worker 
164*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE WARN_UNUSED
NeedsMethodExitEvent(const instrumentation::Instrumentation * instrumentation)165*795d594fSAndroid Build Coastguard Worker   static bool NeedsMethodExitEvent(const instrumentation::Instrumentation* instrumentation)
166*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
167*795d594fSAndroid Build Coastguard Worker     DCHECK(!interpreter::NeedsMethodExitEvent(instrumentation));
168*795d594fSAndroid Build Coastguard Worker     return false;
169*795d594fSAndroid Build Coastguard Worker   }
170*795d594fSAndroid Build Coastguard Worker 
171*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE WARN_UNUSED
GetForcePopFrame(ShadowFrame & shadow_frame)172*795d594fSAndroid Build Coastguard Worker   static bool GetForcePopFrame(ShadowFrame& shadow_frame) {
173*795d594fSAndroid Build Coastguard Worker     DCHECK(!shadow_frame.GetForcePopFrame());
174*795d594fSAndroid Build Coastguard Worker     DCHECK(!Runtime::Current()->AreNonStandardExitsEnabled());
175*795d594fSAndroid Build Coastguard Worker     return false;
176*795d594fSAndroid Build Coastguard Worker   }
177*795d594fSAndroid Build Coastguard Worker 
178*795d594fSAndroid Build Coastguard Worker   NO_RETURN
Branch(Thread * self,ArtMethod * method,uint32_t dex_pc,int32_t dex_pc_offset,const instrumentation::Instrumentation * instrumentation)179*795d594fSAndroid Build Coastguard Worker   static void Branch([[maybe_unused]] Thread* self,
180*795d594fSAndroid Build Coastguard Worker                      [[maybe_unused]] ArtMethod* method,
181*795d594fSAndroid Build Coastguard Worker                      [[maybe_unused]] uint32_t dex_pc,
182*795d594fSAndroid Build Coastguard Worker                      [[maybe_unused]] int32_t dex_pc_offset,
183*795d594fSAndroid Build Coastguard Worker                      [[maybe_unused]] const instrumentation::Instrumentation* instrumentation)
184*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
185*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "UNREACHABLE";
186*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
187*795d594fSAndroid Build Coastguard Worker   }
188*795d594fSAndroid Build Coastguard Worker 
ExceptionHandledEvent(Thread * self,bool is_move_exception,const instrumentation::Instrumentation * instrumentation)189*795d594fSAndroid Build Coastguard Worker   static bool ExceptionHandledEvent(
190*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] Thread* self,
191*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] bool is_move_exception,
192*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] const instrumentation::Instrumentation* instrumentation)
193*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
194*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "UNREACHABLE";
195*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
196*795d594fSAndroid Build Coastguard Worker   }
197*795d594fSAndroid Build Coastguard Worker 
DoDexPcMoveEvent(Thread * self,const CodeItemDataAccessor & accessor,const ShadowFrame & shadow_frame,uint32_t dex_pc,const instrumentation::Instrumentation * instrumentation,JValue * save_ref)198*795d594fSAndroid Build Coastguard Worker   static bool DoDexPcMoveEvent(
199*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] Thread* self,
200*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] const CodeItemDataAccessor& accessor,
201*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] const ShadowFrame& shadow_frame,
202*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] uint32_t dex_pc,
203*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] const instrumentation::Instrumentation* instrumentation,
204*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] JValue* save_ref)
205*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
206*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "UNREACHABLE";
207*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
208*795d594fSAndroid Build Coastguard Worker   }
209*795d594fSAndroid Build Coastguard Worker 
210*795d594fSAndroid Build Coastguard Worker   template <typename T>
SendMethodExitEvents(Thread * self,const instrumentation::Instrumentation * instrumentation,ShadowFrame & frame,ArtMethod * method,T & result)211*795d594fSAndroid Build Coastguard Worker   static bool SendMethodExitEvents(
212*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] Thread* self,
213*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] const instrumentation::Instrumentation* instrumentation,
214*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] ShadowFrame& frame,
215*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] ArtMethod* method,
216*795d594fSAndroid Build Coastguard Worker       [[maybe_unused]] T& result) REQUIRES_SHARED(Locks::mutator_lock_) {
217*795d594fSAndroid Build Coastguard Worker     LOG(FATAL) << "UNREACHABLE";
218*795d594fSAndroid Build Coastguard Worker     UNREACHABLE();
219*795d594fSAndroid Build Coastguard Worker   }
220*795d594fSAndroid Build Coastguard Worker };
221*795d594fSAndroid Build Coastguard Worker 
222*795d594fSAndroid Build Coastguard Worker // Explicit definition of ExecuteSwitchImplCpp.
223*795d594fSAndroid Build Coastguard Worker template
224*795d594fSAndroid Build Coastguard Worker void ExecuteSwitchImplCpp<true>(SwitchImplContext* ctx);
225*795d594fSAndroid Build Coastguard Worker 
226*795d594fSAndroid Build Coastguard Worker }  // namespace interpreter
227*795d594fSAndroid Build Coastguard Worker }  // namespace art
228