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