blob: 6693eefa5a7cd8b08b161e6be614cf4e1535e82b [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,
Nicolas Geoffray01822292017-03-09 09:03:19 +000039 const DexFile::CodeItem* code_item,
Orion Hodson811bd5f2016-12-07 11:35:37 +000040 ShadowFrame* shadow_frame,
41 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,
49 JValue* result)
50 REQUIRES_SHARED(Locks::mutator_lock_) {
51 if (LIKELY(Runtime::Current()->IsStarted())) {
52 ArtMethod* target = callee_frame->GetMethod();
53 if (ClassLinker::ShouldUseInterpreterEntrypoint(
54 target,
55 target->GetEntryPointFromQuickCompiledCode())) {
56 interpreter::ArtInterpreterToInterpreterBridge(self, code_item, callee_frame, result);
57 } else {
58 interpreter::ArtInterpreterToCompiledCodeBridge(
Nicolas Geoffray01822292017-03-09 09:03:19 +000059 self, caller_method, code_item, callee_frame, result);
Orion Hodson811bd5f2016-12-07 11:35:37 +000060 }
61 } else {
62 interpreter::UnstartedRuntime::Invoke(self, code_item, callee_frame, result, first_dest_reg);
63 }
64}
65
66template<Primitive::Type field_type>
67static ALWAYS_INLINE void DoFieldGetCommon(Thread* self,
68 const ShadowFrame& shadow_frame,
69 ObjPtr<mirror::Object> obj,
70 ArtField* field,
71 JValue* result)
72 REQUIRES_SHARED(Locks::mutator_lock_) {
73 field->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
74
75 // Report this field access to instrumentation if needed.
76 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
77 if (UNLIKELY(instrumentation->HasFieldReadListeners())) {
78 StackHandleScope<1> hs(self);
79 // Wrap in handle wrapper in case the listener does thread suspension.
80 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
81 ObjPtr<mirror::Object> this_object;
82 if (!field->IsStatic()) {
83 this_object = obj;
84 }
85 instrumentation->FieldReadEvent(self,
86 this_object.Ptr(),
87 shadow_frame.GetMethod(),
88 shadow_frame.GetDexPC(),
89 field);
90 }
91
92 switch (field_type) {
93 case Primitive::kPrimBoolean:
94 result->SetZ(field->GetBoolean(obj));
95 break;
96 case Primitive::kPrimByte:
97 result->SetB(field->GetByte(obj));
98 break;
99 case Primitive::kPrimChar:
100 result->SetC(field->GetChar(obj));
101 break;
102 case Primitive::kPrimShort:
103 result->SetS(field->GetShort(obj));
104 break;
105 case Primitive::kPrimInt:
106 result->SetI(field->GetInt(obj));
107 break;
108 case Primitive::kPrimLong:
109 result->SetJ(field->GetLong(obj));
110 break;
111 case Primitive::kPrimNot:
112 result->SetL(field->GetObject(obj));
113 break;
114 case Primitive::kPrimVoid:
115 LOG(FATAL) << "Unreachable " << field_type;
116 break;
117 }
118}
119
120template<Primitive::Type field_type, bool do_assignability_check, bool transaction_active>
121ALWAYS_INLINE bool DoFieldPutCommon(Thread* self,
122 const ShadowFrame& shadow_frame,
123 ObjPtr<mirror::Object> obj,
124 ArtField* field,
125 const JValue& value)
126 REQUIRES_SHARED(Locks::mutator_lock_) {
127 field->GetDeclaringClass()->AssertInitializedOrInitializingInThread(self);
128
129 // Report this field access to instrumentation if needed. Since we only have the offset of
130 // the field from the base of the object, we need to look for it first.
131 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
132 if (UNLIKELY(instrumentation->HasFieldWriteListeners())) {
133 StackHandleScope<1> hs(self);
134 // Wrap in handle wrapper in case the listener does thread suspension.
135 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj));
136 ObjPtr<mirror::Object> this_object = field->IsStatic() ? nullptr : obj;
137 instrumentation->FieldWriteEvent(self, this_object.Ptr(),
138 shadow_frame.GetMethod(),
139 shadow_frame.GetDexPC(),
140 field,
141 value);
142 }
143
144 switch (field_type) {
145 case Primitive::kPrimBoolean:
146 field->SetBoolean<transaction_active>(obj, value.GetZ());
147 break;
148 case Primitive::kPrimByte:
149 field->SetByte<transaction_active>(obj, value.GetB());
150 break;
151 case Primitive::kPrimChar:
152 field->SetChar<transaction_active>(obj, value.GetC());
153 break;
154 case Primitive::kPrimShort:
155 field->SetShort<transaction_active>(obj, value.GetS());
156 break;
157 case Primitive::kPrimInt:
158 field->SetInt<transaction_active>(obj, value.GetI());
159 break;
160 case Primitive::kPrimLong:
161 field->SetLong<transaction_active>(obj, value.GetJ());
162 break;
163 case Primitive::kPrimNot: {
164 ObjPtr<mirror::Object> reg = value.GetL();
165 if (do_assignability_check && reg != nullptr) {
166 // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the
167 // object in the destructor.
168 ObjPtr<mirror::Class> field_class;
169 {
170 StackHandleScope<2> hs(self);
171 HandleWrapperObjPtr<mirror::Object> h_reg(hs.NewHandleWrapper(&reg));
172 HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&obj));
173 field_class = field->GetType<true>();
174 }
175 if (!reg->VerifierInstanceOf(field_class.Ptr())) {
176 // This should never happen.
177 std::string temp1, temp2, temp3;
178 self->ThrowNewExceptionF("Ljava/lang/InternalError;",
179 "Put '%s' that is not instance of field '%s' in '%s'",
180 reg->GetClass()->GetDescriptor(&temp1),
181 field_class->GetDescriptor(&temp2),
182 field->GetDeclaringClass()->GetDescriptor(&temp3));
183 return false;
184 }
185 }
186 field->SetObj<transaction_active>(obj, reg);
187 break;
188 }
189 case Primitive::kPrimVoid: {
190 LOG(FATAL) << "Unreachable " << field_type;
191 break;
192 }
193 }
194 return true;
195}
196
197} // namespace art
198
199#endif // ART_RUNTIME_COMMON_DEX_OPERATIONS_H_