summaryrefslogtreecommitdiffstats
path: root/compiler/dex/verified_method.h
blob: bad449554ac9257337f4eab9db0f6e4cb7925c87 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_COMPILER_DEX_VERIFIED_METHOD_H_
#define ART_COMPILER_DEX_VERIFIED_METHOD_H_

#include <vector>

#include "base/mutex.h"
#include "dex_file.h"
#include "method_reference.h"
#include "safe_map.h"

namespace art {

namespace verifier {
class MethodVerifier;
}  // namespace verifier

class VerifiedMethod {
 public:
  // Cast elision set type.
  // Since we're adding the dex PCs to the set in increasing order, a sorted vector
  // is better for performance (not just memory usage), especially for large sets.
  typedef std::vector<uint32_t> SafeCastSet;

  // Devirtualization map type maps dex offset to concrete method reference.
  typedef SafeMap<uint32_t, MethodReference> DevirtualizationMap;

  // Devirtualization map type maps dex offset to field / method idx.
  typedef SafeMap<uint32_t, DexFileReference> DequickenMap;

  static const VerifiedMethod* Create(verifier::MethodVerifier* method_verifier, bool compile)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
  ~VerifiedMethod() = default;

  const std::vector<uint8_t>& GetDexGcMap() const {
    return dex_gc_map_;
  }

  const DevirtualizationMap& GetDevirtMap() const {
    return devirt_map_;
  }

  const SafeCastSet& GetSafeCastSet() const {
    return safe_cast_set_;
  }

  // Returns the devirtualization target method, or null if none.
  const MethodReference* GetDevirtTarget(uint32_t dex_pc) const;

  // Returns the dequicken field / method for a quick invoke / field get. Returns null if there is
  // no entry for that dex pc.
  const DexFileReference* GetDequickenIndex(uint32_t dex_pc) const;

  // Returns true if the cast can statically be verified to be redundant
  // by using the check-cast elision peephole optimization in the verifier.
  bool IsSafeCast(uint32_t pc) const;

  // Returns true if there were any errors during verification.
  bool HasVerificationFailures() const {
    return has_verification_failures_;
  }

  bool HasRuntimeThrow() const {
    return has_runtime_throw_;
  }

  void SetStringInitPcRegMap(SafeMap<uint32_t, std::set<uint32_t>>& string_init_pc_reg_map) {
    string_init_pc_reg_map_ = string_init_pc_reg_map;
  }
  const SafeMap<uint32_t, std::set<uint32_t>>& GetStringInitPcRegMap() const {
    return string_init_pc_reg_map_;
  }

 private:
  VerifiedMethod() = default;

  /*
   * Generate the GC map for a method that has just been verified (i.e. we're doing this as part of
   * verification). For type-precise determination we have all the data we need, so we just need to
   * encode it in some clever fashion.
   * Stores the data in dex_gc_map_, returns true on success and false on failure.
   */
  bool GenerateGcMap(verifier::MethodVerifier* method_verifier);

  // Verify that the GC map associated with method_ is well formed.
  static void VerifyGcMap(verifier::MethodVerifier* method_verifier,
                          const std::vector<uint8_t>& data);

  // Compute sizes for GC map data.
  static void ComputeGcMapSizes(verifier::MethodVerifier* method_verifier,
                                size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc);

  // Generate devirtualizaion map into devirt_map_.
  void GenerateDevirtMap(verifier::MethodVerifier* method_verifier)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  // Generate dequickening map into dequicken_map_. Returns false if there is an error.
  bool GenerateDequickenMap(verifier::MethodVerifier* method_verifier)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  // Generate safe case set into safe_cast_set_.
  void GenerateSafeCastSet(verifier::MethodVerifier* method_verifier)
      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);

  std::vector<uint8_t> dex_gc_map_;
  DevirtualizationMap devirt_map_;
  // Dequicken map is required for compiling quickened byte codes. The quicken maps from
  // dex PC to dex method index or dex field index based on the instruction.
  DequickenMap dequicken_map_;
  SafeCastSet safe_cast_set_;

  bool has_verification_failures_;
  bool has_runtime_throw_ = false;

  // Copy of mapping generated by verifier of dex PCs of string init invocations
  // to the set of other registers that the receiver has been copied into.
  SafeMap<uint32_t, std::set<uint32_t>> string_init_pc_reg_map_;
};

}  // namespace art

#endif  // ART_COMPILER_DEX_VERIFIED_METHOD_H_