Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
type_testing_stubs.h
Go to the documentation of this file.
1// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_TYPE_TESTING_STUBS_H_
6#define RUNTIME_VM_TYPE_TESTING_STUBS_H_
7
8#include "vm/object.h"
9
10#if !defined(DART_PRECOMPILED_RUNTIME)
14#endif // !defined(DART_PRECOMPILED_RUNTIME)
15
16namespace dart {
17
19 public:
21
22 // Simple helper for stringifying a [type] and prefix it with the type
23 // testing
24 //
25 // (only during dart_bootstrap).
26 const char* StubNameForType(const AbstractType& type) const;
28 const AbstractType& type) const;
29
30 private:
31 void StringifyTypeTo(BaseTextBuffer* buffer, const AbstractType& type) const;
32 // Converts the contents of the buffer to an assembly-safe name.
33 static void MakeNameAssemblerSafe(BaseTextBuffer* buffer);
34
35 Library& lib_;
36 Class& klass_;
37 AbstractType& type_;
38 String& string_;
39 mutable intptr_t nonce_ = 0;
40};
41
43 public:
44 // During bootstrapping it will return `null` for |void| and |dynamic| types,
45 // otherwise it will return a default stub which tail-calls
46 // subtypingtest/runtime code.
47 static CodePtr DefaultCodeForType(const AbstractType& type,
48 bool lazy_specialize = true);
49
50#if !defined(DART_PRECOMPILED_RUNTIME)
51 static CodePtr SpecializeStubFor(Thread* thread, const AbstractType& type);
52#endif
53
55
56 // Creates new stub for [type] (and registers the tuple in object store
57 // array) or returns default stub.
59
60 private:
61#if !defined(TARGET_ARCH_IA32)
62#if !defined(DART_PRECOMPILED_RUNTIME)
63 CodePtr BuildCodeForType(const AbstractType& type);
64 static void BuildOptimizedTypeTestStub(
65 compiler::Assembler* assembler,
67 const Code& slow_type_test_stub,
68 HierarchyInfo* hi,
69 const AbstractType& type);
70
71 static void BuildOptimizedTypeTestStubFastCases(
72 compiler::Assembler* assembler,
73 HierarchyInfo* hi,
74 const AbstractType& type);
75
76 static bool BuildOptimizedSubtypeRangeCheck(compiler::Assembler* assembler,
77 const CidRangeVector& ranges,
78 Register class_id_reg,
79 compiler::Label* check_succeeded,
80 compiler::Label* check_failed);
81
82 static void BuildOptimizedSubclassRangeCheckWithTypeArguments(
83 compiler::Assembler* assembler,
84 HierarchyInfo* hi,
85 const Type& type,
86 const Class& type_class);
87
88 static void BuildOptimizedRecordSubtypeRangeCheck(
89 compiler::Assembler* assembler,
90 HierarchyInfo* hi,
91 const RecordType& type);
92
93 // Returns whether any cid ranges require type argument checking.
94 //
95 // If any do, then returns from the stub if any checks that do not need
96 // type argument checking succeed, falls through or jumps to load_succeeded if
97 // loading the type arguments succeeds, and otherwise jumps to load_failed.
98 // That is, code that uses the type arguments should follow immediately.
99 //
100 // If none do, then falls through or jumps to load_failed if the checks fail,
101 // else returns from the stub if the checks are successful. That is, code
102 // that handles the failure case (like calling the slow stub) should follow.
103 static bool BuildLoadInstanceTypeArguments(
104 compiler::Assembler* assembler,
105 HierarchyInfo* hi,
106 const Type& type,
107 const Class& type_class,
108 const Register class_id_reg,
109 const Register instance_type_args_reg,
110 compiler::Label* load_succeeded,
111 compiler::Label* load_failed);
112
113 static void BuildOptimizedTypeParameterArgumentValueCheck(
114 compiler::Assembler* assembler,
115 HierarchyInfo* hi,
116 const TypeParameter& type_param,
117 intptr_t type_param_value_offset_i,
118 compiler::Label* check_failed);
119
120 static void BuildOptimizedTypeArgumentValueCheck(
121 compiler::Assembler* assembler,
122 HierarchyInfo* hi,
123 const Type& type,
124 intptr_t type_param_value_offset_i,
125 compiler::Label* check_failed);
126
127#endif // !defined(DART_PRECOMPILED_RUNTIME)
128#endif // !defined(TARGET_ARCH_IA32)
129
131 ObjectStore* object_store_;
132};
133
134template <typename T>
136 public:
137 explicit ReusableHandleStack(Zone* zone) : zone_(zone), handles_count_(0) {}
138
139 private:
140 T* Obtain() {
141 T* handle;
142 if (handles_count_ < handles_.length()) {
143 handle = handles_[handles_count_];
144 } else {
145 handle = &T::ZoneHandle(zone_);
146 handles_.Add(handle);
147 }
148 handles_count_++;
149 return handle;
150 }
151
152 void Release(T* handle) {
153 handles_count_--;
154 ASSERT(handles_count_ >= 0);
155 ASSERT(handles_[handles_count_] == handle);
156 }
157
158 Zone* zone_;
159
160 intptr_t handles_count_;
161 MallocGrowableArray<T*> handles_;
162
163 template <typename U>
164 friend class ScopedHandle;
165};
166
167template <typename T>
169 public:
171 : stack_(stack), handle_(stack_->Obtain()) {}
172
173 ~ScopedHandle() { stack_->Release(handle_); }
174
175 T& operator*() { return *handle_; }
176 T* operator->() { return handle_; }
177
178 private:
180 T* handle_;
181};
182
183// Collects data on how [Type] objects are used in generated code.
185 public:
186 explicit TypeUsageInfo(Thread* thread);
188
191 const TypeArguments& ta);
192
193 // Finalize the collected type usage information.
195
196 // Query if [type] is very likely used in a type test (can give
197 // false-positives and false-negatives, but tries to make a very good guess)
199
200 private:
201 template <typename T>
202 class ObjectSetTrait {
203 public:
204 // Typedefs needed for the DirectChainedHashMap template.
205 typedef const T* Key;
206 typedef const T* Value;
207 typedef const T* Pair;
208
209 static Key KeyOf(Pair kv) { return kv; }
210 static Value ValueOf(Pair kv) { return kv; }
211 static inline uword Hash(Key key) { return key->Hash(); }
212 };
213
214 class TypeSetTrait : public ObjectSetTrait<const AbstractType> {
215 public:
216 static inline bool IsKeyEqual(const AbstractType* pair,
217 const AbstractType* key) {
218 return pair->Equals(*key);
219 }
220 };
221
222 class TypeArgumentsSetTrait : public ObjectSetTrait<const TypeArguments> {
223 public:
224 static inline bool IsKeyEqual(const TypeArguments* pair,
225 const TypeArguments* key) {
226 return pair->ptr() == key->ptr();
227 }
228 };
229
230 class TypeParameterSetTrait : public ObjectSetTrait<const TypeParameter> {
231 public:
232 static inline bool IsKeyEqual(const TypeParameter* pair,
233 const TypeParameter* key) {
234 return pair->ptr() == key->ptr();
235 }
236 };
237
241
242 // Collects all type parameters we are doing assert assignable checks against.
243 void CollectTypeParametersUsedInAssertAssignable(TypeParameterSet* set);
244
245 // All types which flow into any of the type parameters in [set] will be added
246 // to the set of types we test against.
247 void UpdateAssertAssignableTypes(ClassTable* class_table,
248 intptr_t cid_count,
249 TypeParameterSet* set);
250
251 void AddToSetIfParameter(TypeParameterSet* set,
252 const AbstractType* type,
253 TypeParameter* param);
254 void AddTypeToSet(TypeSet* set, const AbstractType* type);
255
256 Zone* zone_;
257 TypeSet assert_assignable_types_;
258 TypeArgumentsSet* instance_creation_arguments_;
259
260 Class& klass_;
261};
262
263#if !defined(DART_PRECOMPILED_RUNTIME)
265 TypeUsageInfo* type_usage_info,
266 const Class& klass,
267 Definition* type_arguments);
268#endif
269
270#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
271
273
274#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
275
276} // namespace dart
277
278#endif // RUNTIME_VM_TYPE_TESTING_STUBS_H_
TArray< uint32_t > Key
virtual bool Equals(const Instance &other) const
Definition object.h:9074
void Add(const T &value)
intptr_t length() const
ObjectPtr ptr() const
Definition object.h:332
ScopedHandle(ReusableHandleStack< T > *stack)
static CodePtr DefaultCodeForType(const AbstractType &type, bool lazy_specialize=true)
CodePtr OptimizedCodeForType(const AbstractType &type)
static CodePtr SpecializeStubFor(Thread *thread, const AbstractType &type)
void WriteStubNameForTypeTo(BaseTextBuffer *buffer, const AbstractType &type) const
const char * StubNameForType(const AbstractType &type) const
bool IsUsedInTypeTest(const AbstractType &type)
void UseTypeArgumentsInInstanceCreation(const Class &klass, const TypeArguments &ta)
void UseTypeInAssertAssignable(const AbstractType &type)
#define ASSERT(E)
static const uint8_t buffer[]
Dart_NativeFunction function
Definition fuchsia.cc:51
void DeoptimizeTypeTestingStubs()
uintptr_t uword
Definition globals.h:501
void RegisterTypeArgumentsUse(const Function &function, TypeUsageInfo *type_usage_info, const Class &klass, Definition *type_arguments)
#define T