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 "android-base/logging.h" 21 #include "art_field.h" 22 #include "art_method.h" 23 #include "base/macros.h" 24 #include "base/mutex.h" 25 #include "class_linker.h" 26 #include "dex/code_item_accessors.h" 27 #include "dex/primitive.h" 28 #include "handle_scope-inl.h" 29 #include "instrumentation.h" 30 #include "interpreter/shadow_frame.h" 31 #include "interpreter/unstarted_runtime.h" 32 #include "mirror/class.h" 33 #include "mirror/object.h" 34 #include "obj_ptr-inl.h" 35 #include "runtime.h" 36 #include "stack.h" 37 #include "thread.h" 38 39 namespace art { 40 41 namespace interpreter { 42 void ArtInterpreterToInterpreterBridge(Thread* self, 43 const DexFile::CodeItem* code_item, 44 ShadowFrame* shadow_frame, 45 JValue* result) 46 REQUIRES_SHARED(Locks::mutator_lock_); 47 48 void ArtInterpreterToCompiledCodeBridge(Thread* self, 49 ArtMethod* caller, 50 ShadowFrame* shadow_frame, 51 uint16_t arg_offset, 52 JValue* result); 53 } // namespace interpreter 54 55 inline void PerformCall(Thread* self, 56 const CodeItemDataAccessor& accessor, 57 ArtMethod* caller_method, 58 const size_t first_dest_reg, 59 ShadowFrame* callee_frame, 60 JValue* result, 61 bool use_interpreter_entrypoint) 62 REQUIRES_SHARED(Locks::mutator_lock_) { 63 if (LIKELY(Runtime::Current()->IsStarted())) { 64 if (use_interpreter_entrypoint) { 65 interpreter::ArtInterpreterToInterpreterBridge(self, accessor, callee_frame, result); 66 } else { 67 interpreter::ArtInterpreterToCompiledCodeBridge( 68 self, caller_method, callee_frame, first_dest_reg, result); 69 } 70 } else { 71 interpreter::UnstartedRuntime::Invoke(self, accessor, callee_frame, result, first_dest_reg); 72 } 73 } 74 75 template <typename T> 76 inline void DCheckStaticState(Thread* self, T* entity) REQUIRES_SHARED(Locks::mutator_lock_) { 77 if (kIsDebugBuild) { 78 ObjPtr<mirror::Class> klass = entity->GetDeclaringClass(); 79 if (entity->IsStatic()) { 80 klass->AssertInitializedOrInitializingInThread(self); 81 } else { 82 CHECK(klass->IsInitializing() || klass->IsErroneousResolved()); 83 } 84 } 85 } 86 87 template<Primitive::Type field_type> 88 static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self, 89 const ShadowFrame& shadow_frame, 90 ObjPtr<mirror::Object> obj, 91 ArtField* field, 92 JValue* result) 93 REQUIRES_SHARED(Locks::mutator_lock_) { 94 DCheckStaticState(self, field); 95 96 // Report this field access to instrumentation if needed. 97 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); 98 if (UNLIKELY(instrumentation->HasFieldReadListeners())) { 99 StackHandleScope<1> hs(self); 100 // Wrap in handle wrapper in case the listener does thread suspension. 101 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj)); 102 ObjPtr<mirror::Object> this_object; 103 if (!field->IsStatic()) { 104 this_object = obj; 105 } 106 instrumentation->FieldReadEvent(self, 107 this_object.Ptr(), 108 shadow_frame.GetMethod(), 109 shadow_frame.GetDexPC(), 110 field); 111 if (UNLIKELY(self->IsExceptionPending())) { 112 return false; 113 } 114 } 115 116 switch (field_type) { 117 case Primitive::kPrimBoolean: 118 result->SetZ(field->GetBoolean(obj)); 119 break; 120 case Primitive::kPrimByte: 121 result->SetB(field->GetByte(obj)); 122 break; 123 case Primitive::kPrimChar: 124 result->SetC(field->GetChar(obj)); 125 break; 126 case Primitive::kPrimShort: 127 result->SetS(field->GetShort(obj)); 128 break; 129 case Primitive::kPrimInt: 130 result->SetI(field->GetInt(obj)); 131 break; 132 case Primitive::kPrimLong: 133 result->SetJ(field->GetLong(obj)); 134 break; 135 case Primitive::kPrimNot: 136 result->SetL(field->GetObject(obj)); 137 break; 138 case Primitive::kPrimVoid: 139 LOG(FATAL) << "Unreachable " << field_type; 140 break; 141 } 142 return true; 143 } 144 145 template<Primitive::Type field_type, bool do_assignability_check, bool transaction_active> 146 ALWAYS_INLINE bool DoFieldPutCommon(Thread* self, 147 const ShadowFrame& shadow_frame, 148 ObjPtr<mirror::Object> obj, 149 ArtField* field, 150 JValue& value) 151 REQUIRES_SHARED(Locks::mutator_lock_) { 152 DCheckStaticState(self, field); 153 154 // Report this field access to instrumentation if needed. Since we only have the offset of 155 // the field from the base of the object, we need to look for it first. 156 instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); 157 if (UNLIKELY(instrumentation->HasFieldWriteListeners())) { 158 StackHandleScope<2> hs(self); 159 // Save this and return value (if needed) in case the instrumentation causes a suspend. 160 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj)); 161 ObjPtr<mirror::Object> this_object = field->IsStatic() ? nullptr : obj; 162 mirror::Object* fake_root = nullptr; 163 HandleWrapper<mirror::Object> ret(hs.NewHandleWrapper<mirror::Object>( 164 field_type == Primitive::kPrimNot ? value.GetGCRoot() : &fake_root)); 165 instrumentation->FieldWriteEvent(self, 166 this_object.Ptr(), 167 shadow_frame.GetMethod(), 168 shadow_frame.GetDexPC(), 169 field, 170 value); 171 if (UNLIKELY(self->IsExceptionPending())) { 172 return false; 173 } 174 } 175 176 switch (field_type) { 177 case Primitive::kPrimBoolean: 178 field->SetBoolean<transaction_active>(obj, value.GetZ()); 179 break; 180 case Primitive::kPrimByte: 181 field->SetByte<transaction_active>(obj, value.GetB()); 182 break; 183 case Primitive::kPrimChar: 184 field->SetChar<transaction_active>(obj, value.GetC()); 185 break; 186 case Primitive::kPrimShort: 187 field->SetShort<transaction_active>(obj, value.GetS()); 188 break; 189 case Primitive::kPrimInt: 190 field->SetInt<transaction_active>(obj, value.GetI()); 191 break; 192 case Primitive::kPrimLong: 193 field->SetLong<transaction_active>(obj, value.GetJ()); 194 break; 195 case Primitive::kPrimNot: { 196 ObjPtr<mirror::Object> reg = value.GetL(); 197 if (do_assignability_check && reg != nullptr) { 198 // FieldHelper::GetType can resolve classes, use a handle wrapper which will restore the 199 // object in the destructor. 200 ObjPtr<mirror::Class> field_class; 201 { 202 StackHandleScope<2> hs(self); 203 HandleWrapperObjPtr<mirror::Object> h_reg(hs.NewHandleWrapper(®)); 204 HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&obj)); 205 field_class = field->ResolveType(); 206 } 207 if (!reg->VerifierInstanceOf(field_class.Ptr())) { 208 // This should never happen. 209 std::string temp1, temp2, temp3; 210 self->ThrowNewExceptionF("Ljava/lang/InternalError;", 211 "Put '%s' that is not instance of field '%s' in '%s'", 212 reg->GetClass()->GetDescriptor(&temp1), 213 field_class->GetDescriptor(&temp2), 214 field->GetDeclaringClass()->GetDescriptor(&temp3)); 215 return false; 216 } 217 } 218 field->SetObj<transaction_active>(obj, reg); 219 break; 220 } 221 case Primitive::kPrimVoid: { 222 LOG(FATAL) << "Unreachable " << field_type; 223 break; 224 } 225 } 226 if (transaction_active) { 227 if (UNLIKELY(self->IsExceptionPending())) { 228 return false; 229 } 230 } 231 return true; 232 } 233 234 } // namespace art 235 236 #endif // ART_RUNTIME_COMMON_DEX_OPERATIONS_H_ 237