1c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko/*
2c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * Copyright (C) 2014 The Android Open Source Project
3c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko *
4c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * Licensed under the Apache License, Version 2.0 (the "License");
5c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * you may not use this file except in compliance with the License.
6c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * You may obtain a copy of the License at
7c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko *
8c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko *      http://www.apache.org/licenses/LICENSE-2.0
9c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko *
10c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * Unless required by applicable law or agreed to in writing, software
11c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * distributed under the License is distributed on an "AS IS" BASIS,
12c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * See the License for the specific language governing permissions and
14c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko * limitations under the License.
15c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko */
16c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
17c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#ifndef ART_COMPILER_DEX_VERIFIED_METHOD_H_
18c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#define ART_COMPILER_DEX_VERIFIED_METHOD_H_
19c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
20c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include <vector>
21c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
22719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers#include "base/mutex.h"
23c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "method_reference.h"
24c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "safe_map.h"
25c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
26c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markonamespace art {
27c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
28c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markonamespace verifier {
29c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markoclass MethodVerifier;
30c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko}  // namespace verifier
31c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
32c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markoclass VerifiedMethod {
33c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko public:
34c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Cast elision set type.
35c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Since we're adding the dex PCs to the set in increasing order, a sorted vector
36c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // is better for performance (not just memory usage), especially for large sets.
37c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  typedef std::vector<uint32_t> SafeCastSet;
38c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
39c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Devirtualization map type maps dex offset to concrete method reference.
40c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  typedef SafeMap<uint32_t, MethodReference> DevirtualizationMap;
41c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
42c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  static const VerifiedMethod* Create(verifier::MethodVerifier* method_verifier, bool compile)
43c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
44c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  ~VerifiedMethod() = default;
45c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
46c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  const std::vector<uint8_t>& GetDexGcMap() const {
47c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko    return dex_gc_map_;
48c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  }
49c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
50c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  const DevirtualizationMap& GetDevirtMap() const {
51c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko    return devirt_map_;
52c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  }
53c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
54c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  const SafeCastSet& GetSafeCastSet() const {
55c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko    return safe_cast_set_;
56c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  }
57c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
58c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Returns the devirtualization target method, or nullptr if none.
59c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  const MethodReference* GetDevirtTarget(uint32_t dex_pc) const;
60c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
61c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Returns true if the cast can statically be verified to be redundant
62c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // by using the check-cast elision peephole optimization in the verifier.
63c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  bool IsSafeCast(uint32_t pc) const;
64c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
65c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko private:
66c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  VerifiedMethod() = default;
67c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
68c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  /*
69c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko   * Generate the GC map for a method that has just been verified (i.e. we're doing this as part of
70c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko   * verification). For type-precise determination we have all the data we need, so we just need to
71c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko   * encode it in some clever fashion.
72c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko   * Stores the data in dex_gc_map_, returns true on success and false on failure.
73c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko   */
74c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  bool GenerateGcMap(verifier::MethodVerifier* method_verifier);
75c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
76c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Verify that the GC map associated with method_ is well formed.
77c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  static void VerifyGcMap(verifier::MethodVerifier* method_verifier,
78c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko                          const std::vector<uint8_t>& data);
79c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
80c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Compute sizes for GC map data.
81c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  static void ComputeGcMapSizes(verifier::MethodVerifier* method_verifier,
82c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko                                size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc);
83c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
84c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Generate devirtualizaion map into devirt_map_.
85c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  void GenerateDevirtMap(verifier::MethodVerifier* method_verifier)
86c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
87c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
88c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Generate safe case set into safe_cast_set_.
89c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  void GenerateSafeCastSet(verifier::MethodVerifier* method_verifier)
90c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
91c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
92c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  std::vector<uint8_t> dex_gc_map_;
93c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  DevirtualizationMap devirt_map_;
94c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  SafeCastSet safe_cast_set_;
95c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko};
96c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
97c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko}  // namespace art
98c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
99c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#endif  // ART_COMPILER_DEX_VERIFIED_METHOD_H_
100