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 "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 
28 namespace art {
29 
30 namespace 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,
39                                           const DexFile::CodeItem* code_item,
40                                           ShadowFrame* shadow_frame,
41                                           JValue* result);
42 }  // namespace interpreter
43 
PerformCall(Thread * self,const DexFile::CodeItem * code_item,ArtMethod * caller_method,const size_t first_dest_reg,ShadowFrame * callee_frame,JValue * result)44 inline 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(
59           self, caller_method, code_item, callee_frame, result);
60     }
61   } else {
62     interpreter::UnstartedRuntime::Invoke(self, code_item, callee_frame, result, first_dest_reg);
63   }
64 }
65 
66 template<Primitive::Type field_type>
DoFieldGetCommon(Thread * self,const ShadowFrame & shadow_frame,ObjPtr<mirror::Object> obj,ArtField * field,JValue * result)67 static 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 
120 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,const JValue & value)121 ALWAYS_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_
200