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