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(®));
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