[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/+/1924265 Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Commit-Queue: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#65089}
This commit is contained in:
parent
ea06b01e52
commit
dddc6a90f1
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user