1 /*
2  * Copyright (C) 2016 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 #ifndef ART_RUNTIME_COMMON_DEX_OPERATIONS_H_
18 #define ART_RUNTIME_COMMON_DEX_OPERATIONS_H_
19 
20 #include "android-base/logging.h"
21 #include "art_field.h"
22 #include "art_method.h"
23 #include "base/locks.h"
24 #include "base/macros.h"
25 #include "class_linker.h"
26 #include "dex/code_item_accessors.h"
27 #include "dex/dex_file_structs.h"
28 #include "dex/primitive.h"
29 #include "handle_scope-inl.h"
30 #include "instrumentation.h"
31 #include "interpreter/interpreter.h"
32 #include "interpreter/shadow_frame.h"
33 #include "interpreter/unstarted_runtime.h"
34 #include "jvalue-inl.h"
35 #include "mirror/class.h"
36 #include "mirror/object.h"
37 #include "obj_ptr-inl.h"
38 #include "reflective_handle.h"
39 #include "reflective_handle_scope.h"
40 #include "runtime.h"
41 #include "stack.h"
42 #include "thread.h"
43 
44 namespace art {
45 
46 namespace interpreter {
47   void ArtInterpreterToInterpreterBridge(Thread* self,
48                                         const dex::CodeItem* code_item,
49                                         ShadowFrame* shadow_frame,
50                                         JValue* result)
51      REQUIRES_SHARED(Locks::mutator_lock_);
52 
53   void ArtInterpreterToCompiledCodeBridge(Thread* self,
54                                           ArtMethod* caller,
55                                           ShadowFrame* shadow_frame,
56                                           uint16_t arg_offset,
57                                           JValue* result);
58 }  // namespace interpreter
59 
PerformCall(Thread * self,const CodeItemDataAccessor & accessor,ArtMethod * caller_method,const size_t first_dest_reg,ShadowFrame * callee_frame,JValue * result,bool use_interpreter_entrypoint)60 inline void PerformCall(Thread* self,
61                         const CodeItemDataAccessor& accessor,
62                         ArtMethod* caller_method,
63                         const size_t first_dest_reg,
64                         ShadowFrame* callee_frame,
65                         JValue* result,
66                         bool use_interpreter_entrypoint)
67     REQUIRES_SHARED(Locks::mutator_lock_) {
68   if (LIKELY(Runtime::Current()->IsStarted())) {
69     if (use_interpreter_entrypoint) {
70       interpreter::ArtInterpreterToInterpreterBridge(self, accessor, callee_frame, result);
71     } else {
72       interpreter::ArtInterpreterToCompiledCodeBridge(
73           self, caller_method, callee_frame, first_dest_reg, result);
74     }
75   } else {
76     interpreter::UnstartedRuntime::Invoke(self, accessor, callee_frame, result, first_dest_reg);
77   }
78 }
79 
80 template <typename T>
DCheckStaticState(Thread * self,T * entity)81 inline void DCheckStaticState(Thread* self, T* entity) REQUIRES_SHARED(Locks::mutator_lock_) {
82   if (kIsDebugBuild) {
83     ObjPtr<mirror::Class> klass = entity->GetDeclaringClass();
84     if (entity->IsStatic()) {
85       klass->AssertInitializedOrInitializingInThread(self);
86     } else {
87       CHECK(klass->IsInitializing() || klass->IsErroneousResolved());
88     }
89   }
90 }
91 
92 template<Primitive::Type field_type>
DoFieldGetCommon(Thread * self,const ShadowFrame & shadow_frame,ObjPtr<mirror::Object> obj,ArtField * field,JValue * result)93 static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self,
94                                            const ShadowFrame& shadow_frame,
95                                            ObjPtr<mirror::Object> obj,
96                                            ArtField* field,
97                                            JValue* result)
98     REQUIRES_SHARED(Locks::mutator_lock_) {
99   DCheckStaticState(self, field);
100 
101   // Report this field access to instrumentation if needed.
102   instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
103   if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
104     StackHandleScope<1> hs(self);
105     StackArtFieldHandleScope<1> rhs(self);
106     // Wrap in handle wrapper in case the listener does thread suspension.
107     HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
108     ReflectiveHandleWrapper<ArtField> fh(rhs.NewReflectiveHandleWrapper(&field));
109     ObjPtr<mirror::Object> this_object;
110     if (!field->IsStatic()) {
111       this_object = obj;
112     }
113     instrumentation->FieldReadEvent(self,
114                                     this_object,
115                                     shadow_frame.GetMethod(),
116                                     shadow_frame.GetDexPC(),
117                                     field);
118     if (UNLIKELY(self->IsExceptionPending())) {
119       return false;
120     }
121   }
122 
123   switch (field_type) {
124     case Primitive::kPrimBoolean:
125       result->SetZ(field->GetBoolean(obj));
126       break;
127     case Primitive::kPrimByte:
128       result->SetB(field->GetByte(obj));
129       break;
130     case Primitive::kPrimChar:
131       result->SetC(field->GetChar(obj));
132       break;
133     case Primitive::kPrimShort:
134       result->SetS(field->GetShort(obj));
135       break;
136     case Primitive::kPrimInt:
137       result->SetI(field->GetInt(obj));
138       break;
139     case Primitive::kPrimLong:
140       result->SetJ(field->GetLong(obj));
141       break;
142     case Primitive::kPrimNot:
143       result->SetL(field->GetObject(obj));
144       break;
145     case Primitive::kPrimVoid:
146       LOG(FATAL) << "Unreachable " << field_type;
147       break;
148   }
149   return true;
150 }
151 
152 template<Primitive::Type field_type, bool do_assignability_check, bool transaction_active>
DoFieldPutCommon(Thread * self,const ShadowFrame & shadow_frame,ObjPtr<mirror::Object> obj,ArtField * field,JValue & value)153 ALWAYS_INLINE bool DoFieldPutCommon(Thread* self,
154                                     const ShadowFrame& shadow_frame,
155                                     ObjPtr<mirror::Object> obj,
156                                     ArtField* field,
157                                     JValue& value)
158     REQUIRES_SHARED(Locks::mutator_lock_) {
159   DCheckStaticState(self, field);
160 
161   // Report this field access to instrumentation if needed. Since we only have the offset of
162   // the field from the base of the object, we need to look for it first.
163   instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
164   if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
165     StackHandleScope<2> hs(self);
166     StackArtFieldHandleScope<1> rhs(self);
167     // Save this and return value (if needed) in case the instrumentation causes a suspend.
168     HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
169     ReflectiveHandleWrapper<ArtField> fh(rhs.NewReflectiveHandleWrapper(&field));
170     ObjPtr<mirror::Object> this_object = field->IsStatic() ? nullptr : obj;
171     mirror::Object* fake_root = nullptr;
172     HandleWrapper<mirror::Object> ret(hs.NewHandleWrapper<mirror::Object>(
173         field_type == Primitive::kPrimNot ? value.GetGCRoot() : &fake_root));
174     instrumentation->FieldWriteEvent(self,
175                                      this_object,
176                                      shadow_frame.GetMethod(),
177                                      shadow_frame.GetDexPC(),
178                                      field,
179                                      value);
180     if (UNLIKELY(self->IsExceptionPending())) {
181       return false;
182     }
183     if (shadow_frame.GetForcePopFrame()) {
184       // We need to check this here since we expect that the FieldWriteEvent happens before the
185       // actual field write. If one pops the stack we should not modify the field.  The next
186       // instruction will force a pop. Return true.
187       DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
188       return true;
189     }
190   }
191 
192   switch (field_type) {
193     case Primitive::kPrimBoolean:
194       field->SetBoolean<transaction_active>(obj, value.GetZ());
195       break;
196     case Primitive::kPrimByte:
197       field->SetByte<transaction_active>(obj, value.GetB());
198       break;
199     case Primitive::kPrimChar:
200       field->SetChar<transaction_active>(obj, value.GetC());
201       break;
202     case Primitive::kPrimShort:
203       field->SetShort<transaction_active>(obj, value.GetS());
204       break;
205     case Primitive::kPrimInt:
206       field->SetInt<transaction_active>(obj, value.GetI());
207       break;
208     case Primitive::kPrimLong:
209       field->SetLong<transaction_active>(obj, value.GetJ());
210       break;
211     case Primitive::kPrimNot: {
212       ObjPtr<mirror::Object> reg = value.GetL();
213       if (do_assignability_check && reg != nullptr) {
214         // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the
215         // object in the destructor.
216         ObjPtr<mirror::Class> field_class;
217         {
218           StackHandleScope<2> hs(self);
219           StackArtFieldHandleScope<1> rhs(self);
220           HandleWrapperObjPtr<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
221           HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
222           ReflectiveHandleWrapper<ArtField> fh(rhs.NewReflectiveHandleWrapper(&field));
223           field_class = field->ResolveType();
224         }
225         // ArtField::ResolveType() may fail as evidenced with a dexing bug (b/78788577).
226         if (UNLIKELY(field_class.IsNull())) {
227           Thread::Current()->AssertPendingException();
228           return false;
229         }
230         if (UNLIKELY(!reg->VerifierInstanceOf(field_class))) {
231           // This should never happen.
232           std::string temp1, temp2, temp3;
233           self->ThrowNewExceptionF("Ljava/lang/InternalError;",
234                                    "Put '%s' that is not instance of field '%s' in '%s'",
235                                    reg->GetClass()->GetDescriptor(&temp1),
236                                    field_class->GetDescriptor(&temp2),
237                                    field->GetDeclaringClass()->GetDescriptor(&temp3));
238           return false;
239         }
240       }
241       field->SetObj<transaction_active>(obj, reg);
242       break;
243     }
244     case Primitive::kPrimVoid: {
245       LOG(FATAL) << "Unreachable " << field_type;
246       break;
247     }
248   }
249   if (transaction_active) {
250     if (UNLIKELY(self->IsExceptionPending())) {
251       return false;
252     }
253   }
254   return true;
255 }
256 
257 }  // namespace art
258 
259 #endif  // ART_RUNTIME_COMMON_DEX_OPERATIONS_H_
260