Home | History | Annotate | Download | only in runtime
      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_RUNTIME_CHECK_REFERENCE_MAP_VISITOR_H_
     18 #define ART_RUNTIME_CHECK_REFERENCE_MAP_VISITOR_H_
     19 
     20 #include "art_method-inl.h"
     21 #include "oat_quick_method_header.h"
     22 #include "scoped_thread_state_change-inl.h"
     23 #include "stack.h"
     24 #include "stack_map.h"
     25 
     26 namespace art {
     27 
     28 // Helper class for tests checking that the compiler keeps track of dex registers
     29 // holding references.
     30 class CheckReferenceMapVisitor : public StackVisitor {
     31  public:
     32   explicit CheckReferenceMapVisitor(Thread* thread) REQUIRES_SHARED(Locks::mutator_lock_)
     33       : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames) {}
     34 
     35   bool VisitFrame() REQUIRES_SHARED(Locks::mutator_lock_) {
     36     ArtMethod* m = GetMethod();
     37     if (m->IsCalleeSaveMethod() || m->IsNative()) {
     38       CHECK_EQ(GetDexPc(), DexFile::kDexNoIndex);
     39     }
     40 
     41     if (m == nullptr || m->IsNative() || m->IsRuntimeMethod() || IsShadowFrame()) {
     42       return true;
     43     }
     44 
     45     LOG(INFO) << "At " << m->PrettyMethod(false);
     46 
     47     if (m->IsCalleeSaveMethod()) {
     48       LOG(WARNING) << "no PC for " << m->PrettyMethod();
     49       return true;
     50     }
     51 
     52     return false;
     53   }
     54 
     55   void CheckReferences(int* registers, int number_of_references, uint32_t native_pc_offset)
     56       REQUIRES_SHARED(Locks::mutator_lock_) {
     57     CHECK(GetCurrentOatQuickMethodHeader()->IsOptimized());
     58     CheckOptimizedMethod(registers, number_of_references, native_pc_offset);
     59   }
     60 
     61  private:
     62   void CheckOptimizedMethod(int* registers, int number_of_references, uint32_t native_pc_offset)
     63       REQUIRES_SHARED(Locks::mutator_lock_) {
     64     ArtMethod* m = GetMethod();
     65     CodeInfo code_info = GetCurrentOatQuickMethodHeader()->GetOptimizedCodeInfo();
     66     CodeInfoEncoding encoding = code_info.ExtractEncoding();
     67     StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
     68     uint16_t number_of_dex_registers = m->GetCodeItem()->registers_size_;
     69     DexRegisterMap dex_register_map =
     70         code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
     71     uint32_t register_mask = code_info.GetRegisterMaskOf(encoding, stack_map);
     72     BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, stack_map);
     73     for (int i = 0; i < number_of_references; ++i) {
     74       int reg = registers[i];
     75       CHECK(reg < m->GetCodeItem()->registers_size_);
     76       DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(
     77           reg, number_of_dex_registers, code_info, encoding);
     78       switch (location.GetKind()) {
     79         case DexRegisterLocation::Kind::kNone:
     80           // Not set, should not be a reference.
     81           CHECK(false);
     82           break;
     83         case DexRegisterLocation::Kind::kInStack:
     84           DCHECK_EQ(location.GetValue() % kFrameSlotSize, 0);
     85           CHECK(stack_mask.LoadBit(location.GetValue() / kFrameSlotSize));
     86           break;
     87         case DexRegisterLocation::Kind::kInRegister:
     88         case DexRegisterLocation::Kind::kInRegisterHigh:
     89           CHECK_NE(register_mask & (1 << location.GetValue()), 0u);
     90           break;
     91         case DexRegisterLocation::Kind::kInFpuRegister:
     92         case DexRegisterLocation::Kind::kInFpuRegisterHigh:
     93           // In Fpu register, should not be a reference.
     94           CHECK(false);
     95           break;
     96         case DexRegisterLocation::Kind::kConstant:
     97           CHECK_EQ(location.GetValue(), 0);
     98           break;
     99         default:
    100           LOG(FATAL) << "Unexpected location kind " << location.GetInternalKind();
    101       }
    102     }
    103   }
    104 };
    105 
    106 }  // namespace art
    107 
    108 #endif  // ART_RUNTIME_CHECK_REFERENCE_MAP_VISITOR_H_
    109