Flutter Engine
The Flutter Engine
slot.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// Slot is an abstraction that describes an readable (and possibly writeable)
6// location within an object.
7//
8// In general slots follow the memory model for normal Dart fields - but can
9// also be used to describe locations that don't have corresponding Field
10// object, i.e. fields within native objects like arrays or contexts.
11//
12// Slot objects created by the compiler have an identity. If two slots F and G
13// are different then compiler assumes that store into F can't alias a load
14// from G and vice versa.
15//
16// All slots can be split into 4 categories:
17//
18// - slots for fields of native classes (Array, Closure, etc);
19// - slots for type arguments;
20// - slots for captured variable;
21// - slots for normal Dart fields (e.g. those that Field object).
22//
23
24#ifndef RUNTIME_VM_COMPILER_BACKEND_SLOT_H_
25#define RUNTIME_VM_COMPILER_BACKEND_SLOT_H_
26
27#if defined(DART_PRECOMPILED_RUNTIME)
28#error "AOT runtime should not use compiler sources (including header files)"
29#endif // defined(DART_PRECOMPILED_RUNTIME)
30
33#include "vm/thread.h"
34
35namespace dart {
36
37class LocalScope;
38class LocalVariable;
39class ParsedFunction;
40
41// The list of slots that correspond to nullable boxed fields of native
42// Dart objects in the following format:
43//
44// V(class_name, underlying_type, field_name, exact_type, FINAL|VAR|WEAK)
45//
46// - class_name and field_name specify the name of the host class and the name
47// of the field respectively;
48// - underlying_type: the Raw class which holds the field;
49// - exact_type specifies exact type of the field (any load from this field
50// would only yield instances of this type);
51// - the last component specifies whether field behaves like a final field
52// (i.e. initialized once at construction time and does not change after
53// that), ordinary mutable field or a weak field (can be modified by GC).
54#define NULLABLE_TAGGED_NATIVE_DART_SLOTS_LIST(V) \
55 V(Array, UntaggedArray, type_arguments, TypeArguments, FINAL) \
56 V(Finalizer, UntaggedFinalizer, type_arguments, TypeArguments, FINAL) \
57 V(FinalizerBase, UntaggedFinalizerBase, all_entries, Set, VAR) \
58 V(FinalizerBase, UntaggedFinalizerBase, detachments, Dynamic, VAR) \
59 V(FinalizerBase, UntaggedFinalizer, entries_collected, FinalizerEntry, VAR) \
60 V(FinalizerEntry, UntaggedFinalizerEntry, value, Dynamic, WEAK) \
61 V(FinalizerEntry, UntaggedFinalizerEntry, detach, Dynamic, WEAK) \
62 V(FinalizerEntry, UntaggedFinalizerEntry, token, Dynamic, VAR) \
63 V(FinalizerEntry, UntaggedFinalizerEntry, finalizer, FinalizerBase, WEAK) \
64 V(FinalizerEntry, UntaggedFinalizerEntry, next, FinalizerEntry, VAR) \
65 V(Function, UntaggedFunction, signature, FunctionType, FINAL) \
66 V(Context, UntaggedContext, parent, Context, FINAL) \
67 V(Closure, UntaggedClosure, instantiator_type_arguments, TypeArguments, \
68 FINAL) \
69 V(Closure, UntaggedClosure, delayed_type_arguments, TypeArguments, FINAL) \
70 V(Closure, UntaggedClosure, function_type_arguments, TypeArguments, FINAL) \
71 V(FunctionType, UntaggedFunctionType, type_parameters, TypeParameters, \
72 FINAL) \
73 V(ReceivePort, UntaggedReceivePort, send_port, SendPort, FINAL) \
74 V(ReceivePort, UntaggedReceivePort, handler, Closure, VAR) \
75 V(ImmutableLinkedHashBase, UntaggedLinkedHashBase, index, \
76 TypedDataUint32Array, VAR) \
77 V(Instance, UntaggedInstance, native_fields_array, Dynamic, VAR) \
78 V(SuspendState, UntaggedSuspendState, function_data, Dynamic, VAR) \
79 V(SuspendState, UntaggedSuspendState, then_callback, Closure, VAR) \
80 V(SuspendState, UntaggedSuspendState, error_callback, Closure, VAR) \
81 V(TypeParameters, UntaggedTypeParameters, flags, Array, FINAL) \
82 V(TypeParameters, UntaggedTypeParameters, bounds, TypeArguments, FINAL) \
83 V(TypeParameters, UntaggedTypeParameters, defaults, TypeArguments, FINAL) \
84 V(WeakProperty, UntaggedWeakProperty, key, Dynamic, WEAK) \
85 V(WeakProperty, UntaggedWeakProperty, value, Dynamic, WEAK) \
86 V(WeakReference, UntaggedWeakReference, target, Dynamic, WEAK) \
87 V(WeakReference, UntaggedWeakReference, type_arguments, TypeArguments, FINAL)
88
89// The list of slots that correspond to non-nullable boxed fields of native
90// Dart objects that contain integers in the following format:
91//
92// V(class_name, underlying_type, field_name, exact_type, FINAL|VAR)
93//
94// - class_name and field_name specify the name of the host class and the name
95// of the field respectively;
96// - underlying_type: the Raw class which holds the field;
97// - exact_type specifies exact type of the field (any load from this field
98// would only yield instances of this type);
99// - the last component specifies whether field behaves like a final field
100// (i.e. initialized once at construction time and does not change after
101// that) or like a non-final field.
102#define NONNULLABLE_INT_TAGGED_NATIVE_DART_SLOTS_LIST(V) \
103 V(Array, UntaggedArray, length, Smi, FINAL) \
104 V(Closure, UntaggedClosure, hash, Smi, VAR) \
105 V(GrowableObjectArray, UntaggedGrowableObjectArray, length, Smi, VAR) \
106 V(TypedDataBase, UntaggedTypedDataBase, length, Smi, FINAL) \
107 V(TypedDataView, UntaggedTypedDataView, offset_in_bytes, Smi, FINAL) \
108 V(String, UntaggedString, length, Smi, FINAL) \
109 V(LinkedHashBase, UntaggedLinkedHashBase, hash_mask, Smi, VAR) \
110 V(LinkedHashBase, UntaggedLinkedHashBase, used_data, Smi, VAR) \
111 V(LinkedHashBase, UntaggedLinkedHashBase, deleted_keys, Smi, VAR) \
112 V(ArgumentsDescriptor, UntaggedArray, type_args_len, Smi, FINAL) \
113 V(ArgumentsDescriptor, UntaggedArray, positional_count, Smi, FINAL) \
114 V(ArgumentsDescriptor, UntaggedArray, count, Smi, FINAL) \
115 V(ArgumentsDescriptor, UntaggedArray, size, Smi, FINAL) \
116 V(Record, UntaggedRecord, shape, Smi, FINAL) \
117 V(TypeArguments, UntaggedTypeArguments, hash, Smi, VAR) \
118 V(TypeArguments, UntaggedTypeArguments, length, Smi, FINAL) \
119 V(AbstractType, UntaggedTypeArguments, hash, Smi, VAR)
120
121// The list of slots that correspond to non-nullable boxed fields of native
122// Dart objects that do not contain integers in the following format:
123//
124// V(class_name, underlying_type, field_name, exact_type, FINAL|VAR)
125//
126// - class_name and field_name specify the name of the host class and the name
127// of the field respectively;
128// - underlying_type: the Raw class which holds the field;
129// - exact_type specifies exact type of the field (any load from this field
130// would only yield instances of this type);
131// - the last component specifies whether field behaves like a final field
132// (i.e. initialized once at construction time and does not change after
133// that) or like a non-final field.
134#define NONNULLABLE_NONINT_TAGGED_NATIVE_DART_SLOTS_LIST(V) \
135 V(Closure, UntaggedClosure, function, Function, FINAL) \
136 V(Closure, UntaggedClosure, context, Dynamic, FINAL) \
137 V(Finalizer, UntaggedFinalizer, callback, Closure, FINAL) \
138 V(NativeFinalizer, UntaggedFinalizer, callback, Pointer, FINAL) \
139 V(Function, UntaggedFunction, data, Dynamic, FINAL) \
140 V(FunctionType, UntaggedFunctionType, named_parameter_names, Array, FINAL) \
141 V(FunctionType, UntaggedFunctionType, parameter_types, Array, FINAL) \
142 V(GrowableObjectArray, UntaggedGrowableObjectArray, data, Array, VAR) \
143 V(TypedDataView, UntaggedTypedDataView, typed_data, Dynamic, FINAL) \
144 V(LinkedHashBase, UntaggedLinkedHashBase, index, TypedDataUint32Array, VAR) \
145 V(LinkedHashBase, UntaggedLinkedHashBase, data, Array, VAR) \
146 V(ImmutableLinkedHashBase, UntaggedLinkedHashBase, data, ImmutableArray, \
147 FINAL) \
148 V(TypeParameters, UntaggedTypeParameters, names, Array, FINAL) \
149 V(UnhandledException, UntaggedUnhandledException, exception, Dynamic, FINAL) \
150 V(UnhandledException, UntaggedUnhandledException, stacktrace, Dynamic, FINAL)
151
152// List of slots that correspond to fields of native objects that contain
153// unboxed values in the following format:
154//
155// V(class_name, underlying_type, field_name, representation, FINAL|VAR)
156//
157// - class_name and field_name specify the name of the host class and the name
158// of the field respectively;
159// - underlying_type: the Raw class which holds the field;
160// - representation specifies the representation of the bits stored within
161// the unboxed field (minus the kUnboxed prefix);
162// - the last component specifies whether field behaves like a final field
163// (i.e. initialized once at construction time and does not change after
164// that) or like a non-final field.
165//
166// Note: As the underlying field is unboxed, these slots cannot be nullable.
167//
168// Note: Currently LoadFieldInstr::IsImmutableLengthLoad() assumes that no
169// unboxed slots represent length loads.
170#define UNBOXED_NATIVE_DART_SLOTS_LIST(V) \
171 V(AbstractType, UntaggedAbstractType, flags, Uint32, FINAL) \
172 V(ClosureData, UntaggedClosureData, packed_fields, Uint32, FINAL) \
173 V(FinalizerEntry, UntaggedFinalizerEntry, external_size, IntPtr, VAR) \
174 V(Function, UntaggedFunction, kind_tag, Uint32, FINAL) \
175 V(FunctionType, UntaggedFunctionType, packed_parameter_counts, Uint32, \
176 FINAL) \
177 V(FunctionType, UntaggedFunctionType, packed_type_parameter_counts, Uint16, \
178 FINAL) \
179 V(SubtypeTestCache, UntaggedSubtypeTestCache, num_inputs, Uint32, FINAL)
180
181// Native slots containing untagged addresses that do not exist in JIT mode.
182// See UNTAGGED_NATIVE_DART_SLOTS_LIST for the format.
183#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
184#define AOT_ONLY_UNTAGGED_NATIVE_DART_SLOTS_LIST(V) \
185 V(Closure, UntaggedClosure, entry_point, false, FINAL)
186#else
187#define AOT_ONLY_UNTAGGED_NATIVE_DART_SLOTS_LIST(V)
188#endif
189
190// List of slots that correspond to fields of native Dart objects containing
191// untagged addresses in the following format:
192//
193// V(class_name, underlying_type, field_name, gc_may_move, FINAL|VAR)
194//
195// - class_name and field_name specify the name of the host class and the name
196// of the field respectively;
197// - underlying_type: the Raw class which holds the field;
198// - gc_may_move: whether the untagged address contained in this field is a
199// pointer to memory that may be moved by the GC, which means a value loaded
200// from this field is invalidated by any instruction that can cause GC;
201// - the last component specifies whether field behaves like a final field
202// (i.e. initialized once at construction time and does not change after
203// that) or like a non-final field.
204//
205// Note: As the underlying field is untagged, these slots cannot be nullable.
206//
207// Note: All slots for fields that contain untagged addresses are given
208// the kUntagged representation.
209#define UNTAGGED_NATIVE_DART_SLOTS_LIST(V) \
210 AOT_ONLY_UNTAGGED_NATIVE_DART_SLOTS_LIST(V) \
211 V(Function, UntaggedFunction, entry_point, false, FINAL) \
212 V(FinalizerBase, UntaggedFinalizerBase, isolate, false, VAR) \
213 V(PointerBase, UntaggedPointerBase, data, true, VAR)
214
215// List of slots that correspond to fields of non-Dart objects containing
216// tagged addresses of Dart objects in the following format:
217//
218// V(class_name, _, field_name, exact_type, FINAL|VAR)
219//
220// - class_name and field_name specify the name of the host class and the name
221// of the field respectively;
222// - exact_type specifies exact type of the field (any load from this field
223// would only yield instances of this type);
224// - the last component specifies whether field behaves like a final field
225// (i.e. initialized once at construction time and does not change after
226// that) or like a non-final field.
227//
228// Note: Currently LoadFieldInstr::IsImmutableLengthLoad() assumes that no
229// slots of non-Dart values represent length loads.
230#define NULLABLE_TAGGED_NATIVE_NONDART_SLOTS_LIST(V) \
231 V(Isolate, _, finalizers, GrowableObjectArray, VAR) \
232 V(LocalHandle, _, ptr, Dynamic, VAR) \
233 V(ObjectStore, _, record_field_names, Array, VAR) \
234 V(PersistentHandle, _, ptr, Dynamic, VAR)
235
236// List of slots that correspond to fields of non-Dart objects containing
237// unboxed values in the following format:
238//
239// V(class_name, _, field_name, representation, FINAL|VAR)
240//
241// - class_name and field_name specify the name of the host class and the name
242// of the field respectively;
243// - representation specifies the representation of the bits stored within
244// the unboxed field (minus the kUnboxed prefix);
245// - the last component specifies whether field behaves like a final field
246// (i.e. initialized once at construction time and does not change after
247// that) or like a non-final field.
248//
249// Note: As the underlying field is unboxed, these slots cannot be nullable.
250//
251// Note: Currently LoadFieldInstr::IsImmutableLengthLoad() assumes that no
252// slots of non-Dart values represent length loads.
253#define UNBOXED_NATIVE_NONDART_SLOTS_LIST(V) \
254 V(StreamInfo, _, enabled, IntPtr, VAR)
255
256// List of slots that correspond to fields of non-Dart objects containing
257// untagged addresses in the following format:
258//
259// V(class_name, _, field_name, gc_may_move, FINAL|VAR)
260//
261// - class_name and field_name specify the name of the host class and the name
262// of the field respectively;
263// - gc_may_move: whether the untagged address contained in this field is a
264// pointer to memory that may be moved by the GC, which means a value loaded
265// from this field is invalidated by any instruction that can cause GC;
266// - the last component specifies whether field behaves like a final field
267// (i.e. initialized once at construction time and does not change after
268// that) or like a non-final field.
269//
270// Note: As the underlying field is untagged, these slots cannot be nullable.
271//
272// Note: All slots for fields that contain untagged addresses are given
273// the kUntagged representation.
274//
275// Note: while Thread::isolate_ and IsolateGroup::object_store_ aren't const
276// fields, they should never change during a given execution of the code
277// generated for a function and the compiler only does intra-procedural
278// load optimizations.
279#define UNTAGGED_NATIVE_NONDART_SLOTS_LIST(V) \
280 V(IsolateGroup, _, object_store, false, FINAL) \
281 V(Thread, _, api_top_scope, false, VAR) \
282 V(Thread, _, isolate, false, FINAL) \
283 V(Thread, _, isolate_group, false, FINAL) \
284 V(Thread, _, service_extension_stream, false, FINAL)
285
286// No untagged slot on a non-Dart object should contain a GC-movable address.
287// The gc_may_move field is only there so that any code that operates on
288// UNTAGGED_NATIVE_SLOTS_LIST can use that field as desired.
289#define CHECK_NATIVE_NONDART_SLOT(__, ___, ____, gc_may_move, _____) \
290 static_assert(!gc_may_move);
292#undef CHECK_NATIVE_NONDART_SLOT
293
294// For uses that need any native slot that contain an unboxed integer. Such uses
295// can only use the following arguments for each entry:
296// V(class_name, _, field_name, rep, FINAL|VAR)
297#define UNBOXED_NATIVE_SLOTS_LIST(V) \
298 UNBOXED_NATIVE_DART_SLOTS_LIST(V) \
299 UNBOXED_NATIVE_NONDART_SLOTS_LIST(V)
300
301// For uses that need any native slot that contain an untagged address. Such
302// uses can only use the following arguments for each entry:
303// V(class_name, _, field_name, gc_may_move, FINAL|VAR)
304#define UNTAGGED_NATIVE_SLOTS_LIST(V) \
305 UNTAGGED_NATIVE_DART_SLOTS_LIST(V) \
306 UNTAGGED_NATIVE_NONDART_SLOTS_LIST(V)
307
308// For uses that need any native slot that does not contain a Dart object. Such
309// uses can only use the following arguments for each entry:
310// V(class_name, _, field_name, _, FINAL|VAR)
311#define NOT_TAGGED_NATIVE_SLOTS_LIST(V) \
312 UNBOXED_NATIVE_SLOTS_LIST(V) \
313 UNTAGGED_NATIVE_SLOTS_LIST(V)
314
315// For uses that need any native slot that is guaranteed to contain a tagged
316// integer. Such uses can only use the following arguments for each entry:
317// V(class_name, _, field_name, exact_type, FINAL|VAR)
318#define TAGGED_INT_NATIVE_SLOTS_LIST(V) \
319 NONNULLABLE_INT_TAGGED_NATIVE_DART_SLOTS_LIST(V)
320
321// For uses that need any native slot that contains a tagged object which is not
322// guaranteed to be a integer. This includes nullable integer slots, since
323// those slots may return a non-integer value (null). Such uses can
324// only use the following arguments for each entry:
325// V(class_name, _, field_name, exact_type, FINAL|VAR|WEAK)
326#define TAGGED_NONINT_NATIVE_SLOTS_LIST(V) \
327 NULLABLE_TAGGED_NATIVE_DART_SLOTS_LIST(V) \
328 NONNULLABLE_NONINT_TAGGED_NATIVE_DART_SLOTS_LIST(V) \
329 NULLABLE_TAGGED_NATIVE_NONDART_SLOTS_LIST(V)
330
331// For uses that need any native slot that is not guaranteed to contain an
332// integer, whether a Dart object or unboxed. Such uses can only use the
333// following arguments for each entry:
334// V(class_name, _, field_name, _, FINAL|VAR|WEAK)
335#define NOT_INT_NATIVE_SLOTS_LIST(V) \
336 TAGGED_NONINT_NATIVE_SLOTS_LIST(V) \
337 UNTAGGED_NATIVE_SLOTS_LIST(V)
338
339// For uses that need any native slot on Dart objects that contains a Dart
340// object (e.g., for write barrier purposes). Such uses can use the following
341// arguments for each entry:
342// V(class_name, underlying_class, field_name, exact_type, FINAL|VAR|WEAK)
343#define TAGGED_NATIVE_DART_SLOTS_LIST(V) \
344 NULLABLE_TAGGED_NATIVE_DART_SLOTS_LIST(V) \
345 NONNULLABLE_INT_TAGGED_NATIVE_DART_SLOTS_LIST(V) \
346 NONNULLABLE_NONINT_TAGGED_NATIVE_DART_SLOTS_LIST(V)
347
348// For uses that need any native slot that is not on a Dart object or does
349// not contain a Dart object (e.g., for write barrier purposes). Such uses
350// can only use the following arguments for each entry:
351// V(class_name, _, field_name, _, FINAL|VAR)
352#define NOT_TAGGED_NATIVE_DART_SLOTS_LIST(V) \
353 NULLABLE_TAGGED_NATIVE_NONDART_SLOTS_LIST(V) \
354 NOT_TAGGED_NATIVE_SLOTS_LIST(V)
355
356// For uses that need any native slot that contains a Dart object. Such uses can
357// only use the following arguments for each entry:
358// V(class_name, _, field_name, exact_type, FINAL|VAR|WEAK)
359#define TAGGED_NATIVE_SLOTS_LIST(V) \
360 TAGGED_INT_NATIVE_SLOTS_LIST(V) \
361 TAGGED_NONINT_NATIVE_SLOTS_LIST(V)
362
363// For uses that need all native slots. Such uses can only use the following
364// arguments for each entry:
365// V(class_name, _, field_name, _, FINAL|VAR|WEAK)
366#define NATIVE_SLOTS_LIST(V) \
367 TAGGED_NATIVE_SLOTS_LIST(V) \
368 NOT_TAGGED_NATIVE_SLOTS_LIST(V)
369
370// For tagged slots, the cid should either be Dynamic or the precise cid
371// of the values stored in the corresponding field. That means the cid should
372// not be the cid of an abstract superclass, because then the code will assume
373// the cid of retrieved values is always the given cid.
374//
375// Note: If we ever need native slots with CompileTypes created from an
376// AbstractType instead, then a new base category should be created for those,
377// possibly replacing the cid field with the name of the abstract type.
378#define CHECK_TAGGED_NATIVE_SLOT(__, ___, ____, field_type, _____) \
379 static_assert(k##field_type##Cid != kObjectCid); \
380 static_assert(k##field_type##Cid != kInstanceCid); \
381 static_assert(k##field_type##Cid != kIntegerCid); \
382 static_assert(k##field_type##Cid != kStringCid); \
383 static_assert(k##field_type##Cid != kAbstractTypeCid);
385#undef CHECK_NULLABLE_TAGGED_NATIVE_SLOT
386
387// Currently we only create slots with CompileTypes created from a precise cid,
388// so integer slots listed here must only contain Smis (or Mints, but no slot
389// currently does has only Mints, adjust this check if one is added).
390//
391// Note: If we ever add a category of native slots with AbstractType-based
392// CompileTypes that always contain integers, then add additional checks that
393// the AbstractTypes of those slots are subtypes of Integer.
394#define CHECK_INT_NATIVE_SLOT(__, ___, ____, field_type, _____) \
395 static_assert(k##field_type##Cid == kSmiCid);
397#undef CHECK_INT_NATIVE_SLOT
398
399// Any slot with an integer type should go into the correct category.
400//
401// Note: If we ever add native slots with AbstractType-based CompileTypes, then
402// add appropriate checks that the AbstractType is not a subtype of Integer.
403#define CHECK_NONINT_NATIVE_SLOT(__, ___, ____, field_type, _____) \
404 static_assert(k##field_type##Cid != kSmiCid); \
405 static_assert(k##field_type##Cid != kMintCid);
407#undef CHECK_NONINT_NATIVE_SLOT
408
410 public:
411 FieldGuardState() : state_(0) {}
412 explicit FieldGuardState(const Field& field);
413
414 intptr_t guarded_cid() const { return GuardedCidBits::decode(state_); }
415 bool is_nullable() const { return IsNullableBit::decode(state_); }
416
417 private:
418 using GuardedCidBits = BitField<int32_t, ClassIdTagType, 0, 20>;
420
421 const int32_t state_;
422};
423
424// Slot is an abstraction that describes an readable (and possibly writeable)
425// location within an object.
426//
427// Slot objects returned by Slot::Get* methods have identity and can be
428// compared by pointer. If two slots are different they must not alias.
429// If two slots can alias - they must be represented by identical
430// slot object.
431class Slot : public ZoneAllocated {
432 public:
433 // clang-format off
434 enum class Kind : uint8_t {
435 // Native slots are identified by their kind - each native slot has its own.
436#define DECLARE_KIND(ClassName, __, FieldName, ___, ____) \
437 k##ClassName##_##FieldName,
438 NATIVE_SLOTS_LIST(DECLARE_KIND)
439#undef DECLARE_KIND
440
441 // A slot used to store type arguments.
442 kTypeArguments,
443
444 // A slot at a specific [index] in a [UntaggedTypeArgument] vector.
445 kTypeArgumentsIndex,
446
447 // A slot corresponding to an array element at given offset.
448 // Only used during allocation sinking and in MaterializeObjectInstr.
449 kArrayElement,
450
451 // A slot corresponding to a record field at the given offset.
452 kRecordField,
453
454 // A slot within a Context object that contains a value of a captured
455 // local variable.
456 kCapturedVariable,
457
458 // A slot that corresponds to a Dart field (has corresponding Field object).
459 kDartField,
460 };
461 // clang-format on
462
463 // Returns a slot that represents length field for the given [array_cid].
464 static const Slot& GetLengthFieldForArrayCid(intptr_t array_cid);
465
466 // Return a slot that represents type arguments field for the given class.
467 //
468 // We do not distinguish type argument fields within disjoint
469 // class hierarchies: type argument fields at the same offset would be
470 // represented by the same Slot object. Type argument slots are final
471 // so disambiguating type arguments fields does not improve alias analysis.
472 static const Slot& GetTypeArgumentsSlotFor(Thread* thread, const Class& cls);
473
474 // Returns a slot at a specific [index] in a [UntaggedTypeArgument] vector.
475 static const Slot& GetTypeArgumentsIndexSlot(Thread* thread, intptr_t index);
476
477 // Returns a slot corresponding to an array element at [offset_in_bytes].
478 static const Slot& GetArrayElementSlot(Thread* thread,
479 intptr_t offset_in_bytes);
480
481 // Returns a slot corresponding to a record field at [offset_in_bytes].
482 static const Slot& GetRecordFieldSlot(Thread* thread,
483 intptr_t offset_in_bytes);
484
485 // Returns a slot that represents the given captured local variable.
486 static const Slot& GetContextVariableSlotFor(Thread* thread,
487 const LocalVariable& var);
488
489 // Returns a slot that represents the given Dart field.
490 static const Slot& Get(const Field& field,
491 const ParsedFunction* parsed_function);
492
493 // Convenience getters for native slots.
494#define DEFINE_GETTER(ClassName, __, FieldName, ___, ____) \
495 static const Slot& ClassName##_##FieldName() { \
496 return GetNativeSlot(Kind::k##ClassName##_##FieldName); \
497 }
498
500#undef DEFINE_GETTER
501
502 Kind kind() const { return kind_; }
503 bool IsDartField() const { return kind() == Kind::kDartField; }
504 bool IsLocalVariable() const { return kind() == Kind::kCapturedVariable; }
505 bool IsTypeArguments() const { return kind() == Kind::kTypeArguments; }
506 bool IsArgumentOfType() const { return kind() == Kind::kTypeArgumentsIndex; }
507 bool IsArrayElement() const { return kind() == Kind::kArrayElement; }
508 bool IsRecordField() const { return kind() == Kind::kRecordField; }
509 bool IsImmutableLengthSlot() const;
510
511 const char* Name() const;
512
513 intptr_t offset_in_bytes() const { return offset_in_bytes_; }
514
515 // Currently returns the representation of unboxed native fields and kTagged
516 // for most other types of fields. One special case: fields marked as
517 // containing non-nullable ints in AOT kernel, which have the kUnboxedInt64
518 // representation.
519 Representation representation() const { return representation_; }
520
521 bool is_immutable() const { return IsImmutableBit::decode(flags_); }
522
523 bool is_weak() const { return IsWeakBit::decode(flags_); }
524
525 // Returns true if properties of this slot were based on the guarded state
526 // of the corresponding Dart field.
527 bool is_guarded_field() const { return IsGuardedBit::decode(flags_); }
528
529 bool is_compressed() const { return IsCompressedBit::decode(flags_); }
530
531 // Returns true if the field is an unboxed native field that may contain an
532 // inner pointer to a GC-movable object.
535 }
536
537 // Type information about values that can be read from this slot.
538 CompileType type() const { return type_; }
539
540 const Field& field() const {
542 ASSERT(data_ != nullptr);
543 return *DataAs<const Field>();
544 }
545
546 bool Equals(const Slot& other) const;
547 uword Hash() const;
548
549 bool IsIdentical(const Slot& other) const { return this == &other; }
550
551 bool IsContextSlot() const {
552 return kind() == Kind::kCapturedVariable || kind() == Kind::kContext_parent;
553 }
554
555 bool is_tagged() const { return !IsNonTaggedBit::decode(flags_); }
557 return HasUntaggedInstanceBit::decode(flags_);
558 }
559
560 void Write(FlowGraphSerializer* s) const;
561 static const Slot& Read(FlowGraphDeserializer* d);
562
563 private:
564 Slot(Kind kind,
565 int8_t flags,
566 intptr_t offset_in_bytes,
567 const void* data,
570 const FieldGuardState& field_guard_state = FieldGuardState())
571 : kind_(kind),
572 flags_(flags),
573 offset_in_bytes_(offset_in_bytes),
574 representation_(representation),
575 field_guard_state_(field_guard_state),
576 data_(data),
577 type_(type) {}
578
579 Slot(const Slot& other)
580 : Slot(other.kind_,
581 other.flags_,
582 other.offset_in_bytes_,
583 other.data_,
584 other.type_,
585 other.representation_,
586 other.field_guard_state_) {}
587
588 template <typename T>
589 const T* DataAs() const {
590 return static_cast<const T*>(data_);
591 }
592
593 static const Slot& GetCanonicalSlot(
594 Thread* thread,
595 Kind kind,
596 int8_t flags,
597 intptr_t offset_in_bytes,
598 const void* data,
599 CompileType type,
601 const FieldGuardState& field_guard_state = FieldGuardState());
602
603 static const Slot& GetNativeSlot(Kind kind);
604
605 const FieldGuardState& field_guard_state() const {
606 return field_guard_state_;
607 }
608
609 const Kind kind_;
610 const int8_t flags_;
611 const intptr_t offset_in_bytes_;
612 const Representation representation_;
613
614 const FieldGuardState field_guard_state_;
615
616 // Kind dependent data:
617 // - name as a Dart String object for local variables;
618 // - name as a C string for native slots;
619 // - Field object for Dart fields;
620 const void* data_;
621
622 CompileType type_;
623
624 using IsImmutableBit = BitField<decltype(flags_), bool, 0, 1>;
625 using IsWeakBit =
626 BitField<decltype(flags_), bool, IsImmutableBit::kNextBit, 1>;
627 using IsGuardedBit = BitField<decltype(flags_), bool, IsWeakBit::kNextBit, 1>;
628 using IsCompressedBit =
629 BitField<decltype(flags_), bool, IsGuardedBit::kNextBit, 1>;
630 // Stores whether a field isn't tagged so that tagged is the default value
631 using IsNonTaggedBit =
632 BitField<decltype(flags_), bool, IsCompressedBit::kNextBit, 1>;
633 using MayContainInnerPointerBit =
634 BitField<decltype(flags_), bool, IsNonTaggedBit::kNextBit, 1>;
635 using HasUntaggedInstanceBit =
636 BitField<decltype(flags_), bool, MayContainInnerPointerBit::kNextBit, 1>;
637
638 friend class SlotCache;
639};
640
641} // namespace dart
642
643#endif // RUNTIME_VM_COMPILER_BACKEND_SLOT_H_
static constexpr intptr_t kNextBit
Definition: bitfield.h:143
static constexpr T decode(S value)
Definition: bitfield.h:171
bool is_nullable() const
Definition: slot.h:415
intptr_t guarded_cid() const
Definition: slot.h:414
bool is_guarded_field() const
Definition: slot.h:527
static const Slot & GetContextVariableSlotFor(Thread *thread, const LocalVariable &var)
Definition: slot.cc:292
bool IsArgumentOfType() const
Definition: slot.h:506
bool IsImmutableLengthSlot() const
Definition: slot.cc:208
static const Slot & GetRecordFieldSlot(Thread *thread, intptr_t offset_in_bytes)
Definition: slot.cc:324
bool IsArrayElement() const
Definition: slot.h:507
bool IsLocalVariable() const
Definition: slot.h:504
bool IsRecordField() const
Definition: slot.h:508
static const Slot & GetArrayElementSlot(Thread *thread, intptr_t offset_in_bytes)
Definition: slot.cc:316
Kind kind() const
Definition: slot.h:502
bool is_tagged() const
Definition: slot.h:555
bool IsDartField() const
Definition: slot.h:503
bool IsIdentical(const Slot &other) const
Definition: slot.h:549
bool is_immutable() const
Definition: slot.h:521
static const Slot & Get(const Field &field, const ParsedFunction *parsed_function)
Definition: slot.cc:351
static const Slot & GetLengthFieldForArrayCid(intptr_t array_cid)
Definition: slot.cc:249
bool Equals(const Slot &other) const
Definition: slot.cc:481
const Field & field() const
Definition: slot.h:540
bool IsTypeArguments() const
Definition: slot.h:505
bool IsContextSlot() const
Definition: slot.h:551
Representation representation() const
Definition: slot.h:519
void Write(FlowGraphSerializer *s) const
uword Hash() const
Definition: slot.cc:511
bool is_weak() const
Definition: slot.h:523
intptr_t offset_in_bytes() const
Definition: slot.h:513
bool has_untagged_instance() const
Definition: slot.h:556
static const Slot & Read(FlowGraphDeserializer *d)
bool may_contain_inner_pointer() const
Definition: slot.h:533
const char * Name() const
Definition: slot.cc:471
static const Slot & GetTypeArgumentsIndexSlot(Thread *thread, intptr_t index)
Definition: slot.cc:303
bool is_compressed() const
Definition: slot.h:529
CompileType type() const
Definition: slot.h:538
static const Slot & GetTypeArgumentsSlotFor(Thread *thread, const Class &cls)
Definition: slot.cc:276
#define ASSERT(E)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition: main.cc:19
struct MyStruct s
FlutterSemanticsFlag flags
Definition: dart_vm.cc:33
Representation
Definition: locations.h:66
uintptr_t uword
Definition: globals.h:501
static int8_t data[kExtLength]
#define T
Definition: precompiler.cc:65
#define CHECK_TAGGED_NATIVE_SLOT(__, ___, ____, field_type, _____)
Definition: slot.h:378
#define DEFINE_GETTER(ClassName, __, FieldName, ___, ____)
Definition: slot.h:494
#define NATIVE_SLOTS_LIST(V)
Definition: slot.h:366
#define TAGGED_NONINT_NATIVE_SLOTS_LIST(V)
Definition: slot.h:326
#define CHECK_INT_NATIVE_SLOT(__, ___, ____, field_type, _____)
Definition: slot.h:394
#define CHECK_NATIVE_NONDART_SLOT(__, ___, ____, gc_may_move, _____)
Definition: slot.h:289
#define TAGGED_NATIVE_SLOTS_LIST(V)
Definition: slot.h:359
#define TAGGED_INT_NATIVE_SLOTS_LIST(V)
Definition: slot.h:318
#define CHECK_NONINT_NATIVE_SLOT(__, ___, ____, field_type, _____)
Definition: slot.h:403
#define UNTAGGED_NATIVE_NONDART_SLOTS_LIST(V)
Definition: slot.h:279