blob: 46634717291c66cbac1ed7e65bd3b04ccc79f342 [file] [log] [blame]
Calin Juravle10e244f2015-01-26 18:54:32 +00001/*
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
Vladimir Marko2aaa4b52015-09-17 17:03:26 +010020#include "base/arena_containers.h"
Calin Juravleacf735c2015-02-12 15:25:22 +000021#include "driver/dex_compilation_unit.h"
22#include "handle_scope-inl.h"
Calin Juravle10e244f2015-01-26 18:54:32 +000023#include "nodes.h"
Mathieu Chartier3398c782016-09-30 10:27:43 -070024#include "obj_ptr.h"
Calin Juravle10e244f2015-01-26 18:54:32 +000025#include "optimization.h"
Calin Juravleb1498f62015-02-16 13:13:29 +000026#include "optimizing_compiler_stats.h"
Calin Juravle10e244f2015-01-26 18:54:32 +000027
28namespace art {
29
30/**
31 * Propagates reference types to instructions.
Calin Juravle10e244f2015-01-26 18:54:32 +000032 */
Calin Juravle6c0c4f22015-06-12 15:40:42 +000033class ReferenceTypePropagation : public HOptimization {
Calin Juravle10e244f2015-01-26 18:54:32 +000034 public:
Calin Juravlea5ae3c32015-07-28 14:40:50 +000035 ReferenceTypePropagation(HGraph* graph,
Vladimir Marko456307a2016-04-19 14:12:13 +000036 Handle<mirror::DexCache> hint_dex_cache,
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070037 VariableSizedHandleScope* handles,
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +000038 bool is_first_run,
Calin Juravle2e768302015-07-28 14:41:11 +000039 const char* name = kReferenceTypePropagationPassName);
Calin Juravle10e244f2015-01-26 18:54:32 +000040
Vladimir Markobe10e8e2016-01-22 12:09:44 +000041 // Visit a single instruction.
42 void Visit(HInstruction* instruction);
43
Calin Juravle10e244f2015-01-26 18:54:32 +000044 void Run() OVERRIDE;
45
David Brazdil94ab38f2016-06-21 17:48:19 +010046 // Returns true if klass is admissible to the propagation: non-null and resolved.
47 // For an array type, we also check if the component type is admissible.
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070048 static bool IsAdmissible(mirror::Class* klass) REQUIRES_SHARED(Locks::mutator_lock_) {
David Brazdil94ab38f2016-06-21 17:48:19 +010049 return klass != nullptr &&
50 klass->IsResolved() &&
51 (!klass->IsArrayClass() || IsAdmissible(klass->GetComponentType()));
52 }
53
Andreas Gampe7c3952f2015-02-19 18:21:24 -080054 static constexpr const char* kReferenceTypePropagationPassName = "reference_type_propagation";
55
Calin Juravle10e244f2015-01-26 18:54:32 +000056 private:
Vladimir Marko7d1fbf32016-01-26 15:01:12 +000057 class HandleCache {
58 public:
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070059 explicit HandleCache(VariableSizedHandleScope* handles) : handles_(handles) { }
Vladimir Marko7d1fbf32016-01-26 15:01:12 +000060
61 template <typename T>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070062 MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_) {
Vladimir Marko7d1fbf32016-01-26 15:01:12 +000063 return handles_->NewHandle(object);
64 }
65
Mathieu Chartier3398c782016-09-30 10:27:43 -070066 template <typename T>
67 MutableHandle<T> NewHandle(ObjPtr<T> object) REQUIRES_SHARED(Locks::mutator_lock_) {
68 return handles_->NewHandle(object);
69 }
70
Vladimir Marko7d1fbf32016-01-26 15:01:12 +000071 ReferenceTypeInfo::TypeHandle GetObjectClassHandle();
72 ReferenceTypeInfo::TypeHandle GetClassClassHandle();
73 ReferenceTypeInfo::TypeHandle GetStringClassHandle();
74 ReferenceTypeInfo::TypeHandle GetThrowableClassHandle();
75
76 private:
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070077 VariableSizedHandleScope* handles_;
Vladimir Marko7d1fbf32016-01-26 15:01:12 +000078
79 ReferenceTypeInfo::TypeHandle object_class_handle_;
80 ReferenceTypeInfo::TypeHandle class_class_handle_;
81 ReferenceTypeInfo::TypeHandle string_class_handle_;
82 ReferenceTypeInfo::TypeHandle throwable_class_handle_;
83 };
84
85 class RTPVisitor;
86
Calin Juravleb1498f62015-02-16 13:13:29 +000087 void VisitPhi(HPhi* phi);
Calin Juravle10e244f2015-01-26 18:54:32 +000088 void VisitBasicBlock(HBasicBlock* block);
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070089 void UpdateBoundType(HBoundType* bound_type) REQUIRES_SHARED(Locks::mutator_lock_);
90 void UpdatePhi(HPhi* phi) REQUIRES_SHARED(Locks::mutator_lock_);
Calin Juravle61d544b2015-02-23 16:46:57 +000091 void BoundTypeForIfNotNull(HBasicBlock* block);
Calin Juravleb1498f62015-02-16 13:13:29 +000092 void BoundTypeForIfInstanceOf(HBasicBlock* block);
Calin Juravle10e244f2015-01-26 18:54:32 +000093 void ProcessWorklist();
Calin Juravleb1498f62015-02-16 13:13:29 +000094 void AddToWorklist(HInstruction* instr);
95 void AddDependentInstructionsToWorklist(HInstruction* instr);
96
97 bool UpdateNullability(HInstruction* instr);
98 bool UpdateReferenceTypeInfo(HInstruction* instr);
99
Vladimir Marko7d1fbf32016-01-26 15:01:12 +0000100 static void UpdateArrayGet(HArrayGet* instr, HandleCache* handle_cache)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700101 REQUIRES_SHARED(Locks::mutator_lock_);
Vladimir Marko7d1fbf32016-01-26 15:01:12 +0000102
Calin Juravleb1498f62015-02-16 13:13:29 +0000103 ReferenceTypeInfo MergeTypes(const ReferenceTypeInfo& a, const ReferenceTypeInfo& b)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700104 REQUIRES_SHARED(Locks::mutator_lock_);
Calin Juravleacf735c2015-02-12 15:25:22 +0000105
Calin Juravlecdfed3d2015-10-26 14:05:01 +0000106 void ValidateTypes();
107
Vladimir Marko456307a2016-04-19 14:12:13 +0000108 // Note: hint_dex_cache_ is usually, but not necessarily, the dex cache associated with
109 // graph_->GetDexFile(). Since we may look up also in other dex files, it's used only
110 // as a hint, to reduce the number of calls to the costly ClassLinker::FindDexCache().
111 Handle<mirror::DexCache> hint_dex_cache_;
Vladimir Marko7d1fbf32016-01-26 15:01:12 +0000112 HandleCache handle_cache_;
Calin Juravle10e244f2015-01-26 18:54:32 +0000113
Vladimir Marko2aaa4b52015-09-17 17:03:26 +0100114 ArenaVector<HInstruction*> worklist_;
Calin Juravle10e244f2015-01-26 18:54:32 +0000115
Nicolas Geoffrayd9994f02016-02-11 17:35:55 +0000116 // Whether this reference type propagation is the first run we are doing.
117 const bool is_first_run_;
Calin Juravle2e768302015-07-28 14:41:11 +0000118
Calin Juravle10e244f2015-01-26 18:54:32 +0000119 static constexpr size_t kDefaultWorklistSize = 8;
120
Aart Bik8b3f9b22016-04-06 11:22:12 -0700121 friend class ReferenceTypePropagationTest;
122
Calin Juravle10e244f2015-01-26 18:54:32 +0000123 DISALLOW_COPY_AND_ASSIGN(ReferenceTypePropagation);
124};
125
126} // namespace art
127
128#endif // ART_COMPILER_OPTIMIZING_REFERENCE_TYPE_PROPAGATION_H_