blob: 267735fe956a0c9b79539727c0660417750e98b0 [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 Gampe0a0935f2017-10-23 11:59:49 -070023#include "base/macros.h"
24#include "base/mutex.h"
Orion Hodson811bd5f2016-12-07 11:35:37 +000025#include "class_linker.h"
Andreas Gampe0a0935f2017-10-23 11:59:49 -070026#include "handle_scope-inl.h"
27#include "instrumentation.h"
28#include "interpreter/shadow_frame.h"
Orion Hodson811bd5f2016-12-07 11:35:37 +000029#include "interpreter/unstarted_runtime.h"
Andreas Gampe0a0935f2017-10-23 11:59:49 -070030#include "mirror/class.h"
31#include "mirror/object.h"
32#include "obj_ptr-inl.h"
33#include "primitive.h"
Orion Hodson811bd5f2016-12-07 11:35:37 +000034#include "runtime.h"
35#include "stack.h"
36#include "thread.h"
37
38namespace art {
39
40namespace interpreter {
41 void ArtInterpreterToInterpreterBridge(Thread* self,
42 const DexFile::CodeItem* code_item,
43 ShadowFrame* shadow_frame,
44 JValue* result)
45 REQUIRES_SHARED(Locks::mutator_lock_);
46
47 void ArtInterpreterToCompiledCodeBridge(Thread* self,
48 ArtMethod* caller,
Orion Hodson811bd5f2016-12-07 11:35:37 +000049 ShadowFrame* shadow_frame,
Jeff Hao5ea84132017-05-05 16:59:29 -070050 uint16_t arg_offset,
Orion Hodson811bd5f2016-12-07 11:35:37 +000051 JValue* result);
52} // namespace interpreter
53
54inline void PerformCall(Thread* self,
55 const DexFile::CodeItem* code_item,
56 ArtMethod* caller_method,
57 const size_t first_dest_reg,
58 ShadowFrame* callee_frame,
Jeff Hao5ea84132017-05-05 16:59:29 -070059 JValue* result,
60 bool use_interpreter_entrypoint)
Orion Hodson811bd5f2016-12-07 11:35:37 +000061 REQUIRES_SHARED(Locks::mutator_lock_) {
62 if (LIKELY(Runtime::Current()->IsStarted())) {
Jeff Hao5ea84132017-05-05 16:59:29 -070063 if (use_interpreter_entrypoint) {
Orion Hodson811bd5f2016-12-07 11:35:37 +000064 interpreter::ArtInterpreterToInterpreterBridge(self, code_item, callee_frame, result);
65 } else {
66 interpreter::ArtInterpreterToCompiledCodeBridge(
Jeff Hao5ea84132017-05-05 16:59:29 -070067 self, caller_method, callee_frame, first_dest_reg, result);
Orion Hodson811bd5f2016-12-07 11:35:37 +000068 }
69 } else {
70 interpreter::UnstartedRuntime::Invoke(self, code_item, callee_frame, result, first_dest_reg);
71 }
72}
73
Andreas Gampe580667b2017-10-23 11:20:39 -070074template <typename T>
75inline void DCheckStaticState(Thread* self, T* entity) REQUIRES_SHARED(Locks::mutator_lock_) {
76 if (kIsDebugBuild) {
77 ObjPtr<mirror::Class> klass = entity->GetDeclaringClass();
78 if (entity->IsStatic()) {
79 klass->AssertInitializedOrInitializingInThread(self);
80 } else {
81 CHECK(klass->IsInitializing() || klass->IsErroneousResolved());
82 }
83 }
84}
85
Orion Hodson811bd5f2016-12-07 11:35:37 +000086template<Primitive::Type field_type>
Alex Light084fa372017-06-16 08:58:34 -070087static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self,
Orion Hodson811bd5f2016-12-07 11:35:37 +000088 const ShadowFrame& shadow_frame,
89 ObjPtr<mirror::Object> obj,
90 ArtField* field,
91 JValue* result)
92 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe580667b2017-10-23 11:20:39 -070093 DCheckStaticState(self, field);
Orion Hodson811bd5f2016-12-07 11:35:37 +000094
95 // Report this field access to instrumentation if needed.
96 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
97 if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
98 StackHandleScope<1> hs(self);
99 // Wrap in handle wrapper in case the listener does thread suspension.
100 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
101 ObjPtr<mirror::Object> this_object;
102 if (!field->IsStatic()) {
103 this_object = obj;
104 }
105 instrumentation->FieldReadEvent(self,
106 this_object.Ptr(),
107 shadow_frame.GetMethod(),
108 shadow_frame.GetDexPC(),
109 field);
Alex Light084fa372017-06-16 08:58:34 -0700110 if (UNLIKELY(self->IsExceptionPending())) {
111 return false;
112 }
Orion Hodson811bd5f2016-12-07 11:35:37 +0000113 }
114
115 switch (field_type) {
116 case Primitive::kPrimBoolean:
117 result->SetZ(field->GetBoolean(obj));
118 break;
119 case Primitive::kPrimByte:
120 result->SetB(field->GetByte(obj));
121 break;
122 case Primitive::kPrimChar:
123 result->SetC(field->GetChar(obj));
124 break;
125 case Primitive::kPrimShort:
126 result->SetS(field->GetShort(obj));
127 break;
128 case Primitive::kPrimInt:
129 result->SetI(field->GetInt(obj));
130 break;
131 case Primitive::kPrimLong:
132 result->SetJ(field->GetLong(obj));
133 break;
134 case Primitive::kPrimNot:
135 result->SetL(field->GetObject(obj));
136 break;
137 case Primitive::kPrimVoid:
138 LOG(FATAL) << "Unreachable " << field_type;
139 break;
140 }
Alex Light084fa372017-06-16 08:58:34 -0700141 return true;
Orion Hodson811bd5f2016-12-07 11:35:37 +0000142}
143
144template<Primitive::Type field_type, bool do_assignability_check, bool transaction_active>
145ALWAYS_INLINE bool DoFieldPutCommon(Thread* self,
146 const ShadowFrame& shadow_frame,
147 ObjPtr<mirror::Object> obj,
148 ArtField* field,
Alex Light084fa372017-06-16 08:58:34 -0700149 JValue& value)
Orion Hodson811bd5f2016-12-07 11:35:37 +0000150 REQUIRES_SHARED(Locks::mutator_lock_) {
Andreas Gampe580667b2017-10-23 11:20:39 -0700151 DCheckStaticState(self, field);
Orion Hodson811bd5f2016-12-07 11:35:37 +0000152
153 // Report this field access to instrumentation if needed. Since we only have the offset of
154 // the field from the base of the object, we need to look for it first.
155 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
156 if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
Alex Light084fa372017-06-16 08:58:34 -0700157 StackHandleScope<2> hs(self);
158 // Save this and return value (if needed) in case the instrumentation causes a suspend.
Orion Hodson811bd5f2016-12-07 11:35:37 +0000159 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
160 ObjPtr<mirror::Object> this_object = field->IsStatic() ? nullptr : obj;
Alex Light084fa372017-06-16 08:58:34 -0700161 mirror::Object* fake_root = nullptr;
162 HandleWrapper<mirror::Object> ret(hs.NewHandleWrapper<mirror::Object>(
163 field_type == Primitive::kPrimNot ? value.GetGCRoot() : &fake_root));
164 instrumentation->FieldWriteEvent(self,
165 this_object.Ptr(),
Orion Hodson811bd5f2016-12-07 11:35:37 +0000166 shadow_frame.GetMethod(),
167 shadow_frame.GetDexPC(),
168 field,
169 value);
Alex Light084fa372017-06-16 08:58:34 -0700170 if (UNLIKELY(self->IsExceptionPending())) {
171 return false;
172 }
Orion Hodson811bd5f2016-12-07 11:35:37 +0000173 }
174
175 switch (field_type) {
176 case Primitive::kPrimBoolean:
177 field->SetBoolean<transaction_active>(obj, value.GetZ());
178 break;
179 case Primitive::kPrimByte:
180 field->SetByte<transaction_active>(obj, value.GetB());
181 break;
182 case Primitive::kPrimChar:
183 field->SetChar<transaction_active>(obj, value.GetC());
184 break;
185 case Primitive::kPrimShort:
186 field->SetShort<transaction_active>(obj, value.GetS());
187 break;
188 case Primitive::kPrimInt:
189 field->SetInt<transaction_active>(obj, value.GetI());
190 break;
191 case Primitive::kPrimLong:
192 field->SetLong<transaction_active>(obj, value.GetJ());
193 break;
194 case Primitive::kPrimNot: {
195 ObjPtr<mirror::Object> reg = value.GetL();
196 if (do_assignability_check && reg != nullptr) {
197 // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the
198 // object in the destructor.
199 ObjPtr<mirror::Class> field_class;
200 {
201 StackHandleScope<2> hs(self);
202 HandleWrapperObjPtr<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
203 HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
Vladimir Marko4098a7a2017-11-06 16:00:51 +0000204 field_class = field->ResolveType();
Orion Hodson811bd5f2016-12-07 11:35:37 +0000205 }
206 if (!reg->VerifierInstanceOf(field_class.Ptr())) {
207 // This should never happen.
208 std::string temp1, temp2, temp3;
209 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
210 "Put '%s' that is not instance of field '%s' in '%s'",
211 reg->GetClass()->GetDescriptor(&temp1),
212 field_class->GetDescriptor(&temp2),
213 field->GetDeclaringClass()->GetDescriptor(&temp3));
214 return false;
215 }
216 }
217 field->SetObj<transaction_active>(obj, reg);
218 break;
219 }
220 case Primitive::kPrimVoid: {
221 LOG(FATAL) << "Unreachable " << field_type;
222 break;
223 }
224 }
Chang Xingbd208d82017-07-12 14:53:17 -0700225 if (transaction_active) {
226 if (UNLIKELY(self->IsExceptionPending())) {
227 return false;
228 }
229 }
Orion Hodson811bd5f2016-12-07 11:35:37 +0000230 return true;
231}
232
233} // namespace art
234
235#endif // ART_RUNTIME_COMMON_DEX_OPERATIONS_H_