Commit 07d82db1 authored by Seth Brenith's avatar Seth Brenith Committed by V8 LUCI CQ

Reland "[torque] Get rid of @noVerifier annotation"

This is a reland of 94958172

Original change's description:
> [torque] Get rid of @noVerifier annotation
>
> As one small step toward reducing annotations, I propose that all
> classes get generated verifiers unless they've opted out of C++ class
> generation via @doNotGenerateCppClass, and that generated verifiers
> always verify every Torque-defined field. If a generated verifier is
> incorrect, such as for JSFunction or DataHandler, we can just avoid
> calling it and hand-code the verification.
>
> Bug: v8:7793
> Change-Id: I7c0edb660574d0c688a59c7e90c41ee7ad464b42
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3171758
> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
> Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
> Cr-Commit-Position: refs/heads/main@{#77145}

Bug: v8:7793
Change-Id: I3da34705bf9fc2b1886161f8f59c7275583f7fc4
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3194812
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77168}
parent 68ab78e2
......@@ -554,7 +554,6 @@ extern class Filler extends HeapObject generates 'TNode<HeapObject>';
// Like JSObject, but created from API function.
@apiExposedInstanceTypeValue(0x422)
@doNotGenerateCast
@noVerifier
extern class JSApiObject extends JSObject generates 'TNode<JSObject>';
// TODO(gsathya): This only exists to make JSApiObject instance type into a
......@@ -562,7 +561,6 @@ extern class JSApiObject extends JSObject generates 'TNode<JSObject>';
@apiExposedInstanceTypeValue(0x80A)
@doNotGenerateCast
@highestInstanceTypeWithinParentClassRange
@noVerifier
extern class JSLastDummyApiObject extends JSApiObject
generates 'TNode<JSObject>';
......
......@@ -166,7 +166,9 @@ void TaggedIndex::TaggedIndexVerify(Isolate* isolate) {
}
void HeapObject::HeapObjectVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::HeapObjectVerify(*this, isolate);
CHECK(IsHeapObject());
VerifyPointer(isolate, map(isolate));
CHECK(map(isolate).IsMap());
switch (map().instance_type()) {
#define STRING_TYPE_CASE(TYPE, size, name, CamelName) case TYPE:
......@@ -827,7 +829,24 @@ void JSBoundFunction::JSBoundFunctionVerify(Isolate* isolate) {
}
void JSFunction::JSFunctionVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::JSFunctionVerify(*this, isolate);
// Don't call TorqueGeneratedClassVerifiers::JSFunctionVerify here because the
// Torque class definition contains the field `prototype_or_initial_map` which
// may not be allocated.
// This assertion exists to encourage updating this verification function if
// new fields are added in the Torque class layout definition.
STATIC_ASSERT(JSFunction::TorqueGeneratedClass::kHeaderSize ==
8 * kTaggedSize);
JSFunctionOrBoundFunctionVerify(isolate);
CHECK(IsJSFunction());
VerifyPointer(isolate, shared(isolate));
CHECK(shared(isolate).IsSharedFunctionInfo());
VerifyPointer(isolate, context(isolate, kRelaxedLoad));
CHECK(context(isolate, kRelaxedLoad).IsContext());
VerifyPointer(isolate, raw_feedback_cell(isolate));
CHECK(raw_feedback_cell(isolate).IsFeedbackCell());
VerifyPointer(isolate, raw_code(isolate));
CHECK(raw_code(isolate).IsCodeT());
CHECK(map(isolate).is_callable());
Handle<JSFunction> function(*this, isolate);
......@@ -1230,8 +1249,9 @@ void SmallOrderedHashTable<Derived>::SmallOrderedHashTableVerify(
}
}
}
void SmallOrderedHashMap::SmallOrderedHashMapVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::SmallOrderedHashMapVerify(*this, isolate);
CHECK(IsSmallOrderedHashMap());
SmallOrderedHashTable<SmallOrderedHashMap>::SmallOrderedHashTableVerify(
isolate);
for (int entry = NumberOfElements(); entry < NumberOfDeletedElements();
......@@ -1244,7 +1264,7 @@ void SmallOrderedHashMap::SmallOrderedHashMapVerify(Isolate* isolate) {
}
void SmallOrderedHashSet::SmallOrderedHashSetVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::SmallOrderedHashSetVerify(*this, isolate);
CHECK(IsSmallOrderedHashSet());
SmallOrderedHashTable<SmallOrderedHashSet>::SmallOrderedHashTableVerify(
isolate);
for (int entry = NumberOfElements(); entry < NumberOfDeletedElements();
......@@ -1258,8 +1278,7 @@ void SmallOrderedHashSet::SmallOrderedHashSetVerify(Isolate* isolate) {
void SmallOrderedNameDictionary::SmallOrderedNameDictionaryVerify(
Isolate* isolate) {
TorqueGeneratedClassVerifiers::SmallOrderedNameDictionaryVerify(*this,
isolate);
CHECK(IsSmallOrderedNameDictionary());
SmallOrderedHashTable<
SmallOrderedNameDictionary>::SmallOrderedHashTableVerify(isolate);
for (int entry = NumberOfElements(); entry < NumberOfDeletedElements();
......@@ -1655,9 +1674,20 @@ void WasmExportedFunctionData::WasmExportedFunctionDataVerify(
#endif // V8_ENABLE_WEBASSEMBLY
void DataHandler::DataHandlerVerify(Isolate* isolate) {
TorqueGeneratedClassVerifiers::DataHandlerVerify(*this, isolate);
// Don't call TorqueGeneratedClassVerifiers::DataHandlerVerify because the
// Torque definition of this class includes all of the optional fields.
// This assertion exists to encourage updating this verification function if
// new fields are added in the Torque class layout definition.
STATIC_ASSERT(DataHandler::kHeaderSize == 6 * kTaggedSize);
StructVerify(isolate);
CHECK(IsDataHandler());
VerifyPointer(isolate, smi_handler(isolate));
CHECK_IMPLIES(!smi_handler().IsSmi(),
IsStoreHandler() && smi_handler().IsCodeT());
VerifyPointer(isolate, validity_cell(isolate));
CHECK(validity_cell().IsSmi() || validity_cell().IsCell());
int data_count = data_field_count();
if (data_count >= 1) {
VerifyMaybeObjectField(isolate, kData1Offset);
......
......@@ -9,7 +9,6 @@ extern class BigIntBase extends PrimitiveHeapObject
type BigInt extends BigIntBase;
@noVerifier
@hasSameInstanceTypeAsParent
@doNotGenerateCast
extern class MutableBigInt extends BigIntBase generates 'TNode<BigInt>';
......
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This class does not use the generated verifier, so if you change anything
// here, please also update DataHandlerVerify in objects-debug.cc.
@abstract
extern class DataHandler extends Struct {
// [smi_handler]: A Smi which encodes a handler or Code object (we still
......@@ -15,7 +17,7 @@ extern class DataHandler extends Struct {
validity_cell: Smi|Cell;
// Space for the following fields may or may not be allocated.
@noVerifier data1: MaybeObject;
@noVerifier data2: MaybeObject;
@noVerifier data3: MaybeObject;
data1: MaybeObject;
data2: MaybeObject;
data3: MaybeObject;
}
......@@ -17,6 +17,8 @@ extern class JSBoundFunction extends JSFunctionOrBoundFunction {
bound_arguments: FixedArray;
}
// This class does not use the generated verifier, so if you change anything
// here, please also update JSFunctionVerify in objects-debug.cc.
@highestInstanceTypeWithinParentClassRange
extern class JSFunction extends JSFunctionOrBoundFunction {
shared_function_info: SharedFunctionInfo;
......@@ -25,14 +27,13 @@ extern class JSFunction extends JSFunctionOrBoundFunction {
@if(V8_EXTERNAL_CODE_SPACE) code: CodeDataContainer;
@ifnot(V8_EXTERNAL_CODE_SPACE) code: Code;
// Space for the following field may or may not be allocated.
@noVerifier prototype_or_initial_map: JSReceiver|Map;
prototype_or_initial_map: JSReceiver|Map;
}
// Class constructors are special, because they are callable, but [[Call]] will
// raise an exception.
// See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
@doNotGenerateCast
@noVerifier
@highestInstanceTypeWithinParentClassRange
extern class JSClassConstructor extends JSFunction
generates 'TNode<JSFunction>';
......
......@@ -14,7 +14,6 @@ const kSmallOrderedHashTableNotFound: constexpr int31
const kSmallOrderedHashTableLoadFactor: constexpr int31
generates 'SmallOrderedHashTable<int>::kLoadFactor';
@noVerifier
@abstract
@doNotGenerateCppClass
extern class SmallOrderedHashTable extends HeapObject
......
......@@ -4,7 +4,6 @@
#include 'src/objects/swiss-name-dictionary.h'
@noVerifier
@doNotGenerateCppClass
extern class SwissNameDictionary extends HeapObject {
hash: uint32;
......
......@@ -939,7 +939,6 @@ struct ClassFieldExpression {
std::vector<ConditionalAnnotation> conditions;
bool weak;
bool const_qualified;
bool generate_verify;
FieldSynchronization read_synchronization;
FieldSynchronization write_synchronization;
};
......
......@@ -83,7 +83,6 @@ static const char* const FIXED_ARRAY_BASE_TYPE_STRING = "FixedArrayBase";
static const char* const WEAK_HEAP_OBJECT = "WeakHeapObject";
static const char* const STATIC_ASSERT_MACRO_STRING = "StaticAssert";
static const char* const ANNOTATION_NO_VERIFIER = "@noVerifier";
static const char* const ANNOTATION_ABSTRACT = "@abstract";
static const char* const ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT =
"@hasSameInstanceTypeAsParent";
......@@ -143,20 +142,19 @@ using AbstractTypeFlags = base::Flags<AbstractTypeFlag>;
enum class ClassFlag {
kNone = 0,
kExtern = 1 << 0,
kGenerateVerify = 1 << 1,
kTransient = 1 << 2,
kAbstract = 1 << 3,
kIsShape = 1 << 4,
kHasSameInstanceTypeAsParent = 1 << 5,
kGenerateCppClassDefinitions = 1 << 6,
kCustomCppClass = 1 << 7,
kHighestInstanceTypeWithinParent = 1 << 8,
kLowestInstanceTypeWithinParent = 1 << 9,
kUndefinedLayout = 1 << 10,
kGenerateBodyDescriptor = 1 << 11,
kExport = 1 << 12,
kDoNotGenerateCast = 1 << 13,
kCustomMap = 1 << 14,
kTransient = 1 << 1,
kAbstract = 1 << 2,
kIsShape = 1 << 3,
kHasSameInstanceTypeAsParent = 1 << 4,
kGenerateCppClassDefinitions = 1 << 5,
kCustomCppClass = 1 << 6,
kHighestInstanceTypeWithinParent = 1 << 7,
kLowestInstanceTypeWithinParent = 1 << 8,
kUndefinedLayout = 1 << 9,
kGenerateBodyDescriptor = 1 << 10,
kExport = 1 << 11,
kDoNotGenerateCast = 1 << 12,
kCustomMap = 1 << 13,
};
using ClassFlags = base::Flags<ClassFlag>;
......
......@@ -77,7 +77,7 @@ const Type* ImplementationVisitor::Visit(Statement* stmt) {
void ImplementationVisitor::BeginGeneratedFiles() {
std::set<SourceId> contains_class_definitions;
for (const ClassType* type : TypeOracle::GetClasses()) {
if (type->GenerateCppClassDefinitions()) {
if (type->ShouldGenerateCppClassDefinitions()) {
contains_class_definitions.insert(type->AttributedToFile());
}
}
......@@ -4170,7 +4170,7 @@ void CppClassGenerator::GenerateClass() {
// hand-written definition.
base::Optional<const ClassType*> parent = type_->parent()->ClassSupertype();
while (parent) {
if ((*parent)->GenerateCppClassDefinitions() &&
if ((*parent)->ShouldGenerateCppClassDefinitions() &&
!(*parent)->ShouldGenerateFullClassDefinition() &&
(*parent)->AttributedToFile() == type_->AttributedToFile()) {
Error("Exported ", *type_,
......@@ -4641,7 +4641,7 @@ void ImplementationVisitor::GenerateClassDefinitions(
CurrentSourcePosition::Scope position_activator(type->GetPosition());
auto& streams = GlobalContext::GeneratedPerFile(type->AttributedToFile());
std::ostream& header = streams.class_definition_headerfile;
std::string name = type->GenerateCppClassDefinitions()
std::string name = type->ShouldGenerateCppClassDefinitions()
? type->name()
: type->GetGeneratedTNodeTypeName();
header << "class " << name << ";\n";
......@@ -4655,7 +4655,7 @@ void ImplementationVisitor::GenerateClassDefinitions(
std::ostream& inline_header = streams.class_definition_inline_headerfile;
std::ostream& implementation = streams.class_definition_ccfile;
if (type->GenerateCppClassDefinitions()) {
if (type->ShouldGenerateCppClassDefinitions()) {
CppClassGenerator g(type, header, inline_header, implementation);
g.GenerateClass();
}
......@@ -4847,7 +4847,7 @@ void ImplementationVisitor::GeneratePrintDefinitions(
for (const ClassType* type : TypeOracle::GetClasses()) {
if (!type->ShouldGeneratePrint()) continue;
DCHECK(type->GenerateCppClassDefinitions());
DCHECK(type->ShouldGenerateCppClassDefinitions());
const ClassType* super = type->GetSuperClass();
std::string gen_name = "TorqueGenerated" + type->name();
std::string gen_name_T =
......@@ -5081,7 +5081,6 @@ void GenerateClassFieldVerifier(const std::string& class_name,
const ClassType& class_type, const Field& f,
std::ostream& h_contents,
std::ostream& cc_contents) {
if (!f.generate_verify) return;
const Type* field_type = f.name_and_type.type;
// We only verify tagged types, not raw numbers or pointers. Structs
......@@ -5198,16 +5197,7 @@ void ImplementationVisitor::GenerateClassVerifiers(
}
if (super_type) {
std::string super_name = super_type->name();
if (super_name == "HeapObject") {
// Special case: HeapObjectVerify checks the Map type and dispatches
// to more specific types, so calling it here would cause infinite
// recursion. We could consider moving that behavior into a
// different method to make the contract of *Verify methods more
// consistent, but for now we'll just avoid the bad case.
cc_contents << " " << super_name << "Verify(o, isolate);\n";
} else {
cc_contents << " o." << super_name << "Verify(isolate);\n";
}
cc_contents << " o." << super_name << "Verify(isolate);\n";
}
// Second, verify that this object is what it claims to be.
......
......@@ -888,8 +888,7 @@ base::Optional<ParseResult> MakeClassDeclaration(
ParseResultIterator* child_results) {
AnnotationSet annotations(
child_results,
{ANNOTATION_NO_VERIFIER, ANNOTATION_ABSTRACT,
ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT,
{ANNOTATION_ABSTRACT, ANNOTATION_HAS_SAME_INSTANCE_TYPE_AS_PARENT,
ANNOTATION_DO_NOT_GENERATE_CPP_CLASS, ANNOTATION_CUSTOM_CPP_CLASS,
ANNOTATION_CUSTOM_MAP, ANNOTATION_GENERATE_BODY_DESCRIPTOR,
ANNOTATION_EXPORT, ANNOTATION_DO_NOT_GENERATE_CAST,
......@@ -898,8 +897,6 @@ base::Optional<ParseResult> MakeClassDeclaration(
{ANNOTATION_RESERVE_BITS_IN_INSTANCE_TYPE,
ANNOTATION_INSTANCE_TYPE_VALUE});
ClassFlags flags = ClassFlag::kNone;
bool generate_verify = !annotations.Contains(ANNOTATION_NO_VERIFIER);
if (generate_verify) flags |= ClassFlag::kGenerateVerify;
if (annotations.Contains(ANNOTATION_ABSTRACT)) {
flags |= ClassFlag::kAbstract;
}
......@@ -1969,11 +1966,9 @@ base::Optional<ParseResult> MakeAnnotation(ParseResultIterator* child_results) {
base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) {
AnnotationSet annotations(
child_results,
{ANNOTATION_NO_VERIFIER, ANNOTATION_CPP_RELAXED_STORE,
ANNOTATION_CPP_RELAXED_LOAD, ANNOTATION_CPP_RELEASE_STORE,
ANNOTATION_CPP_ACQUIRE_LOAD},
{ANNOTATION_CPP_RELAXED_STORE, ANNOTATION_CPP_RELAXED_LOAD,
ANNOTATION_CPP_RELEASE_STORE, ANNOTATION_CPP_ACQUIRE_LOAD},
{ANNOTATION_IF, ANNOTATION_IFNOT});
bool generate_verify = !annotations.Contains(ANNOTATION_NO_VERIFIER);
FieldSynchronization write_synchronization = FieldSynchronization::kNone;
if (annotations.Contains(ANNOTATION_CPP_RELEASE_STORE)) {
write_synchronization = FieldSynchronization::kAcquireRelease;
......@@ -2025,7 +2020,6 @@ base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) {
std::move(conditions),
weak,
const_qualified,
generate_verify,
read_synchronization,
write_synchronization}};
}
......
......@@ -211,7 +211,6 @@ const StructType* TypeVisitor::ComputeType(
offset.SingleValue(),
false,
field.const_qualified,
false,
FieldSynchronization::kNone,
FieldSynchronization::kNone};
auto optional_size = SizeOf(f.name_and_type.type);
......@@ -319,7 +318,6 @@ const ClassType* TypeVisitor::ComputeType(
Error("non-external classes must have defined layouts");
}
}
flags = flags | ClassFlag::kGenerateVerify;
}
if (!(flags & ClassFlag::kExtern) &&
(flags & ClassFlag::kHasSameInstanceTypeAsParent)) {
......@@ -442,7 +440,6 @@ void TypeVisitor::VisitClassFieldsAndMethods(
class_offset.SingleValue(),
field_expression.weak,
field_expression.const_qualified,
field_expression.generate_verify,
field_expression.read_synchronization,
field_expression.write_synchronization});
ResidueClass field_size = std::get<0>(field.GetFieldSizeInformation());
......
......@@ -228,7 +228,6 @@ struct Field {
bool is_weak;
bool const_qualified;
bool generate_verify;
FieldSynchronization read_synchronization;
FieldSynchronization write_synchronization;
};
......@@ -670,12 +669,12 @@ class ClassType final : public AggregateType {
std::string GetGeneratedTNodeTypeNameImpl() const override;
bool IsExtern() const { return flags_ & ClassFlag::kExtern; }
bool ShouldGeneratePrint() const {
return !IsExtern() || (GenerateCppClassDefinitions() && !IsAbstract() &&
!HasUndefinedLayout());
return !IsExtern() || (ShouldGenerateCppClassDefinitions() &&
!IsAbstract() && !HasUndefinedLayout());
}
bool ShouldGenerateVerify() const {
return !IsExtern() || ((flags_ & ClassFlag::kGenerateVerify) &&
(!HasUndefinedLayout() && !IsShape()));
return !IsExtern() || (ShouldGenerateCppClassDefinitions() &&
!HasUndefinedLayout() && !IsShape());
}
bool ShouldGenerateBodyDescriptor() const {
return flags_ & ClassFlag::kGenerateBodyDescriptor ||
......@@ -689,9 +688,8 @@ class ClassType final : public AggregateType {
bool HasSameInstanceTypeAsParent() const {
return flags_ & ClassFlag::kHasSameInstanceTypeAsParent;
}
bool GenerateCppClassDefinitions() const {
return flags_ & ClassFlag::kGenerateCppClassDefinitions || !IsExtern() ||
ShouldGenerateBodyDescriptor();
bool ShouldGenerateCppClassDefinitions() const {
return (flags_ & ClassFlag::kGenerateCppClassDefinitions) || !IsExtern();
}
bool ShouldGenerateFullClassDefinition() const {
return !IsExtern() && !(flags_ & ClassFlag::kCustomCppClass);
......
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