1e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray/* 2e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * Copyright (C) 2011 The Android Open Source Project 3e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * 4e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License"); 5e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * you may not use this file except in compliance with the License. 6e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * You may obtain a copy of the License at 7e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * 8e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * http://www.apache.org/licenses/LICENSE-2.0 9e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * 10e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software 11e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS, 12e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * See the License for the specific language governing permissions and 14e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray * limitations under the License. 15e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray */ 16e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 17e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray#ifndef ART_RUNTIME_CHECK_REFERENCE_MAP_VISITOR_H_ 18e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray#define ART_RUNTIME_CHECK_REFERENCE_MAP_VISITOR_H_ 19e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 20e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h" 21524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray#include "oat_quick_method_header.h" 22e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray#include "scoped_thread_state_change.h" 23e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray#include "stack_map.h" 24e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 25e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffraynamespace art { 26e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 27e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray// Helper class for tests checking that the compiler keeps track of dex registers 28e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray// holding references. 29e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffrayclass CheckReferenceMapVisitor : public StackVisitor { 30e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray public: 3190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier explicit CheckReferenceMapVisitor(Thread* thread) SHARED_REQUIRES(Locks::mutator_lock_) 328e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {} 33e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 3490443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier bool VisitFrame() SHARED_REQUIRES(Locks::mutator_lock_) { 35e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = GetMethod(); 36e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray if (m->IsCalleeSaveMethod() || m->IsNative()) { 37e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray CHECK_EQ(GetDexPc(), DexFile::kDexNoIndex); 38e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray } 39e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 40cf7f19135f0e273f7b0136315633c2abfc715343Ian Rogers if (m == nullptr || m->IsNative() || m->IsRuntimeMethod() || IsShadowFrame()) { 41e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray return true; 42e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray } 43e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 44e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray LOG(INFO) << "At " << PrettyMethod(m, false); 45e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 46e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray if (m->IsCalleeSaveMethod()) { 47e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray LOG(WARNING) << "no PC for " << PrettyMethod(m); 48e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray return true; 49e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray } 50e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 51e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray return false; 52e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray } 53e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 54e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray void CheckReferences(int* registers, int number_of_references, uint32_t native_pc_offset) 5590443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 569d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko CHECK(GetCurrentOatQuickMethodHeader()->IsOptimized()); 579d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko CheckOptimizedMethod(registers, number_of_references, native_pc_offset); 58e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray } 59e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 60e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray private: 61e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray void CheckOptimizedMethod(int* registers, int number_of_references, uint32_t native_pc_offset) 6290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 63e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ArtMethod* m = GetMethod(); 64524e7ea8cd17bad17bd9f3e0ccbb19ad0d4d9c02Nicolas Geoffray CodeInfo code_info = GetCurrentOatQuickMethodHeader()->GetOptimizedCodeInfo(); 6509ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky CodeInfoEncoding encoding = code_info.ExtractEncoding(); 66f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding); 67fead4e4f397455aa31905b2982d4d861126ab89dNicolas Geoffray uint16_t number_of_dex_registers = m->GetCodeItem()->registers_size_; 68a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DexRegisterMap dex_register_map = 69f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers); 7009ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky uint32_t register_mask = stack_map.GetRegisterMask(encoding.stack_map_encoding); 71e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray for (int i = 0; i < number_of_references; ++i) { 72e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray int reg = registers[i]; 73e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray CHECK(reg < m->GetCodeItem()->registers_size_); 74f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil DexRegisterLocation location = dex_register_map.GetDexRegisterLocation( 75f677ebfd832c9c614fea5e6735725fec2f7a3f2aDavid Brazdil reg, number_of_dex_registers, code_info, encoding); 76a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain switch (location.GetKind()) { 77a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kNone: 78e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray // Not set, should not be a reference. 79e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray CHECK(false); 80e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray break; 81a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInStack: 82a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain DCHECK_EQ(location.GetValue() % kFrameSlotSize, 0); 8309ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky CHECK(stack_map.GetStackMaskBit(encoding.stack_map_encoding, 8409ed09866da6d8c7448ef297c148bfa577a247c2David Srbecky location.GetValue() / kFrameSlotSize)); 85e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray break; 86a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInRegister: 87d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInRegisterHigh: 88a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain CHECK_NE(register_mask & (1 << location.GetValue()), 0u); 89e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray break; 90a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kInFpuRegister: 91d9cb68e3212d31d61445fb7e8446f68991720009David Brazdil case DexRegisterLocation::Kind::kInFpuRegisterHigh: 92102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray // In Fpu register, should not be a reference. 93102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray CHECK(false); 94102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray break; 95a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain case DexRegisterLocation::Kind::kConstant: 96a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain CHECK_EQ(location.GetValue(), 0); 97e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray break; 98a2d8ec6876325e89e5d82f5dbeca59f96ced3ec1Roland Levillain default: 997dc11782ff0a5dffcd8108f256f8975f0b3e8076David Srbecky LOG(FATAL) << "Unexpected location kind " << location.GetInternalKind(); 100e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray } 101e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray } 102e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray } 103e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray}; 104e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 105e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray} // namespace art 106e982f0b8e809cece6f460fa2d8df25873aa69de4Nicolas Geoffray 10748a89618eb6ac318733ff574477182ccb242592cNicolas Geoffray#endif // ART_RUNTIME_CHECK_REFERENCE_MAP_VISITOR_H_ 108