| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2011 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_SRC_MIRROR_METHOD_INL_H_ | 
 | 18 | #define ART_SRC_MIRROR_METHOD_INL_H_ | 
 | 19 |  | 
 | 20 | #include "abstract_method.h" | 
 | 21 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 22 | #include "dex_file.h" | 
| Ian Rogers | 4f6ad8a | 2013-03-18 15:27:28 -0700 | [diff] [blame] | 23 | #include "object_array.h" | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 24 | #include "runtime.h" | 
| Jeff Hao | 58df327 | 2013-04-22 15:28:53 -0700 | [diff] [blame] | 25 | #include "runtime_support.h" | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 26 |  | 
 | 27 | namespace art { | 
 | 28 | namespace mirror { | 
 | 29 |  | 
 | 30 | inline Class* AbstractMethod::GetDeclaringClass() const { | 
 | 31 |   Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, declaring_class_), false); | 
 | 32 |   DCHECK(result != NULL) << this; | 
 | 33 |   DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this; | 
 | 34 |   return result; | 
 | 35 | } | 
 | 36 |  | 
 | 37 | inline void AbstractMethod::SetDeclaringClass(Class *new_declaring_class) { | 
 | 38 |   SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, declaring_class_), new_declaring_class, false); | 
 | 39 | } | 
 | 40 |  | 
 | 41 | inline uint32_t AbstractMethod::GetAccessFlags() const { | 
 | 42 |   DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous()); | 
 | 43 |   return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, access_flags_), false); | 
 | 44 | } | 
 | 45 |  | 
 | 46 | inline uint16_t AbstractMethod::GetMethodIndex() const { | 
 | 47 |   DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous()); | 
 | 48 |   return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_), false); | 
 | 49 | } | 
 | 50 |  | 
 | 51 | inline uint32_t AbstractMethod::GetDexMethodIndex() const { | 
 | 52 |   DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); | 
 | 53 |   return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_dex_index_), false); | 
 | 54 | } | 
 | 55 |  | 
| Ian Rogers | 4f6ad8a | 2013-03-18 15:27:28 -0700 | [diff] [blame] | 56 | inline ObjectArray<String>* AbstractMethod::GetDexCacheStrings() const { | 
 | 57 |   return GetFieldObject<ObjectArray<String>*>( | 
 | 58 |       OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_), false); | 
 | 59 | } | 
 | 60 |  | 
 | 61 | inline ObjectArray<AbstractMethod>* AbstractMethod::GetDexCacheResolvedMethods() const { | 
 | 62 |   return GetFieldObject<ObjectArray<AbstractMethod>*>( | 
 | 63 |       OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_methods_), false); | 
 | 64 | } | 
 | 65 |  | 
 | 66 | inline ObjectArray<Class>* AbstractMethod::GetDexCacheResolvedTypes() const { | 
 | 67 |   return GetFieldObject<ObjectArray<Class>*>( | 
 | 68 |       OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_types_), false); | 
 | 69 | } | 
 | 70 |  | 
 | 71 | inline ObjectArray<StaticStorageBase>* AbstractMethod::GetDexCacheInitializedStaticStorage() const { | 
 | 72 |   return GetFieldObject<ObjectArray<StaticStorageBase>*>( | 
 | 73 |       OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_initialized_static_storage_), | 
 | 74 |       false); | 
 | 75 | } | 
 | 76 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 77 | inline uint32_t AbstractMethod::GetCodeSize() const { | 
 | 78 |   DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this); | 
| Jeff Hao | aa4a793 | 2013-05-13 11:28:27 -0700 | [diff] [blame] | 79 |   uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromCompiledCode()); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 80 |   if (code == 0) { | 
 | 81 |     return 0; | 
 | 82 |   } | 
 | 83 |   // TODO: make this Thumb2 specific | 
 | 84 |   code &= ~0x1; | 
 | 85 |   return reinterpret_cast<uint32_t*>(code)[-1]; | 
 | 86 | } | 
 | 87 |  | 
 | 88 | inline bool AbstractMethod::CheckIncompatibleClassChange(InvokeType type) { | 
 | 89 |   switch (type) { | 
 | 90 |     case kStatic: | 
 | 91 |       return !IsStatic(); | 
 | 92 |     case kDirect: | 
 | 93 |       return !IsDirect() || IsStatic(); | 
 | 94 |     case kVirtual: { | 
 | 95 |       Class* methods_class = GetDeclaringClass(); | 
 | 96 |       return IsDirect() || (methods_class->IsInterface() && !IsMiranda()); | 
 | 97 |     } | 
 | 98 |     case kSuper: | 
 | 99 |       return false;  // TODO: appropriate checks for call to super class. | 
 | 100 |     case kInterface: { | 
 | 101 |       Class* methods_class = GetDeclaringClass(); | 
 | 102 |       return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass()); | 
 | 103 |     } | 
 | 104 |     default: | 
 | 105 |       LOG(FATAL) << "Unreachable - invocation type: " << type; | 
 | 106 |       return true; | 
 | 107 |   } | 
 | 108 | } | 
 | 109 |  | 
 | 110 | inline void AbstractMethod::AssertPcIsWithinCode(uintptr_t pc) const { | 
 | 111 |   if (!kIsDebugBuild) { | 
 | 112 |     return; | 
 | 113 |   } | 
 | 114 |   if (IsNative() || IsRuntimeMethod() || IsProxyMethod()) { | 
 | 115 |     return; | 
 | 116 |   } | 
| Jeff Hao | aa4a793 | 2013-05-13 11:28:27 -0700 | [diff] [blame] | 117 |   if (GetEntryPointFromCompiledCode() == GetInterpreterEntryPoint()) { | 
| Ian Rogers | 62d6c77 | 2013-02-27 08:32:07 -0800 | [diff] [blame] | 118 |     return; | 
 | 119 |   } | 
| Jeff Hao | 0aba0ba | 2013-06-03 14:49:28 -0700 | [diff] [blame^] | 120 |   ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); | 
 | 121 |   if (GetEntryPointFromCompiledCode() == GetResolutionTrampoline(class_linker)) { | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 122 |       return; | 
 | 123 |   } | 
 | 124 |   DCHECK(IsWithinCode(pc)) | 
 | 125 |       << PrettyMethod(this) | 
 | 126 |       << " pc=" << std::hex << pc | 
| Jeff Hao | aa4a793 | 2013-05-13 11:28:27 -0700 | [diff] [blame] | 127 |       << " code=" << GetEntryPointFromCompiledCode() | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 128 |       << " size=" << GetCodeSize(); | 
 | 129 | } | 
 | 130 |  | 
 | 131 | inline uint32_t AbstractMethod::GetOatCodeOffset() const { | 
 | 132 |   DCHECK(!Runtime::Current()->IsStarted()); | 
| Jeff Hao | aa4a793 | 2013-05-13 11:28:27 -0700 | [diff] [blame] | 133 |   return reinterpret_cast<uint32_t>(GetEntryPointFromCompiledCode()); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 134 | } | 
 | 135 |  | 
 | 136 | inline void AbstractMethod::SetOatCodeOffset(uint32_t code_offset) { | 
 | 137 |   DCHECK(!Runtime::Current()->IsStarted()); | 
| Jeff Hao | aa4a793 | 2013-05-13 11:28:27 -0700 | [diff] [blame] | 138 |   SetEntryPointFromCompiledCode(reinterpret_cast<void*>(code_offset)); | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 139 | } | 
 | 140 |  | 
 | 141 | inline uint32_t AbstractMethod::GetOatMappingTableOffset() const { | 
 | 142 |   DCHECK(!Runtime::Current()->IsStarted()); | 
 | 143 |   return reinterpret_cast<uint32_t>(GetMappingTableRaw()); | 
 | 144 | } | 
 | 145 |  | 
 | 146 | inline void AbstractMethod::SetOatMappingTableOffset(uint32_t mapping_table_offset) { | 
 | 147 |   DCHECK(!Runtime::Current()->IsStarted()); | 
 | 148 |   SetMappingTable(reinterpret_cast<const uint32_t*>(mapping_table_offset)); | 
 | 149 | } | 
 | 150 |  | 
 | 151 | inline uint32_t AbstractMethod::GetOatVmapTableOffset() const { | 
 | 152 |   DCHECK(!Runtime::Current()->IsStarted()); | 
 | 153 |   return reinterpret_cast<uint32_t>(GetVmapTableRaw()); | 
 | 154 | } | 
 | 155 |  | 
 | 156 | inline void AbstractMethod::SetOatVmapTableOffset(uint32_t vmap_table_offset) { | 
 | 157 |   DCHECK(!Runtime::Current()->IsStarted()); | 
 | 158 |   SetVmapTable(reinterpret_cast<uint16_t*>(vmap_table_offset)); | 
 | 159 | } | 
 | 160 |  | 
 | 161 | inline void AbstractMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) { | 
 | 162 |   DCHECK(!Runtime::Current()->IsStarted()); | 
 | 163 |   SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset)); | 
 | 164 | } | 
 | 165 |  | 
 | 166 | inline uint32_t AbstractMethod::GetOatNativeGcMapOffset() const { | 
 | 167 |   DCHECK(!Runtime::Current()->IsStarted()); | 
 | 168 |   return reinterpret_cast<uint32_t>(GetNativeGcMap()); | 
 | 169 | } | 
 | 170 |  | 
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 171 | inline bool AbstractMethod::IsRuntimeMethod() const { | 
 | 172 |   return GetDexMethodIndex() == DexFile::kDexNoIndex16; | 
 | 173 | } | 
 | 174 |  | 
 | 175 | inline bool AbstractMethod::IsCalleeSaveMethod() const { | 
 | 176 |   if (!IsRuntimeMethod()) { | 
 | 177 |     return false; | 
 | 178 |   } | 
 | 179 |   Runtime* runtime = Runtime::Current(); | 
 | 180 |   bool result = false; | 
 | 181 |   for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { | 
 | 182 |     if (this == runtime->GetCalleeSaveMethod(Runtime::CalleeSaveType(i))) { | 
 | 183 |       result = true; | 
 | 184 |       break; | 
 | 185 |     } | 
 | 186 |   } | 
 | 187 |   return result; | 
 | 188 | } | 
 | 189 |  | 
 | 190 | inline bool AbstractMethod::IsResolutionMethod() const { | 
 | 191 |   bool result = this == Runtime::Current()->GetResolutionMethod(); | 
 | 192 |   // Check that if we do think it is phony it looks like the resolution method. | 
 | 193 |   DCHECK(!result || IsRuntimeMethod()); | 
 | 194 |   return result; | 
 | 195 | } | 
 | 196 | }  // namespace mirror | 
 | 197 | }  // namespace art | 
 | 198 |  | 
 | 199 | #endif  // ART_SRC_MIRROR_METHOD_INL_H_ |