Files
sdk/runtime/vm/compiler/backend/slot.h
T
Liam Appelbe e4196ce8c6 [vm] Namespace constants like offsets and sizeofs to use runtime_api.h
Second sub-CL of https://dart-review.googlesource.com/c/sdk/+/100644
The first was here https://dart-review.googlesource.com/c/sdk/+/103487

Now that offsets_extractor is checked in, and we have a big header full
of hard coded constants, the next step is to make sure everything is
using those constants. This is essentially everything in the original
CL, except the new simarm_x64 architecture.

Bug: https://github.com/dart-lang/sdk/issues/36839
Change-Id: I236e4f30aa1df6d92209891c983b792d1835b608
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/104286
Commit-Queue: Liam Appelbe <liama@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
2019-06-10 02:55:25 +00:00

226 lines
8.8 KiB
C++

// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Slot is an abstraction that describes an readable (and possibly writeable)
// location within an object.
//
// In general slots follow the memory model for normal Dart fields - but can
// also be used to describe locations that don't have corresponding Field
// object, i.e. fields within native objects like arrays or contexts.
//
// Slot objects created by the compiler have an identity. If two slots F and G
// are different then compiler assumes that store into F can't alias a load
// from G and vice versa.
//
// All slots can be split into 4 categories:
//
// - slots for fields of native classes (Array, Closure, etc);
// - slots for type arguments;
// - slots for captured variable;
// - slots for normal Dart fields (e.g. those that Field object).
//
#ifndef RUNTIME_VM_COMPILER_BACKEND_SLOT_H_
#define RUNTIME_VM_COMPILER_BACKEND_SLOT_H_
#include "vm/compiler/backend/compile_type.h"
#include "vm/thread.h"
namespace dart {
class LocalScope;
class LocalVariable;
class ParsedFunction;
// List of slots that correspond to fields of native objects in the following
// format:
//
// V(class_name, field_name, exact_type, FINAL|VAR)
//
// - class_name and field_name specify the name of the host class and the name
// of the field respectively;
// - exact_type specifies exact type of the field (any load from this field
// would only yield instances of this type);
// - the last component specifies whether field behaves like a final field
// (i.e. initialized once at construction time and does not change after
// that) or like a non-final field.
//
// Note: native slots are expected to be non-nullable.
#define NATIVE_SLOTS_LIST(V) \
V(Array, length, Smi, FINAL) \
V(Context, parent, Context, FINAL) \
V(Closure, instantiator_type_arguments, TypeArguments, FINAL) \
V(Closure, delayed_type_arguments, TypeArguments, FINAL) \
V(Closure, function_type_arguments, TypeArguments, FINAL) \
V(Closure, function, Function, FINAL) \
V(Closure, context, Context, FINAL) \
V(Closure, hash, Context, VAR) \
V(GrowableObjectArray, length, Smi, VAR) \
V(GrowableObjectArray, data, Array, VAR) \
V(TypedDataBase, data_field, Dynamic, FINAL) \
V(TypedDataBase, length, Smi, FINAL) \
V(TypedDataView, offset_in_bytes, Smi, FINAL) \
V(TypedDataView, data, Dynamic, FINAL) \
V(String, length, Smi, FINAL) \
V(LinkedHashMap, index, TypedDataUint32Array, VAR) \
V(LinkedHashMap, data, Array, VAR) \
V(LinkedHashMap, hash_mask, Smi, VAR) \
V(LinkedHashMap, used_data, Smi, VAR) \
V(LinkedHashMap, deleted_keys, Smi, VAR) \
V(ArgumentsDescriptor, type_args_len, Smi, FINAL) \
V(ArgumentsDescriptor, positional_count, Smi, FINAL) \
V(ArgumentsDescriptor, count, Smi, FINAL) \
V(Pointer, c_memory_address, Integer, FINAL)
// Slot is an abstraction that describes an readable (and possibly writeable)
// location within an object.
//
// Slot objects returned by Slot::Get* methods have identity and can be
// compared by pointer. If two slots are different they must not alias.
// If two slots can alias - they must be represented by identical
// slot object.
class Slot : public ZoneAllocated {
public:
// clang-format off
enum class Kind : uint8_t {
// Native slots are identified by their kind - each native slot has its own.
#define DECLARE_KIND(ClassName, FieldName, cid, mutability) \
k##ClassName##_##FieldName,
NATIVE_SLOTS_LIST(DECLARE_KIND)
#undef DECLARE_KIND
// A slot used to store type arguments.
kTypeArguments,
// A slot within a Context object that contains a value of a captured
// local variable.
kCapturedVariable,
// A slot that corresponds to a Dart field (has corresponding Field object).
kDartField,
};
// clang-format on
// Returns a slot that represents length field for the given [array_cid].
static const Slot& GetLengthFieldForArrayCid(intptr_t array_cid);
// Return a slot that represents type arguments field at the given offset
// or for the given class.
//
// We do not distinguish type argument fields within disjoint
// class hierarchies: type argument fields at the same offset would be
// represented by the same Slot object. Type argument slots are final
// so disambiguating type arguments fields does not improve alias analysis.
static const Slot& GetTypeArgumentsSlotAt(Thread* thread, intptr_t offset);
static const Slot& GetTypeArgumentsSlotFor(Thread* thread, const Class& cls);
// Returns a slot that represents the given captured local variable.
static const Slot& GetContextVariableSlotFor(Thread* thread,
const LocalVariable& var);
// Returns a slot that represents the given Dart field.
static const Slot& Get(const Field& field,
const ParsedFunction* parsed_function);
// Convenience getters for native slots.
#define DEFINE_GETTER(ClassName, FieldName, cid, mutability) \
static const Slot& ClassName##_##FieldName() { \
return GetNativeSlot(Kind::k##ClassName##_##FieldName); \
}
NATIVE_SLOTS_LIST(DEFINE_GETTER)
#undef DEFINE_GETTER
Kind kind() const { return kind_; }
bool IsDartField() const { return kind() == Kind::kDartField; }
bool IsLocalVariable() const { return kind() == Kind::kCapturedVariable; }
bool IsTypeArguments() const { return kind() == Kind::kTypeArguments; }
const char* Name() const;
intptr_t offset_in_bytes() const { return offset_in_bytes_; }
bool is_immutable() const { return IsImmutableBit::decode(flags_); }
intptr_t nullable_cid() const { return cid_; }
intptr_t is_nullable() const { return IsNullableBit::decode(flags_); }
// Returns true if properties of this slot were based on the guarded state
// of the corresponding Dart field.
bool is_guarded_field() const { return IsGuardedBit::decode(flags_); }
// Static type of the slots if any.
//
// A value that is read from the slot is guaranteed to be assignable to its
// static type.
const AbstractType& static_type() const;
// More precise type information about values that can be read from this slot.
CompileType ComputeCompileType() const;
const Field& field() const {
ASSERT(IsDartField());
ASSERT(data_ != nullptr);
return *DataAs<const Field>();
}
bool Equals(const Slot* other) const;
intptr_t Hashcode() const;
bool IsIdentical(const Slot& other) const { return this == &other; }
private:
Slot(Kind kind,
int8_t bits,
int16_t cid,
intptr_t offset_in_bytes,
const void* data,
const AbstractType* static_type)
: kind_(kind),
flags_(bits),
cid_(cid),
offset_in_bytes_(offset_in_bytes),
data_(data),
static_type_(static_type) {}
Slot(const Slot& other)
: Slot(other.kind_,
other.flags_,
other.cid_,
other.offset_in_bytes_,
other.data_,
other.static_type_) {}
using IsImmutableBit = BitField<int8_t, bool, 0, 1>;
using IsNullableBit = BitField<int8_t, bool, IsImmutableBit::kNextBit, 1>;
using IsGuardedBit = BitField<int8_t, bool, IsNullableBit::kNextBit, 1>;
template <typename T>
const T* DataAs() const {
return static_cast<const T*>(data_);
}
static const Slot& GetNativeSlot(Kind kind);
const Kind kind_;
const int8_t flags_; // is_immutable, is_nullable
const int16_t cid_; // Concrete cid of a value or kDynamicCid.
const intptr_t offset_in_bytes_;
// Kind dependent data:
// - name as a Dart String object for local variables;
// - name as a C string for native slots;
// - Field object for Dart fields;
const void* data_;
const AbstractType* static_type_;
friend class SlotCache;
};
} // namespace dart
#endif // RUNTIME_VM_COMPILER_BACKEND_SLOT_H_