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

[torque] add %SizeOf intrinsic

This replaces the fragile hand-coded SizeOf function.

Bug: v8:7793
Change-Id: I6bd84f367182b947486192f8968c56723f29efaa
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1924265Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65089}
parent ea06b01e
......@@ -3,24 +3,15 @@
// found in the LICENSE file.
namespace torque_internal {
// TODO(gsps): Synthesize SizeOf<T> in the compiler
macro SizeOf<T: type>(): constexpr int31;
SizeOf<Object>(): constexpr int31 {
return kTaggedSize;
}
SizeOf<float64>(): constexpr int31 {
return kDoubleSize;
}
SizeOf<DescriptorEntry>(): constexpr int31 {
return kTaggedSize * 3;
}
// Unsafe is a marker that we require to be passed when calling internal APIs
// that might lead to unsoundness when used incorrectly. Unsafe markers should
// therefore not be instantiated anywhere outside of this namespace.
struct Unsafe {}
// Size of a type in memory (on the heap). For class types, this is the size
// of the pointer, not of the instance.
intrinsic %SizeOf<T: type>(): constexpr int31;
struct Reference<T: type> {
const object: HeapObject;
const offset: intptr;
......@@ -39,7 +30,7 @@ namespace torque_internal {
TryAtIndex(index: intptr):&T labels OutOfBounds {
if (Convert<uintptr>(index) < Convert<uintptr>(this.length)) {
return UnsafeNewReference<T>(
this.object, this.offset + index * SizeOf<T>());
this.object, this.offset + index * %SizeOf<T>());
} else {
goto OutOfBounds;
}
......@@ -64,7 +55,7 @@ namespace torque_internal {
}
Iterator(): SliceIterator<T> {
const end = this.offset + this.length * SizeOf<T>();
const end = this.offset + this.length * %SizeOf<T>();
return SliceIterator<T>{
object: this.object,
start: this.offset,
......@@ -99,7 +90,7 @@ namespace torque_internal {
goto NoMore;
} else {
const result = UnsafeNewReference<T>(this.object, this.start);
this.start += SizeOf<T>();
this.start += %SizeOf<T>();
return result;
}
}
......
......@@ -9,7 +9,6 @@ extern class EnumCache extends Struct {
indices: FixedArray;
}
// Keep in sync with hand-coded SizeOf<DescriptorEntry> in torque-internal.tq.
@export
struct DescriptorEntry {
key: Name|Undefined;
......
......@@ -242,7 +242,7 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
"%GetAllocationBaseSize") {
if (instruction.specialization_types.size() != 1) {
ReportError(
"incorrect number of specialization classes for "
"incorrect number of type parameters for "
"%GetAllocationBaseSize (should be one)");
}
const ClassType* class_type =
......
......@@ -2360,7 +2360,19 @@ VisitResult ImplementationVisitor::GenerateCall(
return VisitResult(return_type, assembler().TopRange(slot_count));
}
} else if (auto* intrinsic = Intrinsic::DynamicCast(callable)) {
if (intrinsic->ExternalName() == "%RawConstexprCast") {
if (intrinsic->ExternalName() == "%SizeOf") {
if (specialization_types.size() != 1) {
ReportError("%SizeOf must take a single type parameter");
}
const Type* type = specialization_types[0];
std::string size_string;
if (base::Optional<std::tuple<size_t, std::string>> size = SizeOf(type)) {
size_string = std::get<1>(*size);
} else {
Error("size of ", *type, " is not known.");
}
return VisitResult(return_type, size_string);
} else if (intrinsic->ExternalName() == "%RawConstexprCast") {
if (intrinsic->signature().parameter_types.types.size() != 1 ||
constexpr_arguments.size() != 1) {
ReportError(
......
......@@ -155,7 +155,7 @@ const StructType* TypeVisitor::ComputeType(
false,
field.const_qualified,
false};
auto optional_size = f.GetOptionalFieldSizeInformation();
auto optional_size = SizeOf(f.name_and_type.type);
// Structs may contain fields that aren't representable in packed form. If
// so, then this field and any subsequent fields should have their offsets
// marked as invalid.
......
......@@ -718,7 +718,7 @@ VisitResult VisitResult::NeverResult() {
}
std::tuple<size_t, std::string> Field::GetFieldSizeInformation() const {
auto optional = GetOptionalFieldSizeInformation();
auto optional = SizeOf(this->name_and_type.type);
if (optional.has_value()) {
return *optional;
}
......@@ -727,55 +727,52 @@ std::tuple<size_t, std::string> Field::GetFieldSizeInformation() const {
return std::make_tuple(0, "#no size");
}
base::Optional<std::tuple<size_t, std::string>>
Field::GetOptionalFieldSizeInformation() const {
base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type) {
std::string size_string;
const Type* field_type = this->name_and_type.type;
size_t field_size = 0;
if (field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
field_size = TargetArchitecture::TaggedSize();
size_t size;
if (type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
size = TargetArchitecture::TaggedSize();
size_string = "kTaggedSize";
} else if (field_type->IsSubtypeOf(TypeOracle::GetRawPtrType())) {
field_size = TargetArchitecture::RawPtrSize();
} else if (type->IsSubtypeOf(TypeOracle::GetRawPtrType())) {
size = TargetArchitecture::RawPtrSize();
size_string = "kSystemPointerSize";
} else if (field_type->IsSubtypeOf(TypeOracle::GetVoidType())) {
field_size = 0;
} else if (type->IsSubtypeOf(TypeOracle::GetVoidType())) {
size = 0;
size_string = "0";
} else if (field_type->IsSubtypeOf(TypeOracle::GetInt8Type())) {
field_size = kUInt8Size;
} else if (type->IsSubtypeOf(TypeOracle::GetInt8Type())) {
size = kUInt8Size;
size_string = "kUInt8Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetUint8Type())) {
field_size = kUInt8Size;
} else if (type->IsSubtypeOf(TypeOracle::GetUint8Type())) {
size = kUInt8Size;
size_string = "kUInt8Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetInt16Type())) {
field_size = kUInt16Size;
} else if (type->IsSubtypeOf(TypeOracle::GetInt16Type())) {
size = kUInt16Size;
size_string = "kUInt16Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetUint16Type())) {
field_size = kUInt16Size;
} else if (type->IsSubtypeOf(TypeOracle::GetUint16Type())) {
size = kUInt16Size;
size_string = "kUInt16Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetInt32Type())) {
field_size = kInt32Size;
} else if (type->IsSubtypeOf(TypeOracle::GetInt32Type())) {
size = kInt32Size;
size_string = "kInt32Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetUint32Type())) {
field_size = kInt32Size;
} else if (type->IsSubtypeOf(TypeOracle::GetUint32Type())) {
size = kInt32Size;
size_string = "kInt32Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetFloat64Type())) {
field_size = kDoubleSize;
} else if (type->IsSubtypeOf(TypeOracle::GetFloat64Type())) {
size = kDoubleSize;
size_string = "kDoubleSize";
} else if (field_type->IsSubtypeOf(TypeOracle::GetIntPtrType())) {
field_size = TargetArchitecture::RawPtrSize();
} else if (type->IsSubtypeOf(TypeOracle::GetIntPtrType())) {
size = TargetArchitecture::RawPtrSize();
size_string = "kIntptrSize";
} else if (field_type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) {
field_size = TargetArchitecture::RawPtrSize();
} else if (type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) {
size = TargetArchitecture::RawPtrSize();
size_string = "kIntptrSize";
} else if (const StructType* struct_type =
StructType::DynamicCast(field_type)) {
field_size = struct_type->PackedSize();
size_string = std::to_string(field_size);
} else if (const StructType* struct_type = StructType::DynamicCast(type)) {
size = struct_type->PackedSize();
size_string = std::to_string(size);
} else {
return {};
}
return std::make_tuple(field_size, size_string);
return std::make_tuple(size, size_string);
}
} // namespace torque
......
......@@ -183,11 +183,6 @@ struct Field {
// reliance of string types is quite clunky.
std::tuple<size_t, std::string> GetFieldSizeInformation() const;
// Like GetFieldSizeInformation, but rather than raising an error if the
// field's size is unknown, it returns no value.
base::Optional<std::tuple<size_t, std::string>>
GetOptionalFieldSizeInformation() const;
SourcePosition pos;
const AggregateType* aggregate;
base::Optional<NameAndType> index;
......@@ -734,6 +729,8 @@ TypeVector LowerParameterTypes(const TypeVector& parameters);
TypeVector LowerParameterTypes(const ParameterTypes& parameter_types,
size_t vararg_count = 0);
base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type);
} // namespace torque
} // namespace internal
} // namespace v8
......
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