blob: 5c5431d5d905a40ef74bc381cfc820ed7e31b7ce [file] [log] [blame]
Orion Hodson811bd5f2016-12-07 11:35:37 +00001/*
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
Andreas Gampe0a0935f2017-10-23 11:59:49 -070020#include "android-base/logging.h"
Orion Hodson811bd5f2016-12-07 11:35:37 +000021#include "art_field.h"
22#include "art_method.h"
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080023#include "base/locks.h"
Andreas Gampe0a0935f2017-10-23 11:59:49 -070024#include "base/macros.h"
Orion Hodson811bd5f2016-12-07 11:35:37 +000025#include "class_linker.h"
David Sehr9e734c72018-01-04 17:56:19 -080026#include "dex/code_item_accessors.h"
David Sehr67bf42e2018-02-26 16:43:04 -080027#include "dex/primitive.h"
Andreas Gampe0a0935f2017-10-23 11:59:49 -070028#include "handle_scope-inl.h"
29#include "instrumentation.h"
Alex Light0aa7a5a2018-10-10 15:58:14 +000030#include "interpreter/interpreter.h"
Andreas Gampe0a0935f2017-10-23 11:59:49 -070031#include "interpreter/shadow_frame.h"
Orion Hodson811bd5f2016-12-07 11:35:37 +000032#include "interpreter/unstarted_runtime.h"
Andreas Gampec5b75642018-05-16 15:12:11 -070033#include "jvalue-inl.h"
Andreas Gampe0a0935f2017-10-23 11:59:49 -070034#include "mirror/class.h"
35#include "mirror/object.h"
36#include "obj_ptr-inl.h"
Orion Hodson811bd5f2016-12-07 11:35:37 +000037#include "runtime.h"
38#include "stack.h"
39#include "thread.h"
40
41namespace art {
42
43namespace interpreter {
44 void ArtInterpreterToInterpreterBridge(Thread* self,
45 const DexFile::CodeItem* code_item,
46 ShadowFrame* shadow_frame,
47 JValue* result)
48 REQUIRES_SHARED(Locks::mutator_lock_);
49
50 void ArtInterpreterToCompiledCodeBridge(Thread* self,
51 ArtMethod* caller,
Orion Hodson811bd5f2016-12-07 11:35:37 +000052 ShadowFrame* shadow_frame,
Jeff Hao5ea84132017-05-05 16:59:29 -070053 uint16_t arg_offset,
Orion Hodson811bd5f2016-12-07 11:35:37 +000054 JValue* result);
55} // namespace interpreter
56
57inline void PerformCall(Thread* self,
Mathieu Chartier808c7a52017-12-15 11:19:33 -080058 const CodeItemDataAccessor& accessor,
Orion Hodson811bd5f2016-12-07 11:35:37 +000059 ArtMethod* caller_method,
60 const size_t first_dest_reg,
61 ShadowFrame* callee_frame,
Jeff Hao5ea84132017-05-05 16:59:29 -070062 JValue* result,
63 bool use_interpreter_entrypoint)
Orion Hodson811bd5f2016-12-07 11:35:37 +000064 REQUIRES_SHARED(Locks::mutator_lock_) {
65 if (LIKELY(Runtime::Current()->IsStarted())) {
Jeff Hao5ea84132017-05-05 16:59:29 -070066 if (use_interpreter_entrypoint) {
Mathieu Chartier808c7a52017-12-15 11:19:33 -080067 interpreter::ArtInterpreterToInterpreterBridge(self, accessor, callee_frame, result);
Orion Hodson811bd5f2016-12-07 11:35:37 +000068 } else {
69 interpreter::ArtInterpreterToCompiledCodeBridge(
Jeff Hao5ea84132017-05-05 16:59:29 -070070 self, caller_method, callee_frame, first_dest_reg, result);
Orion Hodson811bd5f2016-12-07 11:35:37 +000071 }
72 } else {
Mathieu Chartier808c7a52017-12-15 11:19:33 -080073 interpreter::UnstartedRuntime::Invoke(self, accessor, callee_frame, result, first_dest_reg);
Orion Hodson811bd5f2016-12-07 11:35:37 +000074 }
75}
76
Andreas Gampe580667b2017-10-23 11:20:39 -070077template <typename T>
78inline void DCheckStaticState(Thread* self, T* entity) REQUIRES_SHARED(Locks::mutator_lock_) {
79 if (kIsDebugBuild) {
80 ObjPtr<mirror::Class> klass = entity->GetDeclaringClass();
81 if (entity->IsStatic()) {
82 klass->AssertInitializedOrInitializingInThread(self);
83 } else {
84 CHECK(klass->IsInitializing() || klass->IsErroneousResolved());
85 }
86 }
87}
88
Orion Hodson811bd5f2016-12-07 11:35:37 +000089template<Primitive::Type field_type>
Alex Light084fa372017-06-16 08:58:34 -070090static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self,
Orion Hodson811bd5f2016-12-07 11:35:37 +000091 const ShadowFrame& shadow_frame,
92 ObjPtr<mirror::Object> obj,
93 ArtField* field,
94 JValue* result)
95 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe580667b2017-10-23 11:20:39 -070096 DCheckStaticState(self, field);
Orion Hodson811bd5f2016-12-07 11:35:37 +000097
98 // Report this field access to instrumentation if needed.
99 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
100 if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
101 StackHandleScope<1> hs(self);
102 // Wrap in handle wrapper in case the listener does thread suspension.
103 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
104 ObjPtr<mirror::Object> this_object;
105 if (!field->IsStatic()) {
106 this_object = obj;
107 }
108 instrumentation->FieldReadEvent(self,
109 this_object.Ptr(),
110 shadow_frame.GetMethod(),
111 shadow_frame.GetDexPC(),
112 field);
Alex Light084fa372017-06-16 08:58:34 -0700113 if (UNLIKELY(self->IsExceptionPending())) {
114 return false;
115 }
Orion Hodson811bd5f2016-12-07 11:35:37 +0000116 }
117
118 switch (field_type) {
119 case Primitive::kPrimBoolean:
120 result->SetZ(field->GetBoolean(obj));
121 break;
122 case Primitive::kPrimByte:
123 result->SetB(field->GetByte(obj));
124 break;
125 case Primitive::kPrimChar:
126 result->SetC(field->GetChar(obj));
127 break;
128 case Primitive::kPrimShort:
129 result->SetS(field->GetShort(obj));
130 break;
131 case Primitive::kPrimInt:
132 result->SetI(field->GetInt(obj));
133 break;
134 case Primitive::kPrimLong:
135 result->SetJ(field->GetLong(obj));
136 break;
137 case Primitive::kPrimNot:
138 result->SetL(field->GetObject(obj));
139 break;
140 case Primitive::kPrimVoid:
141 LOG(FATAL) << "Unreachable " << field_type;
142 break;
143 }
Alex Light084fa372017-06-16 08:58:34 -0700144 return true;
Orion Hodson811bd5f2016-12-07 11:35:37 +0000145}
146
147template<Primitive::Type field_type, bool do_assignability_check, bool transaction_active>
148ALWAYS_INLINE bool DoFieldPutCommon(Thread* self,
149 const ShadowFrame& shadow_frame,
150 ObjPtr<mirror::Object> obj,
151 ArtField* field,
Alex Light084fa372017-06-16 08:58:34 -0700152 JValue& value)
Orion Hodson811bd5f2016-12-07 11:35:37 +0000153 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe580667b2017-10-23 11:20:39 -0700154 DCheckStaticState(self, field);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000155
156 // Report this field access to instrumentation if needed. Since we only have the offset of
157 // the field from the base of the object, we need to look for it first.
158 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
159 if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
Alex Light084fa372017-06-16 08:58:34 -0700160 StackHandleScope<2> hs(self);
161 // Save this and return value (if needed) in case the instrumentation causes a suspend.
Orion Hodson811bd5f2016-12-07 11:35:37 +0000162 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
163 ObjPtr<mirror::Object> this_object = field->IsStatic() ? nullptr : obj;
Alex Light084fa372017-06-16 08:58:34 -0700164 mirror::Object* fake_root = nullptr;
165 HandleWrapper<mirror::Object> ret(hs.NewHandleWrapper<mirror::Object>(
166 field_type == Primitive::kPrimNot ? value.GetGCRoot() : &fake_root));
167 instrumentation->FieldWriteEvent(self,
168 this_object.Ptr(),
Orion Hodson811bd5f2016-12-07 11:35:37 +0000169 shadow_frame.GetMethod(),
170 shadow_frame.GetDexPC(),
171 field,
172 value);
Alex Light084fa372017-06-16 08:58:34 -0700173 if (UNLIKELY(self->IsExceptionPending())) {
174 return false;
175 }
Alex Light0aa7a5a2018-10-10 15:58:14 +0000176 if (shadow_frame.GetForcePopFrame()) {
177 // We need to check this here since we expect that the FieldWriteEvent happens before the
178 // actual field write. If one pops the stack we should not modify the field. The next
179 // instruction will force a pop. Return true.
180 DCHECK(Runtime::Current()->AreNonStandardExitsEnabled());
181 DCHECK(interpreter::PrevFrameWillRetry(self, shadow_frame));
182 return true;
183 }
Orion Hodson811bd5f2016-12-07 11:35:37 +0000184 }
185
186 switch (field_type) {
187 case Primitive::kPrimBoolean:
188 field->SetBoolean<transaction_active>(obj, value.GetZ());
189 break;
190 case Primitive::kPrimByte:
191 field->SetByte<transaction_active>(obj, value.GetB());
192 break;
193 case Primitive::kPrimChar:
194 field->SetChar<transaction_active>(obj, value.GetC());
195 break;
196 case Primitive::kPrimShort:
197 field->SetShort<transaction_active>(obj, value.GetS());
198 break;
199 case Primitive::kPrimInt:
200 field->SetInt<transaction_active>(obj, value.GetI());
201 break;
202 case Primitive::kPrimLong:
203 field->SetLong<transaction_active>(obj, value.GetJ());
204 break;
205 case Primitive::kPrimNot: {
206 ObjPtr<mirror::Object> reg = value.GetL();
207 if (do_assignability_check && reg != nullptr) {
208 // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the
209 // object in the destructor.
210 ObjPtr<mirror::Class> field_class;
211 {
212 StackHandleScope<2> hs(self);
213 HandleWrapperObjPtr<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
214 HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
Vladimir Marko4098a7a2017-11-06 16:00:51 +0000215 field_class = field->ResolveType();
Orion Hodson811bd5f2016-12-07 11:35:37 +0000216 }
Orion Hodson9fa1bab2018-05-23 15:21:35 +0100217 // ArtField::ResolveType() may fail as evidenced with a dexing bug (b/78788577).
218 if (UNLIKELY(field_class.IsNull())) {
219 Thread::Current()->AssertPendingException();
220 return false;
221 }
222 if (UNLIKELY(!reg->VerifierInstanceOf(field_class.Ptr()))) {
Orion Hodson811bd5f2016-12-07 11:35:37 +0000223 // This should never happen.
224 std::string temp1, temp2, temp3;
225 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
226 "Put '%s' that is not instance of field '%s' in '%s'",
227 reg->GetClass()->GetDescriptor(&temp1),
228 field_class->GetDescriptor(&temp2),
229 field->GetDeclaringClass()->GetDescriptor(&temp3));
230 return false;
231 }
232 }
233 field->SetObj<transaction_active>(obj, reg);
234 break;
235 }
236 case Primitive::kPrimVoid: {
237 LOG(FATAL) << "Unreachable " << field_type;
238 break;
239 }
240 }
Chang Xingbd208d82017-07-12 14:53:17 -0700241 if (transaction_active) {
242 if (UNLIKELY(self->IsExceptionPending())) {
243 return false;
244 }
245 }
Orion Hodson811bd5f2016-12-07 11:35:37 +0000246 return true;
247}
248
249} // namespace art
250
251#endif // ART_RUNTIME_COMMON_DEX_OPERATIONS_H_