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