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 ShadowFrame* shadow_frame, 40 uint16_t arg_offset, 41 JValue* result); 42 } // namespace interpreter 43 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 bool use_interpreter_entrypoint) 51 REQUIRES_SHARED(Locks::mutator_lock_) { 52 if (LIKELY(Runtime::Current()->IsStarted())) { 53 if (use_interpreter_entrypoint) { 54 interpreter::ArtInterpreterToInterpreterBridge(self, code_item, callee_frame, result); 55 } else { 56 interpreter::ArtInterpreterToCompiledCodeBridge( 57 self, caller_method, callee_frame, first_dest_reg, result); 58 } 59 } else { 60 interpreter::UnstartedRuntime::Invoke(self, code_item, callee_frame, result, first_dest_reg); 61 } 62 } 63 64 template<Primitive::Type field_type> 65 static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self, 66 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); 88 if (UNLIKELY(self->IsExceptionPending())) { 89 return false; 90 } 91 } 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 } 119 return true; 120 } 121 122 template<Primitive::Type field_type, bool do_assignability_check, bool transaction_active> 123 ALWAYS_INLINE bool DoFieldPutCommon(Thread* self, 124 const ShadowFrame& shadow_frame, 125 ObjPtr<mirror::Object> obj, 126 ArtField* field, 127 JValue& value) 128 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())) { 135 StackHandleScope<2> hs(self); 136 // Save this and return value (if needed) in case the instrumentation causes a suspend. 137 HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj)); 138 ObjPtr<mirror::Object> this_object = field->IsStatic() ? nullptr : obj; 139 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(), 144 shadow_frame.GetMethod(), 145 shadow_frame.GetDexPC(), 146 field, 147 value); 148 if (UNLIKELY(self->IsExceptionPending())) { 149 return false; 150 } 151 } 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(®)); 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_ 209