reference_type_propagation.h revision 009d166842195711eca4d5768c59a8f7404e6875
1/*
2 * Copyright (C) 2015 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_COMPILER_OPTIMIZING_REFERENCE_TYPE_PROPAGATION_H_
18#define ART_COMPILER_OPTIMIZING_REFERENCE_TYPE_PROPAGATION_H_
19
20#include "base/arena_containers.h"
21#include "mirror/class-inl.h"
22#include "nodes.h"
23#include "obj_ptr.h"
24#include "optimization.h"
25
26namespace art {
27
28/**
29 * Propagates reference types to instructions.
30 */
31class ReferenceTypePropagation : public HOptimization {
32 public:
33  ReferenceTypePropagation(HGraph* graph,
34                           Handle<mirror::ClassLoader> class_loader,
35                           Handle<mirror::DexCache> hint_dex_cache,
36                           VariableSizedHandleScope* handles,
37                           bool is_first_run,
38                           const char* name = kReferenceTypePropagationPassName);
39
40  // Visit a single instruction.
41  void Visit(HInstruction* instruction);
42
43  void Run() OVERRIDE;
44
45  // Returns true if klass is admissible to the propagation: non-null and resolved.
46  // For an array type, we also check if the component type is admissible.
47  static bool IsAdmissible(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
48    return klass != nullptr &&
49           klass->IsResolved() &&
50           (!klass->IsArrayClass() || IsAdmissible(klass->GetComponentType()));
51  }
52
53  static constexpr const char* kReferenceTypePropagationPassName = "reference_type_propagation";
54
55  // Fix the reference type for an instruction whose inputs have changed.
56  // For a select instruction, the reference types of the inputs are merged
57  // and the resulting reference type is set on the select instruction.
58  static void FixUpInstructionType(HInstruction* instruction,
59                                   VariableSizedHandleScope* handle_scope);
60
61 private:
62  class HandleCache {
63   public:
64    explicit HandleCache(VariableSizedHandleScope* handles) : handles_(handles) { }
65
66    template <typename T>
67    MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_) {
68      return handles_->NewHandle(object);
69    }
70
71    template <typename T>
72    MutableHandle<T> NewHandle(ObjPtr<T> object) REQUIRES_SHARED(Locks::mutator_lock_) {
73      return handles_->NewHandle(object);
74    }
75
76    ReferenceTypeInfo::TypeHandle GetObjectClassHandle();
77    ReferenceTypeInfo::TypeHandle GetClassClassHandle();
78    ReferenceTypeInfo::TypeHandle GetStringClassHandle();
79    ReferenceTypeInfo::TypeHandle GetThrowableClassHandle();
80
81   private:
82    VariableSizedHandleScope* handles_;
83
84    ReferenceTypeInfo::TypeHandle object_class_handle_;
85    ReferenceTypeInfo::TypeHandle class_class_handle_;
86    ReferenceTypeInfo::TypeHandle string_class_handle_;
87    ReferenceTypeInfo::TypeHandle throwable_class_handle_;
88  };
89
90  class RTPVisitor;
91
92  static ReferenceTypeInfo MergeTypes(const ReferenceTypeInfo& a,
93                                      const ReferenceTypeInfo& b,
94                                      HandleCache* handle_cache)
95      REQUIRES_SHARED(Locks::mutator_lock_);
96
97  void ValidateTypes();
98
99  Handle<mirror::ClassLoader> class_loader_;
100
101  // Note: hint_dex_cache_ is usually, but not necessarily, the dex cache associated with
102  // graph_->GetDexFile(). Since we may look up also in other dex files, it's used only
103  // as a hint, to reduce the number of calls to the costly ClassLinker::FindDexCache().
104  Handle<mirror::DexCache> hint_dex_cache_;
105  HandleCache handle_cache_;
106
107  // Whether this reference type propagation is the first run we are doing.
108  const bool is_first_run_;
109
110  friend class ReferenceTypePropagationTest;
111
112  DISALLOW_COPY_AND_ASSIGN(ReferenceTypePropagation);
113};
114
115}  // namespace art
116
117#endif  // ART_COMPILER_OPTIMIZING_REFERENCE_TYPE_PROPAGATION_H_
118