Commit a8ec38d2 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] generate C++ class definitions for fixed-array.h

To enable this, the following changes were necessary:
- Fix generation of accessors with MaybeObject type
  and a bunch of include problems.
- Torque-generated C++ classes now have a constructor that can allow
  Smi values to enable a hack currently used for the DescriptorArray.


Bug: v8:7793 v8:8983
Change-Id: If6e35db99199a0e2afd2698af3d84777d6d0b18f
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2108036
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67247}
parent 4158af83
......@@ -280,8 +280,6 @@ void Symbol::SymbolVerify(Isolate* isolate) {
CHECK_IMPLIES(IsPrivateBrand(), IsPrivateName());
}
USE_TORQUE_VERIFIER(ByteArray)
void BytecodeArray::BytecodeArrayVerify(Isolate* isolate) {
// TODO(oth): Walk bytecodes and immediate values to validate sanity.
// - All bytecodes are known and well formed.
......@@ -520,10 +518,6 @@ void EmbedderDataArray::EmbedderDataArrayVerify(Isolate* isolate) {
}
}
USE_TORQUE_VERIFIER(FixedArrayBase)
USE_TORQUE_VERIFIER(FixedArray)
void WeakFixedArray::WeakFixedArrayVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::WeakFixedArrayVerify(*this, isolate);
for (int i = 0; i < length(); i++) {
......@@ -531,8 +525,6 @@ void WeakFixedArray::WeakFixedArrayVerify(Isolate* isolate) {
}
}
USE_TORQUE_VERIFIER(WeakArrayList)
void PropertyArray::PropertyArrayVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::PropertyArrayVerify(*this, isolate);
if (length() == 0) {
......
......@@ -21,55 +21,38 @@
#include "src/roots/roots-inl.h"
#include "src/sanitizer/tsan.h"
#include "torque-generated/class-definitions-tq-inl.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase, HeapObject)
OBJECT_CONSTRUCTORS_IMPL(FixedArray, FixedArrayBase)
OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray, FixedArrayBase)
TQ_OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase)
FixedArrayBase::FixedArrayBase(Address ptr,
HeapObject::AllowInlineSmiStorage allow_smi)
: TorqueGeneratedFixedArrayBase(ptr, allow_smi) {}
TQ_OBJECT_CONSTRUCTORS_IMPL(FixedArray)
TQ_OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray)
OBJECT_CONSTRUCTORS_IMPL(ArrayList, FixedArray)
OBJECT_CONSTRUCTORS_IMPL(ByteArray, FixedArrayBase)
TQ_OBJECT_CONSTRUCTORS_IMPL(ByteArray)
ByteArray::ByteArray(Address ptr, HeapObject::AllowInlineSmiStorage allow_smi)
: TorqueGeneratedByteArray(ptr, allow_smi) {}
OBJECT_CONSTRUCTORS_IMPL(TemplateList, FixedArray)
OBJECT_CONSTRUCTORS_IMPL(WeakFixedArray, HeapObject)
OBJECT_CONSTRUCTORS_IMPL(WeakArrayList, HeapObject)
FixedArrayBase::FixedArrayBase(Address ptr, AllowInlineSmiStorage allow_smi)
: HeapObject(ptr, allow_smi) {
SLOW_DCHECK(
(allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
IsFixedArrayBase());
}
ByteArray::ByteArray(Address ptr, AllowInlineSmiStorage allow_smi)
: FixedArrayBase(ptr, allow_smi) {
SLOW_DCHECK(
(allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
IsByteArray());
}
TQ_OBJECT_CONSTRUCTORS_IMPL(WeakFixedArray)
TQ_OBJECT_CONSTRUCTORS_IMPL(WeakArrayList)
NEVER_READ_ONLY_SPACE_IMPL(WeakArrayList)
CAST_ACCESSOR(ArrayList)
CAST_ACCESSOR(ByteArray)
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedArrayBase)
CAST_ACCESSOR(FixedDoubleArray)
CAST_ACCESSOR(TemplateList)
CAST_ACCESSOR(WeakFixedArray)
CAST_ACCESSOR(WeakArrayList)
SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
SYNCHRONIZED_SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
SMI_ACCESSORS(WeakArrayList, length, kLengthOffset)
Object FixedArrayBase::unchecked_synchronized_length() const {
return ACQUIRE_READ_FIELD(*this, kLengthOffset);
......@@ -392,28 +375,15 @@ MaybeObject WeakFixedArray::Get(int index) const {
MaybeObject WeakFixedArray::Get(const Isolate* isolate, int index) const {
DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
return TaggedField<MaybeObject>::Relaxed_Load(isolate, *this,
OffsetOfElementAt(index));
}
void WeakFixedArray::Set(int index, MaybeObject value) {
DCHECK_GE(index, 0);
DCHECK_LT(index, length());
int offset = OffsetOfElementAt(index);
RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
WEAK_WRITE_BARRIER(*this, offset, value);
return objects(isolate, index);
}
void WeakFixedArray::Set(int index, MaybeObject value, WriteBarrierMode mode) {
DCHECK_GE(index, 0);
DCHECK_LT(index, length());
int offset = OffsetOfElementAt(index);
RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
set_objects(index, value, mode);
}
MaybeObjectSlot WeakFixedArray::data_start() {
return RawMaybeWeakField(kHeaderSize);
return RawMaybeWeakField(kObjectsOffset);
}
MaybeObjectSlot WeakFixedArray::RawFieldOfElementAt(int index) {
......@@ -440,20 +410,15 @@ MaybeObject WeakArrayList::Get(int index) const {
MaybeObject WeakArrayList::Get(const Isolate* isolate, int index) const {
DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(capacity()));
return TaggedField<MaybeObject>::Relaxed_Load(isolate, *this,
OffsetOfElementAt(index));
return objects(isolate, index);
}
void WeakArrayList::Set(int index, MaybeObject value, WriteBarrierMode mode) {
DCHECK_GE(index, 0);
DCHECK_LT(index, this->capacity());
int offset = OffsetOfElementAt(index);
RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
set_objects(index, value, mode);
}
MaybeObjectSlot WeakArrayList::data_start() {
return RawMaybeWeakField(kHeaderSize);
return RawMaybeWeakField(kObjectsOffset);
}
void WeakArrayList::CopyElements(Isolate* isolate, int dst_index,
......
......@@ -8,7 +8,7 @@
#include "src/handles/maybe-handles.h"
#include "src/objects/instance-type.h"
#include "src/objects/smi.h"
#include "torque-generated/field-offsets-tq.h"
#include "torque-generated/class-definitions-tq.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
......@@ -69,19 +69,14 @@ enum FixedArraySubInstanceType {
// Common superclass for FixedArrays that allow implementations to share
// common accessors and some code paths.
class FixedArrayBase : public HeapObject {
class FixedArrayBase
: public TorqueGeneratedFixedArrayBase<FixedArrayBase, HeapObject> {
public:
// [length]: length of the array.
DECL_INT_ACCESSORS(length)
// Get and set the length using acquire loads and release stores.
DECL_SYNCHRONIZED_INT_ACCESSORS(length)
inline Object unchecked_synchronized_length() const;
DECL_CAST(FixedArrayBase)
DECL_VERIFIER(FixedArrayBase)
static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind);
V8_EXPORT_PRIVATE bool IsCowArray() const;
......@@ -95,20 +90,15 @@ class FixedArrayBase : public HeapObject {
static const int kMaxSize = 128 * kTaggedSize * MB - kTaggedSize;
STATIC_ASSERT(Smi::IsValid(kMaxSize));
// Layout description.
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
TORQUE_GENERATED_FIXED_ARRAY_BASE_FIELDS)
protected:
// Special-purpose constructor for subclasses that have fast paths where
// their ptr() is a Smi.
inline FixedArrayBase(Address ptr, AllowInlineSmiStorage allow_smi);
OBJECT_CONSTRUCTORS(FixedArrayBase, HeapObject);
TQ_OBJECT_CONSTRUCTORS(FixedArrayBase)
inline FixedArrayBase(Address ptr,
HeapObject::AllowInlineSmiStorage allow_smi);
};
// FixedArray describes fixed-sized arrays with element type Object.
class FixedArray : public FixedArrayBase {
class FixedArray
: public TorqueGeneratedFixedArray<FixedArray, FixedArrayBase> {
public:
// Setter and getter for elements.
inline Object get(int index) const;
......@@ -171,12 +161,14 @@ class FixedArray : public FixedArrayBase {
}
// Code Generation support.
static constexpr int OffsetOfElementAt(int index) { return SizeFor(index); }
static constexpr int OffsetOfElementAt(int index) {
STATIC_ASSERT(kObjectsOffset == SizeFor(0));
return SizeFor(index);
}
// Garbage collection support.
inline ObjectSlot RawFieldOfElementAt(int index);
DECL_CAST(FixedArray)
// Maximally allowed length of a FixedArray.
static const int kMaxLength = (kMaxSize - kHeaderSize) / kTaggedSize;
static_assert(Internals::IsValidSmi(kMaxLength),
......@@ -189,7 +181,6 @@ class FixedArray : public FixedArrayBase {
// Dispatched behavior.
DECL_PRINTER(FixedArray)
DECL_VERIFIER(FixedArray)
using BodyDescriptor = FlexibleBodyDescriptor<kHeaderSize>;
......@@ -208,7 +199,7 @@ class FixedArray : public FixedArrayBase {
inline void set_null(ReadOnlyRoots ro_roots, int index);
inline void set_the_hole(ReadOnlyRoots ro_roots, int index);
OBJECT_CONSTRUCTORS(FixedArray, FixedArrayBase);
TQ_OBJECT_CONSTRUCTORS(FixedArray)
};
// FixedArray alias added only because of IsFixedArrayExact() predicate, which
......@@ -217,7 +208,8 @@ class FixedArray : public FixedArrayBase {
class FixedArrayExact final : public FixedArray {};
// FixedDoubleArray describes fixed-sized arrays with element type double.
class FixedDoubleArray : public FixedArrayBase {
class FixedDoubleArray
: public TorqueGeneratedFixedDoubleArray<FixedDoubleArray, FixedArrayBase> {
public:
// Setter and getter for elements.
inline double get_scalar(int index);
......@@ -245,8 +237,6 @@ class FixedDoubleArray : public FixedArrayBase {
// Code Generation support.
static int OffsetOfElementAt(int index) { return SizeFor(index); }
DECL_CAST(FixedDoubleArray)
// Start offset of elements.
static constexpr int kFloatsOffset = kHeaderSize;
......@@ -261,29 +251,20 @@ class FixedDoubleArray : public FixedArrayBase {
class BodyDescriptor;
OBJECT_CONSTRUCTORS(FixedDoubleArray, FixedArrayBase);
TQ_OBJECT_CONSTRUCTORS(FixedDoubleArray)
};
// WeakFixedArray describes fixed-sized arrays with element type
// MaybeObject.
class WeakFixedArray : public HeapObject {
class WeakFixedArray
: public TorqueGeneratedWeakFixedArray<WeakFixedArray, HeapObject> {
public:
DECL_CAST(WeakFixedArray)
inline MaybeObject Get(int index) const;
inline MaybeObject Get(const Isolate* isolate, int index) const;
// Setter that uses write barrier.
inline void Set(int index, MaybeObject value);
// Setter with explicit barrier mode.
inline void Set(int index, MaybeObject value, WriteBarrierMode mode);
static constexpr int SizeFor(int length) {
return kHeaderSize + length * kTaggedSize;
}
DECL_INT_ACCESSORS(length)
inline void Set(
int index, MaybeObject value,
WriteBarrierMode mode = WriteBarrierMode::UPDATE_WRITE_BARRIER);
// Get and set the length using acquire loads and release stores.
DECL_SYNCHRONIZED_INT_ACCESSORS(length)
......@@ -301,9 +282,6 @@ class WeakFixedArray : public HeapObject {
using BodyDescriptor = WeakArrayBodyDescriptor;
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
TORQUE_GENERATED_WEAK_FIXED_ARRAY_FIELDS)
static const int kMaxLength =
(FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
static_assert(Internals::IsValidSmi(kMaxLength),
......@@ -319,7 +297,7 @@ class WeakFixedArray : public HeapObject {
static const int kFirstIndex = 1;
OBJECT_CONSTRUCTORS(WeakFixedArray, HeapObject);
TQ_OBJECT_CONSTRUCTORS(WeakFixedArray)
};
// WeakArrayList is like a WeakFixedArray with static convenience methods for
......@@ -327,11 +305,10 @@ class WeakFixedArray : public HeapObject {
// capacity() returns the allocated size. The number of elements is stored at
// kLengthOffset and is updated with every insertion. The array grows
// dynamically with O(1) amortized insertion.
class WeakArrayList : public HeapObject {
class WeakArrayList
: public TorqueGeneratedWeakArrayList<WeakArrayList, HeapObject> {
public:
NEVER_READ_ONLY_SPACE
DECL_CAST(WeakArrayList)
DECL_VERIFIER(WeakArrayList)
DECL_PRINTER(WeakArrayList)
V8_EXPORT_PRIVATE static Handle<WeakArrayList> AddToEnd(
......@@ -365,7 +342,7 @@ class WeakArrayList : public HeapObject {
WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
static constexpr int SizeForCapacity(int capacity) {
return kHeaderSize + capacity * kTaggedSize;
return SizeFor(capacity);
}
static constexpr int CapacityForLength(int length) {
......@@ -380,15 +357,9 @@ class WeakArrayList : public HeapObject {
V8_EXPORT_PRIVATE bool IsFull();
DECL_INT_ACCESSORS(capacity)
DECL_INT_ACCESSORS(length)
// Get and set the capacity using acquire loads and release stores.
DECL_SYNCHRONIZED_INT_ACCESSORS(capacity)
// Layout description.
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
TORQUE_GENERATED_WEAK_ARRAY_LIST_FIELDS)
using BodyDescriptor = WeakArrayBodyDescriptor;
......@@ -418,7 +389,7 @@ class WeakArrayList : public HeapObject {
return kHeaderSize + index * kTaggedSize;
}
OBJECT_CONSTRUCTORS(WeakArrayList, HeapObject);
TQ_OBJECT_CONSTRUCTORS(WeakArrayList)
};
class WeakArrayList::Iterator {
......@@ -494,7 +465,7 @@ inline int Search(T* array, Name name, int valid_entries = 0,
// ByteArray represents fixed sized byte arrays. Used for the relocation info
// that is attached to code objects.
class ByteArray : public FixedArrayBase {
class ByteArray : public TorqueGeneratedByteArray<ByteArray, FixedArrayBase> {
public:
inline int Size();
......@@ -543,12 +514,9 @@ class ByteArray : public FixedArrayBase {
// Returns a pointer to the ByteArray object for a given data start address.
static inline ByteArray FromDataStartAddress(Address address);
DECL_CAST(ByteArray)
// Dispatched behavior.
inline int ByteArraySize();
DECL_PRINTER(ByteArray)
DECL_VERIFIER(ByteArray)
// Layout description.
static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
......@@ -561,11 +529,8 @@ class ByteArray : public FixedArrayBase {
class BodyDescriptor;
protected:
// Special-purpose constructor for subclasses that have fast paths where
// their ptr() is a Smi.
inline ByteArray(Address ptr, AllowInlineSmiStorage allow_smi);
OBJECT_CONSTRUCTORS(ByteArray, FixedArrayBase);
TQ_OBJECT_CONSTRUCTORS(ByteArray)
inline ByteArray(Address ptr, HeapObject::AllowInlineSmiStorage allow_smi);
};
// Wrapper class for ByteArray which can store arbitrary C++ classes, as long
......
......@@ -3,21 +3,34 @@
// found in the LICENSE file.
@abstract
@generateCppClass
extern class FixedArrayBase extends HeapObject {
// length of the array.
const length: Smi;
}
extern class FixedArray extends FixedArrayBase { objects[length]: Object; }
@generateCppClass
extern class FixedArray extends FixedArrayBase {
objects[length]: Object;
}
type EmptyFixedArray extends FixedArray;
@generateCppClass
extern class FixedDoubleArray extends FixedArrayBase {
floats[length]: float64_or_hole;
}
extern class WeakFixedArray extends HeapObject { length: Smi; }
@generateCppClass
extern class WeakFixedArray extends HeapObject {
const length: Smi;
objects[length]: MaybeObject;
}
extern class ByteArray extends FixedArrayBase {}
@generateCppClass
extern class ByteArray extends FixedArrayBase {
bytes[length]: uint8;
}
@hasSameInstanceTypeAsParent
extern class ArrayList extends FixedArray {
......@@ -28,6 +41,7 @@ extern class ArrayList extends FixedArray {
extern class TemplateList extends FixedArray {
}
@generateCppClass
extern class WeakArrayList extends HeapObject {
const capacity: Smi;
length: Smi;
......
......@@ -9,6 +9,7 @@
#include "src/handles/handles-inl.h"
#include "src/objects/descriptor-array-inl.h"
#include "src/objects/fixed-array-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/smi.h"
......
......@@ -3356,7 +3356,7 @@ class CppClassGenerator {
void GenerateFieldAccessor(const Field& f);
void GenerateFieldAccessorForUntagged(const Field& f);
void GenerateFieldAccessorForSmi(const Field& f);
void GenerateFieldAccessorForObject(const Field& f);
void GenerateFieldAccessorForTagged(const Field& f);
void GenerateClassCasts();
......@@ -3532,14 +3532,73 @@ void CppClassGenerator::GenerateClassConstructors() {
hdr_ << "protected:\n";
hdr_ << " inline explicit " << gen_name_ << "(Address ptr);\n";
hdr_ << " // Special-purpose constructor for subclasses that have fast "
"paths where\n";
hdr_ << " // their ptr() is a Smi.\n";
hdr_ << " inline explicit " << gen_name_
<< "(Address ptr, HeapObject::AllowInlineSmiStorage allow_smi);\n";
inl_ << "template<class D, class P>\n";
inl_ << "inline " << gen_name_T_ << "::" << gen_name_ << "(Address ptr)\n";
inl_ << " : P(ptr) {\n";
inl_ << " SLOW_DCHECK(this->Is" << name_ << "());\n";
inl_ << "}\n";
inl_ << "template<class D, class P>\n";
inl_ << "inline " << gen_name_T_ << "::" << gen_name_
<< "(Address ptr, HeapObject::AllowInlineSmiStorage allow_smi)\n";
inl_ << " : P(ptr, allow_smi) {\n";
inl_ << " SLOW_DCHECK((allow_smi == "
"HeapObject::AllowInlineSmiStorage::kAllowBeingASmi && "
<< "this->IsSmi()) || this->Is" << name_ << "());\n";
inl_ << "}\n";
}
namespace {
std::string GenerateRuntimeTypeCheck(const Type* type,
const std::string& value) {
bool maybe_object = !type->IsSubtypeOf(TypeOracle::GetStrongTaggedType());
std::stringstream type_check;
bool at_start = true;
// If weak pointers are allowed, then start by checking for a cleared value.
if (maybe_object) {
type_check << value << ".IsCleared()";
at_start = false;
}
for (const RuntimeType& runtime_type : type->GetRuntimeTypes()) {
if (!at_start) type_check << " || ";
at_start = false;
if (maybe_object) {
bool strong = runtime_type.weak_ref_to.empty();
if (strong && runtime_type.type == "MaybeObject") {
// Rather than a generic Weak<T>, this is a basic type Tagged or
// WeakHeapObject. We can't validate anything more about the type of
// the object pointed to, so just check that it's weak.
type_check << value << ".IsWeak()";
} else {
type_check << "(" << (strong ? "!" : "") << value << ".IsWeak() && "
<< value << ".GetHeapObjectOrSmi().Is"
<< (strong ? runtime_type.type : runtime_type.weak_ref_to)
<< "())";
}
} else {
type_check << value << ".Is" << runtime_type.type << "()";
}
}
return type_check.str();
}
void GenerateBoundsDCheck(std::ostream& os, const std::string& index,
const ClassType* type, const Field& f) {
os << " DCHECK_GE(" << index << ", 0);\n";
if (base::Optional<NameAndType> array_length =
ExtractSimpleFieldArraySize(*type, *f.index)) {
os << " DCHECK_LT(" << index << ", this->" << array_length->name
<< "());\n";
}
}
} // namespace
// TODO(sigurds): Keep in sync with DECL_ACCESSORS and ACCESSORS macro.
void CppClassGenerator::GenerateFieldAccessor(const Field& f) {
const Type* field_type = f.name_and_type.type;
......@@ -3554,8 +3613,8 @@ void CppClassGenerator::GenerateFieldAccessor(const Field& f) {
if (f.name_and_type.type->IsSubtypeOf(TypeOracle::GetSmiType())) {
return GenerateFieldAccessorForSmi(f);
}
if (f.name_and_type.type->IsSubtypeOf(TypeOracle::GetObjectType())) {
return GenerateFieldAccessorForObject(f);
if (f.name_and_type.type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
return GenerateFieldAccessorForTagged(f);
}
Error("Generation of field accessor for ", type_->name(),
......@@ -3599,6 +3658,7 @@ void CppClassGenerator::GenerateFieldAccessorForUntagged(const Field& f) {
}
inl_ << ") const {\n";
if (f.index) {
GenerateBoundsDCheck(inl_, "i", type_, f);
size_t field_size;
std::string size_string;
std::tie(field_size, size_string) = f.GetFieldSizeInformation();
......@@ -3617,6 +3677,7 @@ void CppClassGenerator::GenerateFieldAccessorForUntagged(const Field& f) {
}
inl_ << type << " value) {\n";
if (f.index) {
GenerateBoundsDCheck(inl_, "i", type_, f);
size_t field_size;
std::string size_string;
std::tie(field_size, size_string) = f.GetFieldSizeInformation();
......@@ -3653,6 +3714,7 @@ void CppClassGenerator::GenerateFieldAccessorForSmi(const Field& f) {
}
inl_ << ") const {\n";
if (f.index) {
GenerateBoundsDCheck(inl_, "i", type_, f);
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " return this->template ReadField<Smi>(offset).value();\n";
inl_ << "}\n";
......@@ -3669,6 +3731,7 @@ void CppClassGenerator::GenerateFieldAccessorForSmi(const Field& f) {
}
inl_ << type << " value) {\n";
if (f.index) {
GenerateBoundsDCheck(inl_, "i", type_, f);
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " WRITE_FIELD(*this, offset, Smi::FromInt(value));\n";
} else {
......@@ -3677,18 +3740,16 @@ void CppClassGenerator::GenerateFieldAccessorForSmi(const Field& f) {
inl_ << "}\n\n";
}
void CppClassGenerator::GenerateFieldAccessorForObject(const Field& f) {
void CppClassGenerator::GenerateFieldAccessorForTagged(const Field& f) {
const Type* field_type = f.name_and_type.type;
DCHECK(field_type->IsSubtypeOf(TypeOracle::GetObjectType()));
DCHECK(field_type->IsSubtypeOf(TypeOracle::GetTaggedType()));
const std::string& name = f.name_and_type.name;
const std::string offset = "k" + CamelifyString(name) + "Offset";
base::Optional<const ClassType*> class_type = field_type->ClassSupertype();
std::string type =
class_type ? (*class_type)->GetGeneratedTNodeTypeName() : "Object";
std::string offset = "k" + CamelifyString(name) + "Offset";
bool strong_pointer = field_type->IsSubtypeOf(TypeOracle::GetObjectType());
std::string type = field_type->GetRuntimeType();
// Generate declarations in header.
if (!class_type && field_type != TypeOracle::GetObjectType()) {
if (!field_type->IsClassType() && field_type != TypeOracle::GetObjectType()) {
hdr_ << " // Torque type: " << field_type->ToString() << "\n";
}
......@@ -3699,11 +3760,7 @@ void CppClassGenerator::GenerateFieldAccessorForObject(const Field& f) {
hdr_ << " inline void set_" << name << "(" << (f.index ? "int i, " : "")
<< type << " value, WriteBarrierMode mode = UPDATE_WRITE_BARRIER);\n\n";
std::string type_check;
for (const RuntimeType& runtime_type : field_type->GetRuntimeTypes()) {
if (!type_check.empty()) type_check += " || ";
type_check += "value.Is" + runtime_type.type + "()";
}
std::string type_check = GenerateRuntimeTypeCheck(field_type, "value");
// Generate implementation in inline header.
inl_ << "template <class D, class P>\n";
......@@ -3719,28 +3776,25 @@ void CppClassGenerator::GenerateFieldAccessorForObject(const Field& f) {
<< "(const Isolate* isolate" << (f.index ? ", int i" : "")
<< ") const {\n";
if (class_type) {
if (f.index) {
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " return " << type
<< "::cast(RELAXED_READ_FIELD(*this, offset));\n";
} else {
inl_ << " return TaggedField<" << type << ", " << offset
<< ">::load(isolate, *this);\n";
}
// TODO(tebbi): The distinction between relaxed and non-relaxed accesses here
// is pretty arbitrary and just tries to preserve what was there before.
// It currently doesn't really make a difference due to concurrent marking
// turning all loads and stores to be relaxed. We should probably drop the
// distinction at some point, even though in principle non-relaxed operations
// would give us TSAN protection.
if (f.index) {
GenerateBoundsDCheck(inl_, "i", type_, f);
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " auto value = TaggedField<" << type
<< ">::Relaxed_Load(isolate, *this, offset);\n";
} else {
// TODO(tebbi): load value as HeapObject when possible
if (f.index) {
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " Object value = Object::cast(RELAXED_READ_FIELD(*this, "
"offset));\n";
} else {
inl_ << " Object value = TaggedField<Object, " << offset
<< ">::load(isolate, *this);\n";
}
inl_ << " auto value = TaggedField<" << type << ", " << offset
<< ">::load(isolate, *this);\n";
}
if (!type_check.empty()) {
inl_ << " DCHECK(" << type_check << ");\n";
inl_ << " return value;\n";
}
inl_ << " return value;\n";
inl_ << "}\n";
inl_ << "template <class D, class P>\n";
......@@ -3749,22 +3803,30 @@ void CppClassGenerator::GenerateFieldAccessorForObject(const Field& f) {
inl_ << "int i, ";
}
inl_ << type << " value, WriteBarrierMode mode) {\n";
inl_ << " SLOW_DCHECK(" << type_check << ");\n";
if (!type_check.empty()) {
inl_ << " SLOW_DCHECK(" << type_check << ");\n";
}
if (f.index) {
GenerateBoundsDCheck(inl_, "i", type_, f);
const char* write_macro =
strong_pointer ? "WRITE_FIELD" : "RELAXED_WRITE_WEAK_FIELD";
inl_ << " int offset = " << offset << " + i * kTaggedSize;\n";
inl_ << " WRITE_FIELD(*this, offset, value);\n";
offset = "offset";
inl_ << " " << write_macro << "(*this, offset, value);\n";
} else {
inl_ << " WRITE_FIELD(*this, " << offset << ", value);\n";
const char* write_macro =
strong_pointer ? "RELAXED_WRITE_FIELD" : "RELAXED_WRITE_WEAK_FIELD";
inl_ << " " << write_macro << "(*this, " << offset << ", value);\n";
}
inl_ << " CONDITIONAL_WRITE_BARRIER(*this, " << offset
<< ", value, mode);\n";
const char* write_barrier = strong_pointer ? "CONDITIONAL_WRITE_BARRIER"
: "CONDITIONAL_WEAK_WRITE_BARRIER";
inl_ << " " << write_barrier << "(*this, " << offset << ", value, mode);\n";
inl_ << "}\n\n";
}
void EmitClassDefinitionHeadersIncludes(const std::string& basename,
std::stringstream& header,
std::stringstream& inline_header) {
header << "#include \"src/objects/fixed-array.h\"\n";
header << "#include \"src/objects/objects.h\"\n";
header << "#include \"src/objects/smi.h\"\n";
header << "#include \"torque-generated/field-offsets-tq.h\"\n";
......@@ -3834,8 +3896,12 @@ void ImplementationVisitor::GenerateClassDefinitions(
IncludeGuardScope internal_inline_header_guard(
inline_internal_header, internal_basename + "-inl.h");
external_header
internal_header << "#include \"torque-generated/class-definitions-tq.h\"\n";
internal_header << "#include \"src/objects/fixed-array.h\"\n";
inline_internal_header
<< "#include \"torque-generated/internal-class-definitions-tq.h\"\n";
inline_internal_header
<< "#include \"torque-generated/class-definitions-tq-inl.h\"\n";
EmitClassDefinitionHeadersIncludes(basename, external_header,
inline_external_header);
......@@ -4255,34 +4321,8 @@ void GenerateFieldValueVerifier(const std::string& class_name,
// the Object type because it would not check anything beyond what we already
// checked with VerifyPointer.
if (field_type != TypeOracle::GetObjectType()) {
std::stringstream type_check;
bool at_start = true;
// If weak pointers are allowed, then start by checking for a cleared value.
if (maybe_object) {
type_check << value << ".IsCleared()";
at_start = false;
}
for (const RuntimeType& runtime_type : field_type->GetRuntimeTypes()) {
if (!at_start) type_check << " || ";
at_start = false;
if (maybe_object) {
bool strong = runtime_type.weak_ref_to.empty();
if (strong && runtime_type.type == "MaybeObject") {
// Rather than a generic Weak<T>, this is a basic type Tagged or
// WeakHeapObject. We can't validate anything more about the type of
// the object pointed to, so just check that it's weak.
type_check << value << ".IsWeak()";
} else {
type_check << "(" << (strong ? "!" : "") << value << ".IsWeak() && "
<< value << ".GetHeapObjectOrSmi().Is"
<< (strong ? runtime_type.type : runtime_type.weak_ref_to)
<< "())";
}
} else {
type_check << value << ".Is" << runtime_type.type << "()";
}
}
cc_contents << " CHECK(" << type_check.str() << ");\n";
cc_contents << " CHECK(" << GenerateRuntimeTypeCheck(field_type, value)
<< ");\n";
}
}
......
......@@ -946,6 +946,13 @@ base::Optional<NameAndType> ExtractSimpleFieldArraySize(
return class_type.LookupField(identifier->name->value).name_and_type;
}
std::string Type::GetRuntimeType() const {
// TODO(tebbi): Other types are currently unsupported, since there the TNode
// types and the C++ runtime types disagree.
DCHECK(this->IsSubtypeOf(TypeOracle::GetTaggedType()));
return GetGeneratedTNodeTypeName();
}
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -135,6 +135,7 @@ class V8_EXPORT_PRIVATE Type : public TypeBase {
base::Optional<const ClassType*> ClassSupertype() const;
base::Optional<const StructType*> StructSupertype() const;
virtual std::vector<RuntimeType> GetRuntimeTypes() const { return {}; }
virtual std::string GetRuntimeType() const;
static const Type* CommonSupertype(const Type* a, const Type* b);
void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); }
size_t id() const { return id_; }
......@@ -375,6 +376,9 @@ class V8_EXPORT_PRIVATE UnionType final : public Type {
return "TNode<" + GetGeneratedTNodeTypeName() + ">";
}
std::string GetGeneratedTNodeTypeNameImpl() const override;
std::string GetRuntimeType() const override {
return parent()->GetRuntimeType();
}
friend size_t hash_value(const UnionType& p) {
size_t result = 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment