blob: 528db96dd586e467f770689e96acd6393c1e8379 [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
20#include "art_field.h"
21#include "art_method.h"
22#include "class_linker.h"
23#include "interpreter/unstarted_runtime.h"
24#include "runtime.h"
25#include "stack.h"
26#include "thread.h"
27
28namespace art {
29
30namespace interpreter {
31 void ArtInterpreterToInterpreterBridge(Thread* self,
32 const DexFile::CodeItem* code_item,
33 ShadowFrame* shadow_frame,
34 JValue* result)
35 REQUIRES_SHARED(Locks::mutator_lock_);
36
37 void ArtInterpreterToCompiledCodeBridge(Thread* self,
38 ArtMethod* caller,
Orion Hodson811bd5f2016-12-07 11:35:37 +000039 ShadowFrame* shadow_frame,
Jeff Hao5ea84132017-05-05 16:59:29 -070040 uint16_t arg_offset,
Orion Hodson811bd5f2016-12-07 11:35:37 +000041 JValue* result);
42} // namespace interpreter
43
44inline void PerformCall(Thread* self,
45 const DexFile::CodeItem* code_item,
46 ArtMethod* caller_method,
47 const size_t first_dest_reg,
48 ShadowFrame* callee_frame,
Jeff Hao5ea84132017-05-05 16:59:29 -070049 JValue* result,
50 bool use_interpreter_entrypoint)
Orion Hodson811bd5f2016-12-07 11:35:37 +000051 REQUIRES_SHARED(Locks::mutator_lock_) {
52 if (LIKELY(Runtime::Current()->IsStarted())) {
Jeff Hao5ea84132017-05-05 16:59:29 -070053 if (use_interpreter_entrypoint) {
Orion Hodson811bd5f2016-12-07 11:35:37 +000054 interpreter::ArtInterpreterToInterpreterBridge(self, code_item, callee_frame, result);
55 } else {
56 interpreter::ArtInterpreterToCompiledCodeBridge(
Jeff Hao5ea84132017-05-05 16:59:29 -070057 self, caller_method, callee_frame, first_dest_reg, result);
Orion Hodson811bd5f2016-12-07 11:35:37 +000058 }
59 } else {
60 interpreter::UnstartedRuntime::Invoke(self, code_item, callee_frame, result, first_dest_reg);
61 }
62}
63
64template<Primitive::Type field_type>
Alex Light084fa372017-06-16 08:58:34 -070065static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self,
Orion Hodson811bd5f2016-12-07 11:35:37 +000066 const ShadowFrame& shadow_frame,
67 ObjPtr<mirror::Object> obj,
68 ArtField* field,
69 JValue* result)
70 REQUIRES_SHARED(Locks::mutator_lock_) {
71 field->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
72
73 // Report this field access to instrumentation if needed.
74 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
75 if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
76 StackHandleScope<1> hs(self);
77 // Wrap in handle wrapper in case the listener does thread suspension.
78 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
79 ObjPtr<mirror::Object> this_object;
80 if (!field->IsStatic()) {
81 this_object = obj;
82 }
83 instrumentation->FieldReadEvent(self,
84 this_object.Ptr(),
85 shadow_frame.GetMethod(),
86 shadow_frame.GetDexPC(),
87 field);
Alex Light084fa372017-06-16 08:58:34 -070088 if (UNLIKELY(self->IsExceptionPending())) {
89 return false;
90 }
Orion Hodson811bd5f2016-12-07 11:35:37 +000091 }
92
93 switch (field_type) {
94 case Primitive::kPrimBoolean:
95 result->SetZ(field->GetBoolean(obj));
96 break;
97 case Primitive::kPrimByte:
98 result->SetB(field->GetByte(obj));
99 break;
100 case Primitive::kPrimChar:
101 result->SetC(field->GetChar(obj));
102 break;
103 case Primitive::kPrimShort:
104 result->SetS(field->GetShort(obj));
105 break;
106 case Primitive::kPrimInt:
107 result->SetI(field->GetInt(obj));
108 break;
109 case Primitive::kPrimLong:
110 result->SetJ(field->GetLong(obj));
111 break;
112 case Primitive::kPrimNot:
113 result->SetL(field->GetObject(obj));
114 break;
115 case Primitive::kPrimVoid:
116 LOG(FATAL) << "Unreachable " << field_type;
117 break;
118 }
Alex Light084fa372017-06-16 08:58:34 -0700119 return true;
Orion Hodson811bd5f2016-12-07 11:35:37 +0000120}
121
122template<Primitive::Type field_type, bool do_assignability_check, bool transaction_active>
123ALWAYS_INLINE bool DoFieldPutCommon(Thread* self,
124 const ShadowFrame& shadow_frame,
125 ObjPtr<mirror::Object> obj,
126 ArtField* field,
Alex Light084fa372017-06-16 08:58:34 -0700127 JValue& value)
Orion Hodson811bd5f2016-12-07 11:35:37 +0000128 REQUIRES_SHARED(Locks::mutator_lock_) {
129 field->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
130
131 // Report this field access to instrumentation if needed. Since we only have the offset of
132 // the field from the base of the object, we need to look for it first.
133 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
134 if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
Alex Light084fa372017-06-16 08:58:34 -0700135 StackHandleScope<2> hs(self);
136 // Save this and return value (if needed) in case the instrumentation causes a suspend.
Orion Hodson811bd5f2016-12-07 11:35:37 +0000137 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
138 ObjPtr<mirror::Object> this_object = field->IsStatic() ? nullptr : obj;
Alex Light084fa372017-06-16 08:58:34 -0700139 mirror::Object* fake_root = nullptr;
140 HandleWrapper<mirror::Object> ret(hs.NewHandleWrapper<mirror::Object>(
141 field_type == Primitive::kPrimNot ? value.GetGCRoot() : &fake_root));
142 instrumentation->FieldWriteEvent(self,
143 this_object.Ptr(),
Orion Hodson811bd5f2016-12-07 11:35:37 +0000144 shadow_frame.GetMethod(),
145 shadow_frame.GetDexPC(),
146 field,
147 value);
Alex Light084fa372017-06-16 08:58:34 -0700148 if (UNLIKELY(self->IsExceptionPending())) {
149 return false;
150 }
Orion Hodson811bd5f2016-12-07 11:35:37 +0000151 }
152
153 switch (field_type) {
154 case Primitive::kPrimBoolean:
155 field->SetBoolean<transaction_active>(obj, value.GetZ());
156 break;
157 case Primitive::kPrimByte:
158 field->SetByte<transaction_active>(obj, value.GetB());
159 break;
160 case Primitive::kPrimChar:
161 field->SetChar<transaction_active>(obj, value.GetC());
162 break;
163 case Primitive::kPrimShort:
164 field->SetShort<transaction_active>(obj, value.GetS());
165 break;
166 case Primitive::kPrimInt:
167 field->SetInt<transaction_active>(obj, value.GetI());
168 break;
169 case Primitive::kPrimLong:
170 field->SetLong<transaction_active>(obj, value.GetJ());
171 break;
172 case Primitive::kPrimNot: {
173 ObjPtr<mirror::Object> reg = value.GetL();
174 if (do_assignability_check && reg != nullptr) {
175 // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the
176 // object in the destructor.
177 ObjPtr<mirror::Class> field_class;
178 {
179 StackHandleScope<2> hs(self);
180 HandleWrapperObjPtr<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
181 HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
182 field_class = field->GetType<true>();
183 }
184 if (!reg->VerifierInstanceOf(field_class.Ptr())) {
185 // This should never happen.
186 std::string temp1, temp2, temp3;
187 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
188 "Put '%s' that is not instance of field '%s' in '%s'",
189 reg->GetClass()->GetDescriptor(&temp1),
190 field_class->GetDescriptor(&temp2),
191 field->GetDeclaringClass()->GetDescriptor(&temp3));
192 return false;
193 }
194 }
195 field->SetObj<transaction_active>(obj, reg);
196 break;
197 }
198 case Primitive::kPrimVoid: {
199 LOG(FATAL) << "Unreachable " << field_type;
200 break;
201 }
202 }
203 return true;
204}
205
206} // namespace art
207
208#endif // ART_RUNTIME_COMMON_DEX_OPERATIONS_H_