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