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 @@ ...@@ -3,24 +3,15 @@
// found in the LICENSE file. // found in the LICENSE file.
namespace torque_internal { 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 // 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 // that might lead to unsoundness when used incorrectly. Unsafe markers should
// therefore not be instantiated anywhere outside of this namespace. // therefore not be instantiated anywhere outside of this namespace.
struct Unsafe {} 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> { struct Reference<T: type> {
const object: HeapObject; const object: HeapObject;
const offset: intptr; const offset: intptr;
...@@ -39,7 +30,7 @@ namespace torque_internal { ...@@ -39,7 +30,7 @@ namespace torque_internal {
TryAtIndex(index: intptr):&T labels OutOfBounds { TryAtIndex(index: intptr):&T labels OutOfBounds {
if (Convert<uintptr>(index) < Convert<uintptr>(this.length)) { if (Convert<uintptr>(index) < Convert<uintptr>(this.length)) {
return UnsafeNewReference<T>( return UnsafeNewReference<T>(
this.object, this.offset + index * SizeOf<T>()); this.object, this.offset + index * %SizeOf<T>());
} else { } else {
goto OutOfBounds; goto OutOfBounds;
} }
...@@ -64,7 +55,7 @@ namespace torque_internal { ...@@ -64,7 +55,7 @@ namespace torque_internal {
} }
Iterator(): SliceIterator<T> { Iterator(): SliceIterator<T> {
const end = this.offset + this.length * SizeOf<T>(); const end = this.offset + this.length * %SizeOf<T>();
return SliceIterator<T>{ return SliceIterator<T>{
object: this.object, object: this.object,
start: this.offset, start: this.offset,
...@@ -99,7 +90,7 @@ namespace torque_internal { ...@@ -99,7 +90,7 @@ namespace torque_internal {
goto NoMore; goto NoMore;
} else { } else {
const result = UnsafeNewReference<T>(this.object, this.start); const result = UnsafeNewReference<T>(this.object, this.start);
this.start += SizeOf<T>(); this.start += %SizeOf<T>();
return result; return result;
} }
} }
......
...@@ -9,7 +9,6 @@ extern class EnumCache extends Struct { ...@@ -9,7 +9,6 @@ extern class EnumCache extends Struct {
indices: FixedArray; indices: FixedArray;
} }
// Keep in sync with hand-coded SizeOf<DescriptorEntry> in torque-internal.tq.
@export @export
struct DescriptorEntry { struct DescriptorEntry {
key: Name|Undefined; key: Name|Undefined;
......
...@@ -242,7 +242,7 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction, ...@@ -242,7 +242,7 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
"%GetAllocationBaseSize") { "%GetAllocationBaseSize") {
if (instruction.specialization_types.size() != 1) { if (instruction.specialization_types.size() != 1) {
ReportError( ReportError(
"incorrect number of specialization classes for " "incorrect number of type parameters for "
"%GetAllocationBaseSize (should be one)"); "%GetAllocationBaseSize (should be one)");
} }
const ClassType* class_type = const ClassType* class_type =
......
...@@ -2360,7 +2360,19 @@ VisitResult ImplementationVisitor::GenerateCall( ...@@ -2360,7 +2360,19 @@ VisitResult ImplementationVisitor::GenerateCall(
return VisitResult(return_type, assembler().TopRange(slot_count)); return VisitResult(return_type, assembler().TopRange(slot_count));
} }
} else if (auto* intrinsic = Intrinsic::DynamicCast(callable)) { } 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 || if (intrinsic->signature().parameter_types.types.size() != 1 ||
constexpr_arguments.size() != 1) { constexpr_arguments.size() != 1) {
ReportError( ReportError(
......
...@@ -155,7 +155,7 @@ const StructType* TypeVisitor::ComputeType( ...@@ -155,7 +155,7 @@ const StructType* TypeVisitor::ComputeType(
false, false,
field.const_qualified, field.const_qualified,
false}; 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 // Structs may contain fields that aren't representable in packed form. If
// so, then this field and any subsequent fields should have their offsets // so, then this field and any subsequent fields should have their offsets
// marked as invalid. // marked as invalid.
......
...@@ -718,7 +718,7 @@ VisitResult VisitResult::NeverResult() { ...@@ -718,7 +718,7 @@ VisitResult VisitResult::NeverResult() {
} }
std::tuple<size_t, std::string> Field::GetFieldSizeInformation() const { std::tuple<size_t, std::string> Field::GetFieldSizeInformation() const {
auto optional = GetOptionalFieldSizeInformation(); auto optional = SizeOf(this->name_and_type.type);
if (optional.has_value()) { if (optional.has_value()) {
return *optional; return *optional;
} }
...@@ -727,55 +727,52 @@ std::tuple<size_t, std::string> Field::GetFieldSizeInformation() const { ...@@ -727,55 +727,52 @@ std::tuple<size_t, std::string> Field::GetFieldSizeInformation() const {
return std::make_tuple(0, "#no size"); return std::make_tuple(0, "#no size");
} }
base::Optional<std::tuple<size_t, std::string>> base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type) {
Field::GetOptionalFieldSizeInformation() const {
std::string size_string; std::string size_string;
const Type* field_type = this->name_and_type.type; size_t size;
size_t field_size = 0; if (type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
if (field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) { size = TargetArchitecture::TaggedSize();
field_size = TargetArchitecture::TaggedSize();
size_string = "kTaggedSize"; size_string = "kTaggedSize";
} else if (field_type->IsSubtypeOf(TypeOracle::GetRawPtrType())) { } else if (type->IsSubtypeOf(TypeOracle::GetRawPtrType())) {
field_size = TargetArchitecture::RawPtrSize(); size = TargetArchitecture::RawPtrSize();
size_string = "kSystemPointerSize"; size_string = "kSystemPointerSize";
} else if (field_type->IsSubtypeOf(TypeOracle::GetVoidType())) { } else if (type->IsSubtypeOf(TypeOracle::GetVoidType())) {
field_size = 0; size = 0;
size_string = "0"; size_string = "0";
} else if (field_type->IsSubtypeOf(TypeOracle::GetInt8Type())) { } else if (type->IsSubtypeOf(TypeOracle::GetInt8Type())) {
field_size = kUInt8Size; size = kUInt8Size;
size_string = "kUInt8Size"; size_string = "kUInt8Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetUint8Type())) { } else if (type->IsSubtypeOf(TypeOracle::GetUint8Type())) {
field_size = kUInt8Size; size = kUInt8Size;
size_string = "kUInt8Size"; size_string = "kUInt8Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetInt16Type())) { } else if (type->IsSubtypeOf(TypeOracle::GetInt16Type())) {
field_size = kUInt16Size; size = kUInt16Size;
size_string = "kUInt16Size"; size_string = "kUInt16Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetUint16Type())) { } else if (type->IsSubtypeOf(TypeOracle::GetUint16Type())) {
field_size = kUInt16Size; size = kUInt16Size;
size_string = "kUInt16Size"; size_string = "kUInt16Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetInt32Type())) { } else if (type->IsSubtypeOf(TypeOracle::GetInt32Type())) {
field_size = kInt32Size; size = kInt32Size;
size_string = "kInt32Size"; size_string = "kInt32Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetUint32Type())) { } else if (type->IsSubtypeOf(TypeOracle::GetUint32Type())) {
field_size = kInt32Size; size = kInt32Size;
size_string = "kInt32Size"; size_string = "kInt32Size";
} else if (field_type->IsSubtypeOf(TypeOracle::GetFloat64Type())) { } else if (type->IsSubtypeOf(TypeOracle::GetFloat64Type())) {
field_size = kDoubleSize; size = kDoubleSize;
size_string = "kDoubleSize"; size_string = "kDoubleSize";
} else if (field_type->IsSubtypeOf(TypeOracle::GetIntPtrType())) { } else if (type->IsSubtypeOf(TypeOracle::GetIntPtrType())) {
field_size = TargetArchitecture::RawPtrSize(); size = TargetArchitecture::RawPtrSize();
size_string = "kIntptrSize"; size_string = "kIntptrSize";
} else if (field_type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) { } else if (type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) {
field_size = TargetArchitecture::RawPtrSize(); size = TargetArchitecture::RawPtrSize();
size_string = "kIntptrSize"; size_string = "kIntptrSize";
} else if (const StructType* struct_type = } else if (const StructType* struct_type = StructType::DynamicCast(type)) {
StructType::DynamicCast(field_type)) { size = struct_type->PackedSize();
field_size = struct_type->PackedSize(); size_string = std::to_string(size);
size_string = std::to_string(field_size);
} else { } else {
return {}; return {};
} }
return std::make_tuple(field_size, size_string); return std::make_tuple(size, size_string);
} }
} // namespace torque } // namespace torque
......
...@@ -183,11 +183,6 @@ struct Field { ...@@ -183,11 +183,6 @@ struct Field {
// reliance of string types is quite clunky. // reliance of string types is quite clunky.
std::tuple<size_t, std::string> GetFieldSizeInformation() const; 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; SourcePosition pos;
const AggregateType* aggregate; const AggregateType* aggregate;
base::Optional<NameAndType> index; base::Optional<NameAndType> index;
...@@ -734,6 +729,8 @@ TypeVector LowerParameterTypes(const TypeVector& parameters); ...@@ -734,6 +729,8 @@ TypeVector LowerParameterTypes(const TypeVector& parameters);
TypeVector LowerParameterTypes(const ParameterTypes& parameter_types, TypeVector LowerParameterTypes(const ParameterTypes& parameter_types,
size_t vararg_count = 0); size_t vararg_count = 0);
base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type);
} // namespace torque } // namespace torque
} // namespace internal } // namespace internal
} // namespace v8 } // 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