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