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"
23e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier#include "dex_file.h"
24c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "method_reference.h"
25c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#include "safe_map.h"
26c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
27c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markonamespace art {
28c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
29c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markonamespace verifier {
30c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markoclass MethodVerifier;
31c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko}  // namespace verifier
32c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
33c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Markoclass VerifiedMethod {
34c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko public:
35c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Cast elision set type.
36c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Since we're adding the dex PCs to the set in increasing order, a sorted vector
37c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // is better for performance (not just memory usage), especially for large sets.
38c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  typedef std::vector<uint32_t> SafeCastSet;
39c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
40c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Devirtualization map type maps dex offset to concrete method reference.
41c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  typedef SafeMap<uint32_t, MethodReference> DevirtualizationMap;
42c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
43e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  // Devirtualization map type maps dex offset to field / method idx.
44e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  typedef SafeMap<uint32_t, DexFileReference> DequickenMap;
45e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
46c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  static const VerifiedMethod* Create(verifier::MethodVerifier* method_verifier, bool compile)
4790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
48c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  ~VerifiedMethod() = default;
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
582cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  // Returns the devirtualization target method, or null if none.
59c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  const MethodReference* GetDevirtTarget(uint32_t dex_pc) const;
60c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
61e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  // Returns the dequicken field / method for a quick invoke / field get. Returns null if there is
62e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  // no entry for that dex pc.
63e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  const DexFileReference* GetDequickenIndex(uint32_t dex_pc) const;
64e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
65c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Returns true if the cast can statically be verified to be redundant
66c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // by using the check-cast elision peephole optimization in the verifier.
67c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  bool IsSafeCast(uint32_t pc) const;
68c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
69f1c6d9e87cbfd27702103ccc7c7f08ce784dc872Calin Juravle  // Returns true if there were any errors during verification.
70f1c6d9e87cbfd27702103ccc7c7f08ce784dc872Calin Juravle  bool HasVerificationFailures() const {
710760a81257fa427646c309500d603194009265efAndreas Gampe    return encountered_error_types_ != 0;
720760a81257fa427646c309500d603194009265efAndreas Gampe  }
730760a81257fa427646c309500d603194009265efAndreas Gampe
740760a81257fa427646c309500d603194009265efAndreas Gampe  uint32_t GetEncounteredVerificationFailures() const {
750760a81257fa427646c309500d603194009265efAndreas Gampe    return encountered_error_types_;
76f1c6d9e87cbfd27702103ccc7c7f08ce784dc872Calin Juravle  }
77f1c6d9e87cbfd27702103ccc7c7f08ce784dc872Calin Juravle
784824c27988c8eeb302791624bb3ce1d557b0db6cNicolas Geoffray  bool HasRuntimeThrow() const {
794824c27988c8eeb302791624bb3ce1d557b0db6cNicolas Geoffray    return has_runtime_throw_;
804824c27988c8eeb302791624bb3ce1d557b0db6cNicolas Geoffray  }
814824c27988c8eeb302791624bb3ce1d557b0db6cNicolas Geoffray
82c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko private:
8398e6ce44c700abd9375fe17f0aa31fea1e1e938bNicolas Geoffray  VerifiedMethod(uint32_t encountered_error_types, bool has_runtime_throw);
84c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
85c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  /*
86c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko   * Generate the GC map for a method that has just been verified (i.e. we're doing this as part of
87c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko   * verification). For type-precise determination we have all the data we need, so we just need to
88c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko   * encode it in some clever fashion.
89c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko   * Stores the data in dex_gc_map_, returns true on success and false on failure.
90c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko   */
91c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  bool GenerateGcMap(verifier::MethodVerifier* method_verifier);
92c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
93c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Verify that the GC map associated with method_ is well formed.
94c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  static void VerifyGcMap(verifier::MethodVerifier* method_verifier,
95c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko                          const std::vector<uint8_t>& data);
96c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
97c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Compute sizes for GC map data.
98c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  static void ComputeGcMapSizes(verifier::MethodVerifier* method_verifier,
99c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko                                size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc);
100c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
101c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Generate devirtualizaion map into devirt_map_.
102c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  void GenerateDevirtMap(verifier::MethodVerifier* method_verifier)
10390443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
104c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
105091d238936809f6668ca6b7606c62bc224add430Mathieu Chartier  // Generate dequickening map into dequicken_map_. Returns false if there is an error.
106091d238936809f6668ca6b7606c62bc224add430Mathieu Chartier  bool GenerateDequickenMap(verifier::MethodVerifier* method_verifier)
10790443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
10836b58f5ebb85d58f8b5966b8577a6dfe720d1e16Mathieu Chartier
109c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  // Generate safe case set into safe_cast_set_.
110c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  void GenerateSafeCastSet(verifier::MethodVerifier* method_verifier)
11190443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier      SHARED_REQUIRES(Locks::mutator_lock_);
112c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
113c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  DevirtualizationMap devirt_map_;
114e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  // Dequicken map is required for compiling quickened byte codes. The quicken maps from
115e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  // dex PC to dex method index or dex field index based on the instruction.
116e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier  DequickenMap dequicken_map_;
117c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko  SafeCastSet safe_cast_set_;
118f1c6d9e87cbfd27702103ccc7c7f08ce784dc872Calin Juravle
1190760a81257fa427646c309500d603194009265efAndreas Gampe  const uint32_t encountered_error_types_;
1200760a81257fa427646c309500d603194009265efAndreas Gampe  const bool has_runtime_throw_;
121c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko};
122c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
123c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko}  // namespace art
124c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko
125c7f832061fea59fd6abd125f26c8ca1faec695a5Vladimir Marko#endif  // ART_COMPILER_DEX_VERIFIED_METHOD_H_
126