Commit e483fb27 authored by Seth Brenith's avatar Seth Brenith Committed by Commit Bot

[torque] Automatically generate verifier functions

This change generates functions that verify the things that Torque knows
about objects and their fields. We still must implement each verifier
function in objects-debug.cc, but we can call into the generated code to
verify that field types match their Torque definitions. If no additional
verification is required, we can use the macro USE_TORQUE_VERIFIER as a
shorthand for a verifier that calls the corresponding generated
function.

A new annotation @noVerifier can be applied to both class and field
definitions, to prevent generating verification code. This allows fully
customized verification for complicated cases like
JSFunction::prototype_or_initial_map, which might not exist at all, and
JSObject::elements, which might be a one pointer filler map.

Because Factory::InitializeJSObjectFromMap fills new objects with
undefined values, and many verifiers need to deal with partially-
initialized objects, the generated verifiers allow undefined values on
every class deriving from JSObject. In cases where stricter checks were
previously performed, they are kept in objects-debug.cc.

Bug: v8:7793
Change-Id: I84034efadca89ba0aceddf92e886ffbfaa4c23fa
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1594042
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Reviewed-by: 's avatarSigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61422}
parent 41bc1cfd
......@@ -1053,6 +1053,8 @@ action("run_torque") {
outputs = [
"$target_gen_dir/torque-generated/builtin-definitions-from-dsl.h",
"$target_gen_dir/torque-generated/class-definitions-from-dsl.h",
"$target_gen_dir/torque-generated/class-verifiers-from-dsl.cc",
"$target_gen_dir/torque-generated/class-verifiers-from-dsl.h",
"$target_gen_dir/torque-generated/objects-printer-from-dsl.cc",
]
foreach(namespace, torque_namespaces) {
......@@ -1119,6 +1121,8 @@ v8_source_set("torque_generated_definitions") {
]
sources = [
"$target_gen_dir/torque-generated/class-verifiers-from-dsl.cc",
"$target_gen_dir/torque-generated/class-verifiers-from-dsl.h",
"$target_gen_dir/torque-generated/objects-printer-from-dsl.cc",
]
......
......@@ -78,7 +78,10 @@ type Number = Smi | HeapNumber;
type BigInt extends HeapObject generates 'TNode<BigInt>';
type Numeric = Number | BigInt;
extern class Name extends HeapObject { hash_field: int32; }
@noVerifier
extern class Name extends HeapObject {
hash_field: int32;
}
extern class Symbol extends Name {
flags: int32;
......@@ -93,6 +96,7 @@ extern class ConsString extends String {
second: String;
}
@noVerifier
extern class ExternalString extends String {
resource: RawPtr;
resource_data: RawPtr;
......@@ -104,7 +108,9 @@ extern class ExternalTwoByteString extends ExternalString {}
extern class InternalizedString extends String {}
// TODO(v8:8983): Add declaration for variable-sized region.
extern class SeqString extends String {}
@noVerifier
extern class SeqString extends String {
}
extern class SeqOneByteString extends SeqString {}
extern class SeqTwoByteString extends SeqString {}
......@@ -118,7 +124,9 @@ extern class ThinString extends String { actual: String; }
// The HeapNumber value NaN
type NaN extends HeapNumber;
extern class Struct extends HeapObject {}
@noVerifier
extern class Struct extends HeapObject {
}
@generatePrint
extern class Tuple2 extends Struct {
......@@ -139,7 +147,10 @@ type RootIndex generates 'TNode<Int32T>' constexpr 'RootIndex';
type Map extends HeapObject generates 'TNode<Map>';
extern class FixedArrayBase extends HeapObject { length: Smi; }
@noVerifier
extern class FixedArrayBase extends HeapObject {
length: Smi;
}
extern class FixedArray extends FixedArrayBase { objects[length]: Object; }
......@@ -180,13 +191,16 @@ intrinsic %GetAllocationBaseSize<Class: type>(map: Map): intptr;
intrinsic %Allocate<Class: type>(size: intptr): Class;
intrinsic %AllocateInternalClass<Class: type>(slotCount: constexpr intptr): Class;
@noVerifier
extern class JSReceiver extends HeapObject {
properties_or_hash: FixedArrayBase | Smi;
}
type Constructor extends JSReceiver;
extern class JSObject extends JSReceiver { elements: FixedArrayBase; }
extern class JSObject extends JSReceiver {
@noVerifier elements: FixedArrayBase;
}
macro NewJSObject(
map: Map, properties: FixedArrayBase | Smi,
......@@ -207,9 +221,9 @@ macro NewJSObject(implicit context: Context)(): JSObject {
extern class JSFunction extends JSObject {
shared_function_info: SharedFunctionInfo;
context: Context;
feedback_cell: Smi;
feedback_cell: FeedbackCell;
weak code: Code;
weak prototype_or_initial_map: JSReceiver | Map;
@noVerifier weak prototype_or_initial_map: JSReceiver | Map;
}
extern class JSProxy extends JSReceiver {
......@@ -217,6 +231,7 @@ extern class JSProxy extends JSReceiver {
handler: Object;
}
@noVerifier
extern class JSProxyRevocableResult extends JSObject {
proxy: Object;
revoke: Object;
......@@ -238,6 +253,7 @@ extern class JSGlobalProxy extends JSObject { native_context: Object; }
extern class JSValue extends JSObject { value: Object; }
extern class JSArgumentsObject extends JSObject {}
@noVerifier
extern class JSArgumentsObjectWithLength extends JSArgumentsObject {
length: Object;
}
......@@ -306,10 +322,14 @@ type NoSharedNameSentinel extends Smi;
type JSModuleNamespace extends JSObject;
type WeakArrayList extends HeapObject;
extern class JSWeakCollection extends JSObject { table: Object; }
@noVerifier
extern class JSWeakCollection extends JSObject {
table: Object;
}
extern class JSWeakSet extends JSWeakCollection {}
extern class JSWeakMap extends JSWeakCollection {}
@noVerifier
extern class JSCollectionIterator extends JSObject {
table: Object;
index: Object;
......@@ -336,7 +356,7 @@ extern class PrototypeInfo extends Struct {
prototype_users: WeakArrayList | Zero;
registry_slot: Smi;
validity_cell: Object;
object_create_map: Smi | WeakArrayList;
@noVerifier object_create_map: Smi | WeakArrayList;
bit_field: Smi;
}
......@@ -377,7 +397,7 @@ extern class SharedFunctionInfo extends HeapObject {
weak function_data: Object;
name_or_scope_info: String | NoSharedNameSentinel | ScopeInfo;
outer_scope_info_or_feedback_metadata: HeapObject;
script_or_debug_info: Script | DebugInfo;
script_or_debug_info: Script | DebugInfo | Undefined;
length: int16;
formal_parameter_count: uint16;
// Currently set to uint16, can be set to uint8 to save space.
......@@ -412,7 +432,7 @@ type NumberDictionary extends HeapObject
extern class FreeSpace extends HeapObject {
size: Smi;
next: FreeSpace;
@noVerifier next: FreeSpace;
}
// %RawDownCast should *never* be used anywhere in Torque code except for
......@@ -504,6 +524,7 @@ extern class JSTypedArray extends JSArrayBufferView {
length: Smi;
}
@noVerifier
extern class JSAccessorPropertyDescriptor extends JSObject {
get: Object;
set: Object;
......@@ -511,7 +532,10 @@ extern class JSAccessorPropertyDescriptor extends JSObject {
configurable: Object;
}
extern class JSCollection extends JSObject { table: Object; }
@noVerifier
extern class JSCollection extends JSObject {
table: Object;
}
extern class JSSet extends JSCollection {}
extern class JSMap extends JSCollection {}
......@@ -542,6 +566,7 @@ extern class JSStringIterator extends JSObject {
next_index: Smi;
}
@noVerifier
extern class JSDataPropertyDescriptor extends JSObject {
value: Object;
writable: Object;
......@@ -575,7 +600,7 @@ extern class FunctionTemplateInfo extends TemplateInfo {
function_template_rare_data: Object;
shared_function_info: Object;
flag: Smi;
length: Smi;
@noVerifier length: Smi;
cached_property_name: Object;
}
......@@ -621,13 +646,13 @@ const UTF16:
extern class Foreign extends HeapObject { foreign_address: RawPtr; }
extern class InterceptorInfo extends Struct {
getter: Foreign | Zero;
setter: Foreign | Zero;
query: Foreign | Zero;
descriptor: Foreign | Zero;
deleter: Foreign | Zero;
enumerator: Foreign | Zero;
definer: Foreign | Zero;
@noVerifier getter: Foreign | Zero;
@noVerifier setter: Foreign | Zero;
@noVerifier query: Foreign | Zero;
@noVerifier descriptor: Foreign | Zero;
@noVerifier deleter: Foreign | Zero;
@noVerifier enumerator: Foreign | Zero;
@noVerifier definer: Foreign | Zero;
data: Object;
flags: Smi;
}
......@@ -651,9 +676,9 @@ extern class Cell extends HeapObject { value: Object; }
extern class DataHandler extends Struct {
smi_handler: Smi | Code;
validity_cell: Smi | Cell;
weak data_1: Object;
weak data_2: Object;
weak data_3: Object;
@noVerifier weak data_1: Object;
@noVerifier weak data_2: Object;
@noVerifier weak data_3: Object;
}
extern class JSGeneratorObject extends JSObject {
......@@ -733,9 +758,9 @@ extern class WasmCapiFunctionData extends Struct {
extern class WasmDebugInfo extends Struct {
instance: WasmInstanceObject;
interpreter_handle: Foreign | Undefined;
locals_names: FixedArray;
c_wasm_entries: FixedArray;
c_wasm_entry_map: Foreign; // Managed<wasm::SignatureMap>
locals_names: FixedArray | Undefined;
c_wasm_entries: FixedArray | Undefined;
c_wasm_entry_map: Foreign | Undefined; // Managed<wasm::SignatureMap>
}
extern class WasmExceptionTag extends Struct { index: Smi; }
......@@ -976,7 +1001,7 @@ extern class PromiseReaction extends Struct {
extern class PromiseReactionJobTask extends Microtask {
argument: Object;
context: Context;
handler: Callable | Undefined;
@noVerifier handler: Callable | Undefined;
promise_or_capability: JSPromise | PromiseCapability | Undefined;
}
......@@ -997,6 +1022,7 @@ extern class JSRegExp extends JSObject {
flags: Smi | Undefined;
}
@noVerifier
extern class JSIteratorResult extends JSObject {
value: Object;
done: Boolean;
......@@ -1069,9 +1095,9 @@ extern class AccessorInfo extends Struct {
name: Object;
flags: Smi;
expected_receiver_type: Object;
setter: Foreign | Zero;
getter: Foreign | Zero;
js_getter: Foreign | Zero;
@noVerifier setter: Foreign | Zero;
@noVerifier getter: Foreign | Zero;
@noVerifier js_getter: Foreign | Zero;
data: Object;
}
......@@ -1085,7 +1111,7 @@ extern class BreakPointInfo extends Tuple2 {}
extern class CoverageInfo extends FixedArray {}
extern class DebugInfo extends Struct {
shared_function_info: HeapObject;
shared_function_info: SharedFunctionInfo;
debugger_hints: Smi;
script: Undefined | Script;
original_bytecode_array: Undefined | BytecodeArray;
......@@ -1098,7 +1124,7 @@ extern class DebugInfo extends Struct {
extern class FeedbackVector extends HeapObject {
shared_function_info: SharedFunctionInfo;
// TODO(v8:9108): currently no support for MaybeObject in Torque
optimized_code_weak_or_smi: Object;
@noVerifier optimized_code_weak_or_smi: Object;
closure_feedback_cell_array: FixedArray;
length: int32;
invocation_count: int32;
......@@ -1113,7 +1139,7 @@ extern class FeedbackCell extends Struct {
type AllocationSite extends Struct;
extern class AllocationMemento extends Struct {
allocation_site: AllocationSite;
@noVerifier allocation_site: AllocationSite;
}
extern class WasmModuleObject extends JSObject {
......@@ -1121,8 +1147,8 @@ extern class WasmModuleObject extends JSObject {
export_wrappers: FixedArray;
script: Script;
weak_instance_list: WeakArrayList;
asm_js_offset_table: ByteArray;
break_point_infos: FixedArray;
asm_js_offset_table: ByteArray | Undefined;
break_point_infos: FixedArray | Undefined;
}
extern class WasmTableObject extends JSObject {
......@@ -1135,7 +1161,7 @@ extern class WasmTableObject extends JSObject {
extern class WasmMemoryObject extends JSObject {
array_buffer: JSArrayBuffer;
maximum_pages: Smi;
instances: WeakArrayList;
instances: WeakArrayList | Undefined;
}
extern class WasmGlobalObject extends JSObject {
......@@ -1150,9 +1176,13 @@ extern class WasmExceptionObject extends JSObject {
exception_tag: HeapObject;
}
extern class WasmExceptionPackage extends JSReceiver {}
@noVerifier
extern class WasmExceptionPackage extends JSReceiver {
}
extern class WasmExportedFunction extends JSFunction {}
@noVerifier
extern class WasmExportedFunction extends JSFunction {
}
extern class AsmWasmData extends Struct {
managed_native_module: Foreign; // Managed<wasm::NativeModule>
......
......@@ -64,6 +64,7 @@
#include "src/regexp/jsregexp.h"
#include "src/transitions-inl.h"
#include "src/wasm/wasm-objects-inl.h"
#include "torque-generated/class-verifiers-from-dsl.h"
namespace v8 {
namespace internal {
......@@ -92,6 +93,11 @@ namespace internal {
#ifdef VERIFY_HEAP
#define USE_TORQUE_VERIFIER(Class) \
void Class::Class##Verify(Isolate* isolate) { \
ClassVerifiersFromDSL::Class##Verify(*this, isolate); \
}
void Object::ObjectVerify(Isolate* isolate) {
RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::kObjectVerify);
if (IsSmi()) {
......@@ -133,14 +139,21 @@ void Smi::SmiVerify(Isolate* isolate) {
}
void HeapObject::HeapObjectVerify(Isolate* isolate) {
VerifyHeapPointer(isolate, map());
CHECK(map()->IsMap());
ClassVerifiersFromDSL::HeapObjectVerify(*this, isolate);
switch (map()->instance_type()) {
#define STRING_TYPE_CASE(TYPE, size, name, CamelName) case TYPE:
STRING_TYPE_LIST(STRING_TYPE_CASE)
#undef STRING_TYPE_CASE
if (IsConsString()) {
ConsString::cast(*this)->ConsStringVerify(isolate);
} else if (IsSlicedString()) {
SlicedString::cast(*this)->SlicedStringVerify(isolate);
} else if (IsThinString()) {
ThinString::cast(*this)->ThinStringVerify(isolate);
} else {
String::cast(*this)->StringVerify(isolate);
}
break;
case SYMBOL_TYPE:
Symbol::cast(*this)->SymbolVerify(isolate);
......@@ -480,14 +493,14 @@ void HeapObject::VerifyHeapPointer(Isolate* isolate, Object p) {
}
void Symbol::SymbolVerify(Isolate* isolate) {
CHECK(IsSymbol());
ClassVerifiersFromDSL::SymbolVerify(*this, isolate);
CHECK(HasHashCode());
CHECK_GT(Hash(), 0);
CHECK(name()->IsUndefined(isolate) || name()->IsString());
CHECK_IMPLIES(IsPrivateName(), IsPrivate());
}
void ByteArray::ByteArrayVerify(Isolate* isolate) { CHECK(IsByteArray()); }
USE_TORQUE_VERIFIER(ByteArray)
void BytecodeArray::BytecodeArrayVerify(Isolate* isolate) {
// TODO(oth): Walk bytecodes and immediate values to validate sanity.
......@@ -500,22 +513,12 @@ void BytecodeArray::BytecodeArrayVerify(Isolate* isolate) {
VerifyHeapPointer(isolate, constant_pool());
}
void FreeSpace::FreeSpaceVerify(Isolate* isolate) {
CHECK(IsFreeSpace());
VerifySmiField(kSizeOffset);
}
USE_TORQUE_VERIFIER(FreeSpace)
void FeedbackCell::FeedbackCellVerify(Isolate* isolate) {
CHECK(IsFeedbackCell());
VerifyHeapPointer(isolate, value());
CHECK(value()->IsUndefined(isolate) || value()->IsFeedbackVector() ||
value()->IsFixedArray());
}
USE_TORQUE_VERIFIER(FeedbackCell)
void FeedbackVector::FeedbackVectorVerify(Isolate* isolate) {
CHECK(IsFeedbackVector());
CHECK(closure_feedback_cell_array()->IsFixedArray());
ClassVerifiersFromDSL::FeedbackVectorVerify(*this, isolate);
MaybeObject code = optimized_code_weak_or_smi();
MaybeObject::VerifyMaybeObjectPointer(isolate, code);
CHECK(code->IsSmi() || code->IsWeakOrCleared());
......@@ -577,7 +580,7 @@ void VerifyJSObjectElements(Isolate* isolate, JSObject object) {
} // namespace
void JSObject::JSObjectVerify(Isolate* isolate) {
VerifyPointer(isolate, raw_properties_or_hash());
ClassVerifiersFromDSL::JSObjectVerify(*this, isolate);
VerifyHeapPointer(isolate, elements());
CHECK_IMPLIES(HasSloppyArgumentsElements(), IsJSArgumentsObject());
......@@ -709,29 +712,22 @@ void Map::DictionaryMapVerify(Isolate* isolate) {
CHECK_EQ(Map::GetVisitorId(*this), visitor_id());
}
void AliasedArgumentsEntry::AliasedArgumentsEntryVerify(Isolate* isolate) {
VerifySmiField(kAliasedContextSlotOffset);
}
USE_TORQUE_VERIFIER(AliasedArgumentsEntry)
void EmbedderDataArray::EmbedderDataArrayVerify(Isolate* isolate) {
ClassVerifiersFromDSL::EmbedderDataArrayVerify(*this, isolate);
EmbedderDataSlot start(*this, 0);
EmbedderDataSlot end(*this, length());
for (EmbedderDataSlot slot = start; slot < end; ++slot) {
Object e = slot.load_tagged();
Object::VerifyPointer(isolate, e);
}
VerifySmiField(kLengthOffset);
}
void FixedArray::FixedArrayVerify(Isolate* isolate) {
for (int i = 0; i < length(); i++) {
Object e = get(i);
VerifyPointer(isolate, e);
}
}
USE_TORQUE_VERIFIER(FixedArray)
void WeakFixedArray::WeakFixedArrayVerify(Isolate* isolate) {
VerifySmiField(kLengthOffset);
ClassVerifiersFromDSL::WeakFixedArrayVerify(*this, isolate);
for (int i = 0; i < length(); i++) {
MaybeObject::VerifyMaybeObjectPointer(isolate, Get(i));
}
......@@ -744,6 +740,7 @@ void WeakArrayList::WeakArrayListVerify(Isolate* isolate) {
}
void PropertyArray::PropertyArrayVerify(Isolate* isolate) {
ClassVerifiersFromDSL::PropertyArrayVerify(*this, isolate);
if (length() == 0) {
CHECK_EQ(*this, ReadOnlyRoots(isolate).empty_property_array());
return;
......@@ -754,10 +751,10 @@ void PropertyArray::PropertyArrayVerify(Isolate* isolate) {
Object e = get(i);
Object::VerifyPointer(isolate, e);
}
VerifySmiField(kLengthAndHashOffset);
}
void FixedDoubleArray::FixedDoubleArrayVerify(Isolate* isolate) {
ClassVerifiersFromDSL::FixedDoubleArrayVerify(*this, isolate);
for (int i = 0; i < length(); i++) {
if (!is_the_hole(i)) {
uint64_t value = get_representation(i);
......@@ -773,11 +770,7 @@ void FixedDoubleArray::FixedDoubleArrayVerify(Isolate* isolate) {
}
void Context::ContextVerify(Isolate* isolate) {
VerifySmiField(kLengthOffset);
VerifyObjectField(isolate, kScopeInfoOffset);
VerifyObjectField(isolate, kPreviousOffset);
VerifyObjectField(isolate, kExtensionOffset);
VerifyObjectField(isolate, kNativeContextOffset);
ClassVerifiersFromDSL::ContextVerify(*this, isolate);
for (int i = 0; i < length(); i++) {
VerifyObjectField(isolate, OffsetOfElementAt(i));
}
......@@ -804,6 +797,7 @@ void FeedbackMetadata::FeedbackMetadataVerify(Isolate* isolate) {
}
void DescriptorArray::DescriptorArrayVerify(Isolate* isolate) {
ClassVerifiersFromDSL::DescriptorArrayVerify(*this, isolate);
for (int i = 0; i < number_of_all_descriptors(); i++) {
MaybeObject::VerifyMaybeObjectPointer(isolate, get(ToKeyIndex(i)));
MaybeObject::VerifyMaybeObjectPointer(isolate, get(ToDetailsIndex(i)));
......@@ -852,6 +846,7 @@ void TransitionArray::TransitionArrayVerify(Isolate* isolate) {
}
void JSArgumentsObject::JSArgumentsObjectVerify(Isolate* isolate) {
ClassVerifiersFromDSL::JSArgumentsObjectVerify(*this, isolate);
if (IsSloppyArgumentsElementsKind(GetElementsKind())) {
SloppyArgumentsElements::cast(elements())
->SloppyArgumentsElementsVerify(isolate, *this);
......@@ -867,12 +862,11 @@ void JSArgumentsObject::JSArgumentsObjectVerify(Isolate* isolate) {
Context::STRICT_ARGUMENTS_MAP_INDEX)) {
VerifyObjectField(isolate, JSStrictArgumentsObject::kLengthOffset);
}
JSObjectVerify(isolate);
}
void SloppyArgumentsElements::SloppyArgumentsElementsVerify(Isolate* isolate,
JSObject holder) {
FixedArrayVerify(isolate);
ClassVerifiersFromDSL::SloppyArgumentsElementsVerify(*this, isolate);
// Abort verification if only partially initialized (can't use arguments()
// getter because it does FixedArray::cast()).
if (get(kArgumentsIndex)->IsUndefined(isolate)) return;
......@@ -924,54 +918,22 @@ void SloppyArgumentsElements::SloppyArgumentsElementsVerify(Isolate* isolate,
CHECK_LE(maxMappedIndex, arg_elements->length());
}
void JSGeneratorObject::JSGeneratorObjectVerify(Isolate* isolate) {
// In an expression like "new g()", there can be a point where a generator
// object is allocated but its fields are all undefined, as it hasn't yet been
// initialized by the generator. Hence these weak checks.
VerifyObjectField(isolate, kFunctionOffset);
VerifyObjectField(isolate, kContextOffset);
VerifyObjectField(isolate, kReceiverOffset);
VerifyObjectField(isolate, kParametersAndRegistersOffset);
VerifyObjectField(isolate, kContinuationOffset);
}
USE_TORQUE_VERIFIER(JSGeneratorObject)
void JSAsyncFunctionObject::JSAsyncFunctionObjectVerify(Isolate* isolate) {
// Check inherited fields
JSGeneratorObjectVerify(isolate);
VerifyObjectField(isolate, kPromiseOffset);
ClassVerifiersFromDSL::JSAsyncFunctionObjectVerify(*this, isolate);
promise()->HeapObjectVerify(isolate);
}
void JSAsyncGeneratorObject::JSAsyncGeneratorObjectVerify(Isolate* isolate) {
// Check inherited fields
JSGeneratorObjectVerify(isolate);
VerifyObjectField(isolate, kQueueOffset);
ClassVerifiersFromDSL::JSAsyncGeneratorObjectVerify(*this, isolate);
queue()->HeapObjectVerify(isolate);
}
void JSValue::JSValueVerify(Isolate* isolate) {
Object v = value();
if (v->IsHeapObject()) {
VerifyHeapPointer(isolate, v);
}
}
USE_TORQUE_VERIFIER(JSValue)
void JSDate::JSDateVerify(Isolate* isolate) {
if (value()->IsHeapObject()) {
VerifyHeapPointer(isolate, value());
}
CHECK(value()->IsUndefined(isolate) || value()->IsSmi() ||
value()->IsHeapNumber());
CHECK(year()->IsUndefined(isolate) || year()->IsSmi() || year()->IsNaN());
CHECK(month()->IsUndefined(isolate) || month()->IsSmi() || month()->IsNaN());
CHECK(day()->IsUndefined(isolate) || day()->IsSmi() || day()->IsNaN());
CHECK(weekday()->IsUndefined(isolate) || weekday()->IsSmi() ||
weekday()->IsNaN());
CHECK(hour()->IsUndefined(isolate) || hour()->IsSmi() || hour()->IsNaN());
CHECK(min()->IsUndefined(isolate) || min()->IsSmi() || min()->IsNaN());
CHECK(sec()->IsUndefined(isolate) || sec()->IsSmi() || sec()->IsNaN());
CHECK(cache_stamp()->IsUndefined(isolate) || cache_stamp()->IsSmi() ||
cache_stamp()->IsNaN());
ClassVerifiersFromDSL::JSDateVerify(*this, isolate);
if (month()->IsSmi()) {
int month = Smi::ToInt(this->month());
......@@ -1004,12 +966,7 @@ void JSDate::JSDateVerify(Isolate* isolate) {
}
void JSMessageObject::JSMessageObjectVerify(Isolate* isolate) {
CHECK(IsJSMessageObject());
VerifyObjectField(isolate, kStartPositionOffset);
VerifyObjectField(isolate, kEndPositionOffset);
VerifyObjectField(isolate, kArgumentsOffset);
VerifyObjectField(isolate, kScriptOffset);
VerifyObjectField(isolate, kStackFramesOffset);
ClassVerifiersFromDSL::JSMessageObjectVerify(*this, isolate);
VerifySmiField(kMessageTypeOffset);
VerifySmiField(kStartPositionOffset);
VerifySmiField(kEndPositionOffset);
......@@ -1017,25 +974,16 @@ void JSMessageObject::JSMessageObjectVerify(Isolate* isolate) {
}
void String::StringVerify(Isolate* isolate) {
CHECK(IsString());
ClassVerifiersFromDSL::StringVerify(*this, isolate);
CHECK(length() >= 0 && length() <= Smi::kMaxValue);
CHECK_IMPLIES(length() == 0, *this == ReadOnlyRoots(isolate).empty_string());
if (IsInternalizedString()) {
CHECK(!ObjectInYoungGeneration(*this));
}
if (IsConsString()) {
ConsString::cast(*this)->ConsStringVerify(isolate);
} else if (IsSlicedString()) {
SlicedString::cast(*this)->SlicedStringVerify(isolate);
} else if (IsThinString()) {
ThinString::cast(*this)->ThinStringVerify(isolate);
}
}
void ConsString::ConsStringVerify(Isolate* isolate) {
CHECK(this->first()->IsString());
CHECK(this->second() == ReadOnlyRoots(isolate).empty_string() ||
this->second()->IsString());
ClassVerifiersFromDSL::ConsStringVerify(*this, isolate);
CHECK_GE(this->length(), ConsString::kMinLength);
CHECK(this->length() == this->first()->length() + this->second()->length());
if (this->IsFlat()) {
......@@ -1047,22 +995,20 @@ void ConsString::ConsStringVerify(Isolate* isolate) {
}
void ThinString::ThinStringVerify(Isolate* isolate) {
ClassVerifiersFromDSL::ThinStringVerify(*this, isolate);
CHECK(this->actual()->IsInternalizedString());
CHECK(this->actual()->IsSeqString() || this->actual()->IsExternalString());
}
void SlicedString::SlicedStringVerify(Isolate* isolate) {
ClassVerifiersFromDSL::SlicedStringVerify(*this, isolate);
CHECK(!this->parent()->IsConsString());
CHECK(!this->parent()->IsSlicedString());
CHECK_GE(this->length(), SlicedString::kMinLength);
}
void JSBoundFunction::JSBoundFunctionVerify(Isolate* isolate) {
CHECK(IsJSBoundFunction());
JSObjectVerify(isolate);
VerifyObjectField(isolate, kBoundThisOffset);
VerifyObjectField(isolate, kBoundTargetFunctionOffset);
VerifyObjectField(isolate, kBoundArgumentsOffset);
ClassVerifiersFromDSL::JSBoundFunctionVerify(*this, isolate);
CHECK(IsCallable());
if (!raw_bound_target_function()->IsUndefined(isolate)) {
......@@ -1072,9 +1018,7 @@ void JSBoundFunction::JSBoundFunctionVerify(Isolate* isolate) {
}
void JSFunction::JSFunctionVerify(Isolate* isolate) {
CHECK(IsJSFunction());
JSObjectVerify(isolate);
VerifyHeapPointer(isolate, raw_feedback_cell());
ClassVerifiersFromDSL::JSFunctionVerify(*this, isolate);
CHECK(raw_feedback_cell()->IsFeedbackCell());
CHECK(code()->IsCode());
CHECK(map()->is_callable());
......@@ -1096,16 +1040,9 @@ void JSFunction::JSFunctionVerify(Isolate* isolate) {
}
void SharedFunctionInfo::SharedFunctionInfoVerify(Isolate* isolate) {
CHECK(IsSharedFunctionInfo());
VerifyObjectField(isolate, kFunctionDataOffset);
VerifyObjectField(isolate, kOuterScopeInfoOrFeedbackMetadataOffset);
VerifyObjectField(isolate, kScriptOrDebugInfoOffset);
VerifyObjectField(isolate, kNameOrScopeInfoOffset);
ClassVerifiersFromDSL::SharedFunctionInfoVerify(*this, isolate);
Object value = name_or_scope_info();
CHECK(value == kNoSharedNameSentinel || value->IsString() ||
value->IsScopeInfo());
if (value->IsScopeInfo()) {
CHECK_LT(0, ScopeInfo::cast(value)->length());
CHECK_NE(value, ReadOnlyRoots(isolate).empty_scope_info());
......@@ -1157,9 +1094,7 @@ void SharedFunctionInfo::SharedFunctionInfoVerify(Isolate* isolate) {
}
void JSGlobalProxy::JSGlobalProxyVerify(Isolate* isolate) {
CHECK(IsJSGlobalProxy());
JSObjectVerify(isolate);
VerifyObjectField(isolate, JSGlobalProxy::kNativeContextOffset);
ClassVerifiersFromDSL::JSGlobalProxyVerify(*this, isolate);
CHECK(map()->is_access_check_needed());
// Make sure that this object has no properties, elements.
CHECK_EQ(0, FixedArray::cast(elements())->length());
......@@ -1176,9 +1111,8 @@ void JSGlobalObject::JSGlobalObjectVerify(Isolate* isolate) {
}
void Oddball::OddballVerify(Isolate* isolate) {
CHECK(IsOddball());
ClassVerifiersFromDSL::OddballVerify(*this, isolate);
Heap* heap = isolate->heap();
VerifyHeapPointer(isolate, to_string());
Object number = to_number();
if (number->IsHeapObject()) {
CHECK(number == ReadOnlyRoots(heap).nan_value() ||
......@@ -1219,24 +1153,11 @@ void Oddball::OddballVerify(Isolate* isolate) {
} else {
UNREACHABLE();
}
CHECK(to_string()->IsString());
CHECK(type_of()->IsString());
}
void Cell::CellVerify(Isolate* isolate) {
CHECK(IsCell());
VerifyObjectField(isolate, kValueOffset);
}
USE_TORQUE_VERIFIER(Cell)
void PropertyCell::PropertyCellVerify(Isolate* isolate) {
CHECK(IsPropertyCell());
VerifyObjectField(isolate, kNameOffset);
CHECK(name()->IsName());
VerifySmiField(kPropertyDetailsRawOffset);
VerifyObjectField(isolate, kValueOffset);
VerifyObjectField(isolate, kDependentCodeOffset);
CHECK(dependent_code()->IsDependentCode());
}
USE_TORQUE_VERIFIER(PropertyCell)
void CodeDataContainer::CodeDataContainerVerify(Isolate* isolate) {
CHECK(IsCodeDataContainer());
......@@ -1269,8 +1190,7 @@ void Code::CodeVerify(Isolate* isolate) {
}
void JSArray::JSArrayVerify(Isolate* isolate) {
JSObjectVerify(isolate);
CHECK(length()->IsNumber() || length()->IsUndefined(isolate));
ClassVerifiersFromDSL::JSArrayVerify(*this, isolate);
// If a GC was caused while constructing this array, the elements
// pointer may point to a one pointer filler map.
if (!ElementsAreSafeToExamine()) return;
......@@ -1312,16 +1232,14 @@ void JSArray::JSArrayVerify(Isolate* isolate) {
}
void JSSet::JSSetVerify(Isolate* isolate) {
CHECK(IsJSSet());
JSObjectVerify(isolate);
ClassVerifiersFromDSL::JSSetVerify(*this, isolate);
VerifyHeapPointer(isolate, table());
CHECK(table()->IsOrderedHashSet() || table()->IsUndefined(isolate));
// TODO(arv): Verify OrderedHashTable too.
}
void JSMap::JSMapVerify(Isolate* isolate) {
CHECK(IsJSMap());
JSObjectVerify(isolate);
ClassVerifiersFromDSL::JSMapVerify(*this, isolate);
VerifyHeapPointer(isolate, table());
CHECK(table()->IsOrderedHashMap() || table()->IsUndefined(isolate));
// TODO(arv): Verify OrderedHashTable too.
......@@ -1411,15 +1329,13 @@ void FinalizationGroupCleanupJobTask::FinalizationGroupCleanupJobTaskVerify(
}
void JSWeakMap::JSWeakMapVerify(Isolate* isolate) {
CHECK(IsJSWeakMap());
JSObjectVerify(isolate);
ClassVerifiersFromDSL::JSWeakMapVerify(*this, isolate);
VerifyHeapPointer(isolate, table());
CHECK(table()->IsEphemeronHashTable() || table()->IsUndefined(isolate));
}
void JSArrayIterator::JSArrayIteratorVerify(Isolate* isolate) {
CHECK(IsJSArrayIterator());
JSObjectVerify(isolate);
ClassVerifiersFromDSL::JSArrayIteratorVerify(*this, isolate);
CHECK(iterated_object()->IsJSReceiver());
CHECK_GE(next_index()->Number(), 0);
......@@ -1436,116 +1352,48 @@ void JSArrayIterator::JSArrayIteratorVerify(Isolate* isolate) {
}
void JSStringIterator::JSStringIteratorVerify(Isolate* isolate) {
CHECK(IsJSStringIterator());
JSObjectVerify(isolate);
ClassVerifiersFromDSL::JSStringIteratorVerify(*this, isolate);
CHECK(string()->IsString());
CHECK_GE(index(), 0);
CHECK_LE(index(), String::kMaxLength);
}
void JSAsyncFromSyncIterator::JSAsyncFromSyncIteratorVerify(Isolate* isolate) {
CHECK(IsJSAsyncFromSyncIterator());
JSObjectVerify(isolate);
VerifyHeapPointer(isolate, sync_iterator());
}
USE_TORQUE_VERIFIER(JSAsyncFromSyncIterator)
void JSWeakSet::JSWeakSetVerify(Isolate* isolate) {
CHECK(IsJSWeakSet());
JSObjectVerify(isolate);
ClassVerifiersFromDSL::JSWeakSetVerify(*this, isolate);
VerifyHeapPointer(isolate, table());
CHECK(table()->IsEphemeronHashTable() || table()->IsUndefined(isolate));
}
void Microtask::MicrotaskVerify(Isolate* isolate) { CHECK(IsMicrotask()); }
USE_TORQUE_VERIFIER(Microtask)
void CallableTask::CallableTaskVerify(Isolate* isolate) {
CHECK(IsCallableTask());
MicrotaskVerify(isolate);
VerifyHeapPointer(isolate, callable());
ClassVerifiersFromDSL::CallableTaskVerify(*this, isolate);
CHECK(callable()->IsCallable());
VerifyHeapPointer(isolate, context());
CHECK(context()->IsContext());
}
void CallbackTask::CallbackTaskVerify(Isolate* isolate) {
CHECK(IsCallbackTask());
MicrotaskVerify(isolate);
VerifyHeapPointer(isolate, callback());
VerifyHeapPointer(isolate, data());
}
USE_TORQUE_VERIFIER(CallbackTask)
void PromiseReactionJobTask::PromiseReactionJobTaskVerify(Isolate* isolate) {
CHECK(IsPromiseReactionJobTask());
MicrotaskVerify(isolate);
VerifyPointer(isolate, argument());
VerifyHeapPointer(isolate, context());
CHECK(context()->IsContext());
ClassVerifiersFromDSL::PromiseReactionJobTaskVerify(*this, isolate);
VerifyHeapPointer(isolate, handler());
CHECK(handler()->IsUndefined(isolate) || handler()->IsCallable());
VerifyHeapPointer(isolate, promise_or_capability());
CHECK(promise_or_capability()->IsJSPromise() ||
promise_or_capability()->IsPromiseCapability() ||
promise_or_capability()->IsUndefined(isolate));
}
void PromiseFulfillReactionJobTask::PromiseFulfillReactionJobTaskVerify(
Isolate* isolate) {
CHECK(IsPromiseFulfillReactionJobTask());
PromiseReactionJobTaskVerify(isolate);
}
USE_TORQUE_VERIFIER(PromiseFulfillReactionJobTask)
void PromiseRejectReactionJobTask::PromiseRejectReactionJobTaskVerify(
Isolate* isolate) {
CHECK(IsPromiseRejectReactionJobTask());
PromiseReactionJobTaskVerify(isolate);
}
USE_TORQUE_VERIFIER(PromiseRejectReactionJobTask)
void PromiseResolveThenableJobTask::PromiseResolveThenableJobTaskVerify(
Isolate* isolate) {
CHECK(IsPromiseResolveThenableJobTask());
MicrotaskVerify(isolate);
VerifyHeapPointer(isolate, context());
CHECK(context()->IsContext());
VerifyHeapPointer(isolate, promise_to_resolve());
CHECK(promise_to_resolve()->IsJSPromise());
VerifyHeapPointer(isolate, then());
CHECK(then()->IsCallable());
CHECK(then()->IsJSReceiver());
VerifyHeapPointer(isolate, thenable());
CHECK(thenable()->IsJSReceiver());
}
void PromiseCapability::PromiseCapabilityVerify(Isolate* isolate) {
CHECK(IsPromiseCapability());
VerifyHeapPointer(isolate, promise());
CHECK(promise()->IsJSReceiver() || promise()->IsUndefined(isolate));
VerifyPointer(isolate, resolve());
VerifyPointer(isolate, reject());
}
void PromiseReaction::PromiseReactionVerify(Isolate* isolate) {
CHECK(IsPromiseReaction());
VerifyPointer(isolate, next());
CHECK(next()->IsSmi() || next()->IsPromiseReaction());
VerifyHeapPointer(isolate, reject_handler());
CHECK(reject_handler()->IsUndefined(isolate) ||
reject_handler()->IsCallable());
VerifyHeapPointer(isolate, fulfill_handler());
CHECK(fulfill_handler()->IsUndefined(isolate) ||
fulfill_handler()->IsCallable());
VerifyHeapPointer(isolate, promise_or_capability());
CHECK(promise_or_capability()->IsJSPromise() ||
promise_or_capability()->IsPromiseCapability() ||
promise_or_capability()->IsUndefined(isolate));
}
USE_TORQUE_VERIFIER(PromiseResolveThenableJobTask)
USE_TORQUE_VERIFIER(PromiseCapability)
USE_TORQUE_VERIFIER(PromiseReaction)
void JSPromise::JSPromiseVerify(Isolate* isolate) {
CHECK(IsJSPromise());
JSObjectVerify(isolate);
VerifyPointer(isolate, reactions_or_result());
ClassVerifiersFromDSL::JSPromiseVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
if (status() == Promise::kPending) {
CHECK(reactions()->IsSmi() || reactions()->IsPromiseReaction());
......@@ -1629,10 +1477,7 @@ void SmallOrderedNameDictionary::SmallOrderedNameDictionaryVerify(
}
void JSRegExp::JSRegExpVerify(Isolate* isolate) {
JSObjectVerify(isolate);
CHECK(data()->IsUndefined(isolate) || data()->IsFixedArray());
CHECK(source()->IsUndefined(isolate) || source()->IsString());
CHECK(flags()->IsUndefined() || flags()->IsSmi());
ClassVerifiersFromDSL::JSRegExpVerify(*this, isolate);
switch (TypeTag()) {
case JSRegExp::ATOM: {
FixedArray arr = FixedArray::cast(data());
......@@ -1667,18 +1512,14 @@ void JSRegExp::JSRegExpVerify(Isolate* isolate) {
}
void JSRegExpStringIterator::JSRegExpStringIteratorVerify(Isolate* isolate) {
CHECK(IsJSRegExpStringIterator());
JSObjectVerify(isolate);
ClassVerifiersFromDSL::JSRegExpStringIteratorVerify(*this, isolate);
CHECK(iterating_string()->IsString());
CHECK(iterating_regexp()->IsObject());
VerifySmiField(kFlagsOffset);
}
void JSProxy::JSProxyVerify(Isolate* isolate) {
CHECK(IsJSProxy());
ClassVerifiersFromDSL::JSProxyVerify(*this, isolate);
CHECK(map()->GetConstructor()->IsJSFunction());
VerifyPointer(isolate, target());
VerifyPointer(isolate, handler());
if (!IsRevoked()) {
CHECK_EQ(target()->IsCallable(), map()->is_callable());
CHECK_EQ(target()->IsConstructor(), map()->is_constructor());
......@@ -1689,48 +1530,33 @@ void JSProxy::JSProxyVerify(Isolate* isolate) {
}
void JSArrayBuffer::JSArrayBufferVerify(Isolate* isolate) {
CHECK(IsJSArrayBuffer());
ClassVerifiersFromDSL::JSArrayBufferVerify(*this, isolate);
if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
CHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
CHECK_EQ(0,
*reinterpret_cast<uint32_t*>(address() + kOptionalPaddingOffset));
}
JSObjectVerify(isolate);
}
void JSArrayBufferView::JSArrayBufferViewVerify(Isolate* isolate) {
CHECK(IsJSArrayBufferView());
JSObjectVerify(isolate);
VerifyPointer(isolate, buffer());
CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined(isolate) ||
buffer() == Smi::kZero);
ClassVerifiersFromDSL::JSArrayBufferViewVerify(*this, isolate);
CHECK_LE(byte_length(), JSArrayBuffer::kMaxByteLength);
CHECK_LE(byte_offset(), JSArrayBuffer::kMaxByteLength);
}
void JSTypedArray::JSTypedArrayVerify(Isolate* isolate) {
CHECK(IsJSTypedArray());
JSArrayBufferViewVerify(isolate);
VerifyPointer(isolate, raw_length());
CHECK(raw_length()->IsSmi() || raw_length()->IsUndefined(isolate));
ClassVerifiersFromDSL::JSTypedArrayVerify(*this, isolate);
VerifyPointer(isolate, elements());
}
void JSDataView::JSDataViewVerify(Isolate* isolate) {
CHECK(IsJSDataView());
JSArrayBufferViewVerify(isolate);
}
USE_TORQUE_VERIFIER(JSDataView)
void Foreign::ForeignVerify(Isolate* isolate) { CHECK(IsForeign()); }
USE_TORQUE_VERIFIER(Foreign)
void AsyncGeneratorRequest::AsyncGeneratorRequestVerify(Isolate* isolate) {
CHECK(IsAsyncGeneratorRequest());
VerifySmiField(kResumeModeOffset);
ClassVerifiersFromDSL::AsyncGeneratorRequestVerify(*this, isolate);
CHECK_GE(resume_mode(), JSGeneratorObject::kNext);
CHECK_LE(resume_mode(), JSGeneratorObject::kThrow);
CHECK(promise()->IsJSPromise());
VerifyPointer(isolate, value());
VerifyPointer(isolate, next());
next()->ObjectVerify(isolate);
}
......@@ -1746,17 +1572,7 @@ void JSModuleNamespace::JSModuleNamespaceVerify(Isolate* isolate) {
}
void ModuleInfoEntry::ModuleInfoEntryVerify(Isolate* isolate) {
CHECK(IsModuleInfoEntry());
CHECK(export_name()->IsUndefined(isolate) || export_name()->IsString());
CHECK(local_name()->IsUndefined(isolate) || local_name()->IsString());
CHECK(import_name()->IsUndefined(isolate) || import_name()->IsString());
VerifySmiField(kModuleRequestOffset);
VerifySmiField(kCellIndexOffset);
VerifySmiField(kBegPosOffset);
VerifySmiField(kEndPosOffset);
ClassVerifiersFromDSL::ModuleInfoEntryVerify(*this, isolate);
CHECK_IMPLIES(import_name()->IsString(), module_request() >= 0);
CHECK_IMPLIES(export_name()->IsString() && import_name()->IsString(),
local_name()->IsUndefined(isolate));
......@@ -1797,9 +1613,7 @@ void Module::ModuleVerify(Isolate* isolate) {
}
void PrototypeInfo::PrototypeInfoVerify(Isolate* isolate) {
CHECK(IsPrototypeInfo());
Object module_ns = module_namespace();
CHECK(module_ns->IsJSModuleNamespace() || module_ns->IsUndefined(isolate));
ClassVerifiersFromDSL::PrototypeInfoVerify(*this, isolate);
if (prototype_users()->IsWeakArrayList()) {
PrototypeUsers::Verify(WeakArrayList::cast(prototype_users()));
} else {
......@@ -1839,45 +1653,29 @@ void PrototypeUsers::Verify(WeakArrayList array) {
CHECK_EQ(weak_maps_count + empty_slots_count + 1, array->length());
}
void Tuple2::Tuple2Verify(Isolate* isolate) {
CHECK(IsTuple2());
VerifyObjectField(isolate, kValue1Offset);
VerifyObjectField(isolate, kValue2Offset);
}
USE_TORQUE_VERIFIER(Tuple2)
void EnumCache::EnumCacheVerify(Isolate* isolate) {
CHECK(IsEnumCache());
ClassVerifiersFromDSL::EnumCacheVerify(*this, isolate);
Heap* heap = isolate->heap();
if (*this == ReadOnlyRoots(heap).empty_enum_cache()) {
CHECK_EQ(ReadOnlyRoots(heap).empty_fixed_array(), keys());
CHECK_EQ(ReadOnlyRoots(heap).empty_fixed_array(), indices());
} else {
VerifyObjectField(isolate, kKeysOffset);
VerifyObjectField(isolate, kIndicesOffset);
CHECK(keys()->IsFixedArray());
CHECK(indices()->IsFixedArray());
}
}
void SourcePositionTableWithFrameCache::SourcePositionTableWithFrameCacheVerify(
Isolate* isolate) {
VerifyObjectField(isolate, kSourcePositionTableOffset);
VerifyObjectField(isolate, kStackFrameCacheOffset);
CHECK(source_position_table()->IsByteArray());
}
USE_TORQUE_VERIFIER(SourcePositionTableWithFrameCache)
void Tuple3::Tuple3Verify(Isolate* isolate) {
// Not using the Torque-generated verifier because IsTuple2 incorrectly
// returns false for instances of Tuple3.
CHECK(IsTuple3());
VerifyObjectField(isolate, kValue1Offset);
VerifyObjectField(isolate, kValue2Offset);
VerifyObjectField(isolate, kValue3Offset);
}
void ClassPositions::ClassPositionsVerify(Isolate* isolate) {
CHECK(IsClassPositions());
VerifySmiField(kStartOffset);
VerifySmiField(kEndOffset);
}
USE_TORQUE_VERIFIER(ClassPositions)
void ObjectBoilerplateDescription::ObjectBoilerplateDescriptionVerify(
Isolate* isolate) {
......@@ -1887,41 +1685,13 @@ void ObjectBoilerplateDescription::ObjectBoilerplateDescriptionVerify(
this->FixedArrayVerify(isolate);
}
void ArrayBoilerplateDescription::ArrayBoilerplateDescriptionVerify(
Isolate* isolate) {
CHECK(IsArrayBoilerplateDescription());
CHECK(constant_elements()->IsFixedArrayBase());
VerifyObjectField(isolate, kConstantElementsOffset);
}
USE_TORQUE_VERIFIER(ArrayBoilerplateDescription)
void AsmWasmData::AsmWasmDataVerify(Isolate* isolate) {
CHECK(IsAsmWasmData());
CHECK(managed_native_module()->IsForeign());
VerifyObjectField(isolate, kManagedNativeModuleOffset);
CHECK(export_wrappers()->IsFixedArray());
VerifyObjectField(isolate, kExportWrappersOffset);
CHECK(asm_js_offset_table()->IsByteArray());
VerifyObjectField(isolate, kAsmJsOffsetTableOffset);
CHECK(uses_bitset()->IsHeapNumber());
VerifyObjectField(isolate, kUsesBitsetOffset);
}
USE_TORQUE_VERIFIER(AsmWasmData)
void WasmDebugInfo::WasmDebugInfoVerify(Isolate* isolate) {
CHECK(IsWasmDebugInfo());
VerifyObjectField(isolate, kInstanceOffset);
CHECK(wasm_instance()->IsWasmInstanceObject());
VerifyObjectField(isolate, kInterpreterHandleOffset);
CHECK(interpreter_handle()->IsUndefined(isolate) ||
interpreter_handle()->IsForeign());
VerifyObjectField(isolate, kLocalsNamesOffset);
VerifyObjectField(isolate, kCWasmEntriesOffset);
VerifyObjectField(isolate, kCWasmEntryMapOffset);
}
USE_TORQUE_VERIFIER(WasmDebugInfo)
void WasmExceptionTag::WasmExceptionTagVerify(Isolate* isolate) {
CHECK(IsWasmExceptionTag());
VerifySmiField(kIndexOffset);
}
USE_TORQUE_VERIFIER(WasmExceptionTag)
void WasmInstanceObject::WasmInstanceObjectVerify(Isolate* isolate) {
JSObjectVerify(isolate);
......@@ -1938,69 +1708,41 @@ void WasmInstanceObject::WasmInstanceObjectVerify(Isolate* isolate) {
void WasmExportedFunctionData::WasmExportedFunctionDataVerify(
Isolate* isolate) {
CHECK(IsWasmExportedFunctionData());
VerifyObjectField(isolate, kWrapperCodeOffset);
ClassVerifiersFromDSL::WasmExportedFunctionDataVerify(*this, isolate);
CHECK(wrapper_code()->kind() == Code::JS_TO_WASM_FUNCTION ||
wrapper_code()->kind() == Code::C_WASM_ENTRY);
VerifyObjectField(isolate, kInstanceOffset);
CHECK(instance()->IsWasmInstanceObject());
VerifySmiField(kJumpTableOffsetOffset);
VerifySmiField(kFunctionIndexOffset);
}
void WasmModuleObject::WasmModuleObjectVerify(Isolate* isolate) {
CHECK(IsWasmModuleObject());
VerifyObjectField(isolate, kNativeModuleOffset);
ClassVerifiersFromDSL::WasmModuleObjectVerify(*this, isolate);
CHECK(managed_native_module()->IsForeign());
VerifyObjectField(isolate, kExportWrappersOffset);
CHECK(export_wrappers()->IsFixedArray());
VerifyObjectField(isolate, kScriptOffset);
CHECK(script()->IsScript());
VerifyObjectField(isolate, kWeakInstanceListOffset);
VerifyObjectField(isolate, kAsmJsOffsetTableOffset);
VerifyObjectField(isolate, kBreakPointInfosOffset);
}
void WasmTableObject::WasmTableObjectVerify(Isolate* isolate) {
CHECK(IsWasmTableObject());
VerifyObjectField(isolate, kElementsOffset);
ClassVerifiersFromDSL::WasmTableObjectVerify(*this, isolate);
CHECK(elements()->IsFixedArray());
VerifyObjectField(isolate, kMaximumLengthOffset);
CHECK(maximum_length()->IsSmi() || maximum_length()->IsHeapNumber() ||
maximum_length()->IsUndefined(isolate));
VerifyObjectField(isolate, kDispatchTablesOffset);
VerifySmiField(kRawTypeOffset);
}
void WasmMemoryObject::WasmMemoryObjectVerify(Isolate* isolate) {
CHECK(IsWasmMemoryObject());
VerifyObjectField(isolate, kArrayBufferOffset);
ClassVerifiersFromDSL::WasmMemoryObjectVerify(*this, isolate);
CHECK(array_buffer()->IsJSArrayBuffer());
VerifySmiField(kMaximumPagesOffset);
VerifyObjectField(isolate, kInstancesOffset);
}
void WasmGlobalObject::WasmGlobalObjectVerify(Isolate* isolate) {
CHECK(IsWasmGlobalObject());
VerifyObjectField(isolate, kUntaggedBufferOffset);
VerifyObjectField(isolate, kTaggedBufferOffset);
VerifyObjectField(isolate, kOffsetOffset);
VerifyObjectField(isolate, kFlagsOffset);
}
USE_TORQUE_VERIFIER(WasmGlobalObject)
void WasmExceptionObject::WasmExceptionObjectVerify(Isolate* isolate) {
CHECK(IsWasmExceptionObject());
VerifyObjectField(isolate, kSerializedSignatureOffset);
ClassVerifiersFromDSL::WasmExceptionObjectVerify(*this, isolate);
CHECK(serialized_signature()->IsByteArray());
VerifyObjectField(isolate, kExceptionTagOffset);
CHECK(exception_tag()->IsHeapObject());
}
void DataHandler::DataHandlerVerify(Isolate* isolate) {
CHECK(IsDataHandler());
ClassVerifiersFromDSL::DataHandlerVerify(*this, isolate);
CHECK_IMPLIES(!smi_handler()->IsSmi(),
smi_handler()->IsCode() && IsStoreHandler());
CHECK(validity_cell()->IsSmi() || validity_cell()->IsCell());
int data_count = data_field_count();
if (data_count >= 1) {
VerifyMaybeObjectField(isolate, kData1Offset);
......@@ -2024,28 +1766,15 @@ void StoreHandler::StoreHandlerVerify(Isolate* isolate) {
}
void AccessorInfo::AccessorInfoVerify(Isolate* isolate) {
CHECK(IsAccessorInfo());
VerifyPointer(isolate, name());
VerifyPointer(isolate, expected_receiver_type());
ClassVerifiersFromDSL::AccessorInfoVerify(*this, isolate);
VerifyForeignPointer(isolate, *this, getter());
VerifyForeignPointer(isolate, *this, setter());
VerifyForeignPointer(isolate, *this, js_getter());
VerifyPointer(isolate, data());
}
void AccessorPair::AccessorPairVerify(Isolate* isolate) {
CHECK(IsAccessorPair());
VerifyPointer(isolate, getter());
VerifyPointer(isolate, setter());
}
USE_TORQUE_VERIFIER(AccessorPair)
void AccessCheckInfo::AccessCheckInfoVerify(Isolate* isolate) {
CHECK(IsAccessCheckInfo());
VerifyPointer(isolate, callback());
VerifyPointer(isolate, named_interceptor());
VerifyPointer(isolate, indexed_interceptor());
VerifyPointer(isolate, data());
}
USE_TORQUE_VERIFIER(AccessCheckInfo)
void CallHandlerInfo::CallHandlerInfoVerify(Isolate* isolate) {
CHECK(IsCallHandlerInfo());
......@@ -2060,55 +1789,25 @@ void CallHandlerInfo::CallHandlerInfoVerify(Isolate* isolate) {
}
void InterceptorInfo::InterceptorInfoVerify(Isolate* isolate) {
CHECK(IsInterceptorInfo());
ClassVerifiersFromDSL::InterceptorInfoVerify(*this, isolate);
VerifyForeignPointer(isolate, *this, getter());
VerifyForeignPointer(isolate, *this, setter());
VerifyForeignPointer(isolate, *this, query());
VerifyForeignPointer(isolate, *this, descriptor());
VerifyForeignPointer(isolate, *this, deleter());
VerifyForeignPointer(isolate, *this, enumerator());
VerifyPointer(isolate, data());
VerifySmiField(kFlagsOffset);
VerifyForeignPointer(isolate, *this, definer());
}
void TemplateInfo::TemplateInfoVerify(Isolate* isolate) {
VerifyPointer(isolate, tag());
VerifyPointer(isolate, property_list());
VerifyPointer(isolate, property_accessors());
}
USE_TORQUE_VERIFIER(TemplateInfo)
void FunctionTemplateInfo::FunctionTemplateInfoVerify(Isolate* isolate) {
CHECK(IsFunctionTemplateInfo());
TemplateInfoVerify(isolate);
VerifyPointer(isolate, serial_number());
VerifyPointer(isolate, call_code());
VerifyPointer(isolate, signature());
VerifyPointer(isolate, cached_property_name());
VerifyPointer(isolate, rare_data());
}
USE_TORQUE_VERIFIER(FunctionTemplateInfo)
void FunctionTemplateRareData::FunctionTemplateRareDataVerify(
Isolate* isolate) {
CHECK(IsFunctionTemplateRareData());
VerifyPointer(isolate, prototype_template());
VerifyPointer(isolate, parent_template());
VerifyPointer(isolate, named_property_handler());
VerifyPointer(isolate, indexed_property_handler());
VerifyPointer(isolate, instance_template());
VerifyPointer(isolate, access_check_info());
}
USE_TORQUE_VERIFIER(FunctionTemplateRareData)
void WasmCapiFunctionData::WasmCapiFunctionDataVerify(Isolate* isolate) {
CHECK(IsWasmCapiFunctionData());
VerifyPointer(isolate, wrapper_code());
VerifyPointer(isolate, serialized_signature());
}
USE_TORQUE_VERIFIER(WasmCapiFunctionData)
void ObjectTemplateInfo::ObjectTemplateInfoVerify(Isolate* isolate) {
CHECK(IsObjectTemplateInfo());
TemplateInfoVerify(isolate);
VerifyPointer(isolate, constructor());
VerifyPointer(isolate, data());
}
USE_TORQUE_VERIFIER(ObjectTemplateInfo)
void AllocationSite::AllocationSiteVerify(Isolate* isolate) {
CHECK(IsAllocationSite());
......@@ -2119,16 +1818,13 @@ void AllocationSite::AllocationSiteVerify(Isolate* isolate) {
}
void AllocationMemento::AllocationMementoVerify(Isolate* isolate) {
CHECK(IsAllocationMemento());
ClassVerifiersFromDSL::AllocationMementoVerify(*this, isolate);
VerifyHeapPointer(isolate, allocation_site());
CHECK(!IsValid() || GetAllocationSite()->IsAllocationSite());
}
void Script::ScriptVerify(Isolate* isolate) {
CHECK(IsScript());
VerifyPointer(isolate, source());
VerifyPointer(isolate, name());
VerifyPointer(isolate, line_ends());
ClassVerifiersFromDSL::ScriptVerify(*this, isolate);
for (int i = 0; i < shared_function_infos()->length(); ++i) {
MaybeObject maybe_object = shared_function_infos()->Get(i);
HeapObject heap_object;
......@@ -2136,12 +1832,6 @@ void Script::ScriptVerify(Isolate* isolate) {
(maybe_object->GetHeapObjectIfStrong(&heap_object) &&
heap_object->IsUndefined(isolate)));
}
VerifySmiField(kIdOffset);
VerifySmiField(kLineOffsetOffset);
VerifySmiField(kColumnOffsetOffset);
VerifySmiField(kScriptTypeOffset);
VerifySmiField(kEvalFromPositionOffset);
VerifySmiField(kFlagsOffset);
}
void NormalizedMapCache::NormalizedMapCacheVerify(Isolate* isolate) {
......@@ -2160,36 +1850,14 @@ void NormalizedMapCache::NormalizedMapCacheVerify(Isolate* isolate) {
}
}
void DebugInfo::DebugInfoVerify(Isolate* isolate) {
CHECK(IsDebugInfo());
VerifySmiField(kFlagsOffset);
VerifySmiField(kDebuggerHintsOffset);
CHECK(shared()->IsSharedFunctionInfo());
CHECK(script()->IsUndefined(isolate) || script()->IsScript());
CHECK(original_bytecode_array()->IsUndefined(isolate) ||
original_bytecode_array()->IsBytecodeArray());
CHECK(debug_bytecode_array()->IsUndefined(isolate) ||
debug_bytecode_array()->IsBytecodeArray());
CHECK(break_points()->IsFixedArray());
}
USE_TORQUE_VERIFIER(DebugInfo)
void StackTraceFrame::StackTraceFrameVerify(Isolate* isolate) {
CHECK(IsStackTraceFrame());
VerifySmiField(kFrameIndexOffset);
VerifySmiField(kIdOffset);
VerifyPointer(isolate, frame_array());
VerifyPointer(isolate, frame_info());
}
USE_TORQUE_VERIFIER(StackTraceFrame)
void StackFrameInfo::StackFrameInfoVerify(Isolate* isolate) {
CHECK(IsStackFrameInfo());
VerifyPointer(isolate, script_name());
VerifyPointer(isolate, script_name_or_source_url());
VerifyPointer(isolate, function_name());
}
USE_TORQUE_VERIFIER(StackFrameInfo)
void PreparseData::PreparseDataVerify(Isolate* isolate) {
CHECK(IsPreparseData());
ClassVerifiersFromDSL::PreparseDataVerify(*this, isolate);
CHECK_LE(0, data_length());
CHECK_LE(0, children_length());
......@@ -2213,13 +1881,7 @@ void UncompiledDataWithoutPreparseData::UncompiledDataWithoutPreparseDataVerify(
VerifyPointer(isolate, inferred_name());
}
void InterpreterData::InterpreterDataVerify(Isolate* isolate) {
CHECK(IsInterpreterData());
VerifyObjectField(isolate, kBytecodeArrayOffset);
CHECK(bytecode_array()->IsBytecodeArray());
VerifyObjectField(isolate, kInterpreterTrampolineOffset);
CHECK(interpreter_trampoline()->IsCode());
}
USE_TORQUE_VERIFIER(InterpreterData)
#ifdef V8_INTL_SUPPORT
void JSV8BreakIterator::JSV8BreakIteratorVerify(Isolate* isolate) {
......@@ -2243,66 +1905,42 @@ void JSCollator::JSCollatorVerify(Isolate* isolate) {
}
void JSDateTimeFormat::JSDateTimeFormatVerify(Isolate* isolate) {
JSObjectVerify(isolate);
VerifyObjectField(isolate, kIcuLocaleOffset);
VerifyObjectField(isolate, kIcuSimpleDateFormatOffset);
VerifyObjectField(isolate, kIcuDateIntervalFormatOffset);
ClassVerifiersFromDSL::JSDateTimeFormatVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
VerifyObjectField(isolate, kBoundFormatOffset);
CHECK(bound_format()->IsUndefined(isolate) || bound_format()->IsJSFunction());
}
void JSListFormat::JSListFormatVerify(Isolate* isolate) {
JSObjectVerify(isolate);
VerifyObjectField(isolate, kLocaleOffset);
VerifyObjectField(isolate, kIcuFormatterOffset);
ClassVerifiersFromDSL::JSListFormatVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
}
void JSLocale::JSLocaleVerify(Isolate* isolate) {
JSObjectVerify(isolate);
VerifyObjectField(isolate, kIcuLocaleOffset);
}
USE_TORQUE_VERIFIER(JSLocale)
void JSNumberFormat::JSNumberFormatVerify(Isolate* isolate) {
CHECK(IsJSNumberFormat());
JSObjectVerify(isolate);
VerifyObjectField(isolate, kLocaleOffset);
VerifyObjectField(isolate, kIcuNumberFormatterOffset);
VerifyObjectField(isolate, kBoundFormatOffset);
CHECK(bound_format()->IsUndefined(isolate) || bound_format()->IsJSFunction());
ClassVerifiersFromDSL::JSNumberFormatVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
}
void JSPluralRules::JSPluralRulesVerify(Isolate* isolate) {
CHECK(IsJSPluralRules());
JSObjectVerify(isolate);
VerifyObjectField(isolate, kLocaleOffset);
ClassVerifiersFromDSL::JSPluralRulesVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
VerifyObjectField(isolate, kIcuPluralRulesOffset);
VerifyObjectField(isolate, kIcuDecimalFormatOffset);
}
void JSRelativeTimeFormat::JSRelativeTimeFormatVerify(Isolate* isolate) {
JSObjectVerify(isolate);
VerifyObjectField(isolate, kLocaleOffset);
VerifyObjectField(isolate, kIcuFormatterOffset);
ClassVerifiersFromDSL::JSRelativeTimeFormatVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
}
void JSSegmentIterator::JSSegmentIteratorVerify(Isolate* isolate) {
JSObjectVerify(isolate);
VerifyObjectField(isolate, kIcuBreakIteratorOffset);
VerifyObjectField(isolate, kUnicodeStringOffset);
ClassVerifiersFromDSL::JSSegmentIteratorVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
}
void JSSegmenter::JSSegmenterVerify(Isolate* isolate) {
JSObjectVerify(isolate);
VerifyObjectField(isolate, kLocaleOffset);
VerifyObjectField(isolate, kIcuBreakIteratorOffset);
ClassVerifiersFromDSL::JSSegmenterVerify(*this, isolate);
VerifySmiField(kFlagsOffset);
}
#endif // V8_INTL_SUPPORT
#endif // VERIFY_HEAP
......@@ -2494,6 +2132,8 @@ bool TransitionsAccessor::IsConsistentWithBackPointers() {
return true;
}
#undef USE_TORQUE_VERIFIER
#endif // DEBUG
} // namespace internal
......
......@@ -121,6 +121,12 @@ bool Object::IsNullOrUndefined() const {
return IsHeapObject() && HeapObject::cast(*this)->IsNullOrUndefined();
}
bool Object::IsZero() const { return *this == Smi::zero(); }
bool Object::IsNoSharedNameSentinel() const {
return *this == SharedFunctionInfo::kNoSharedNameSentinel;
}
bool HeapObject::IsNullOrUndefined(Isolate* isolate) const {
return Object::IsNullOrUndefined(isolate);
}
......
......@@ -306,6 +306,9 @@ class Object {
V8_INLINE bool IsNullOrUndefined(ReadOnlyRoots roots) const;
V8_INLINE bool IsNullOrUndefined() const;
V8_INLINE bool IsZero() const;
V8_INLINE bool IsNoSharedNameSentinel() const;
enum class Conversion { kToNumber, kToNumeric };
#define DECL_STRUCT_PREDICATE(NAME, Name, name) V8_INLINE bool Is##Name() const;
......
......@@ -201,6 +201,8 @@ class FixedArray : public FixedArrayBase {
using BodyDescriptor = FlexibleBodyDescriptor<kHeaderSize>;
static constexpr int kObjectsOffset = kHeaderSize;
protected:
// Set operation on FixedArray without using write barriers. Can
// only be used for storing old space objects or smis.
......
......@@ -721,6 +721,7 @@ struct ClassFieldExpression {
base::Optional<std::string> conditional;
bool weak;
bool const_qualified;
bool generate_verify;
};
struct LabelAndTypes {
......@@ -924,7 +925,7 @@ struct StructDeclaration : TypeDeclaration {
struct ClassDeclaration : TypeDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassDeclaration)
ClassDeclaration(SourcePosition pos, Identifier* name, bool is_extern,
bool generate_print, bool transient,
bool generate_print, bool generate_verify, bool transient,
base::Optional<TypeExpression*> super,
base::Optional<std::string> generates,
std::vector<Declaration*> methods,
......@@ -932,6 +933,7 @@ struct ClassDeclaration : TypeDeclaration {
: TypeDeclaration(kKind, pos, name),
is_extern(is_extern),
generate_print(generate_print),
generate_verify(generate_verify),
transient(transient),
super(super),
generates(std::move(generates)),
......@@ -939,6 +941,7 @@ struct ClassDeclaration : TypeDeclaration {
fields(std::move(fields)) {}
bool is_extern;
bool generate_print;
bool generate_verify;
bool transient;
base::Optional<TypeExpression*> super;
base::Optional<std::string> generates;
......
......@@ -2965,6 +2965,179 @@ void ImplementationVisitor::GeneratePrintDefinitions(std::string& file_name) {
ReplaceFileContentsIfDifferent(file_name, new_contents);
}
namespace {
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.
if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) return;
if (f.index) {
if ((*f.index)->name_and_type.type != TypeOracle::GetSmiType()) {
ReportError("Non-SMI values are not (yet) supported as indexes.");
}
// We already verified the index field because it was listed earlier, so we
// can assume it's safe to read here.
cc_contents << " for (int i = 0; i < Smi::ToInt(READ_FIELD(o, "
<< class_name << "::k"
<< CamelifyString((*f.index)->name_and_type.name)
<< "Offset)); ++i) {\n";
} else {
cc_contents << " {\n";
}
const char* object_type = f.is_weak ? "MaybeObject" : "Object";
const char* read_fn = f.is_weak ? "READ_WEAK_FIELD" : "READ_FIELD";
const char* verify_fn =
f.is_weak ? "VerifyMaybeObjectPointer" : "VerifyPointer";
const char* index_offset = f.index ? " + i * kTaggedSize" : "";
// Name the local var based on the field name for nicer CHECK output.
const std::string value = f.name_and_type.name + "_value";
// Read the field.
cc_contents << " " << object_type << " " << value << " = " << read_fn
<< "(o, " << class_name << "::k"
<< CamelifyString(f.name_and_type.name) << "Offset"
<< index_offset << ");\n";
// Call VerifyPointer or VerifyMaybeObjectPointer on it.
cc_contents << " " << object_type << "::" << verify_fn << "(isolate, "
<< value << ");\n";
// Check that the value is of an appropriate type. We can skip this part for
// the Object type because it would not check anything beyond what we already
// checked with VerifyPointer.
if (f.name_and_type.type != TypeOracle::GetObjectType()) {
std::string type_check = f.is_weak ? value + ".IsWeakOrCleared()" : "";
std::string strong_value =
value + (f.is_weak ? ".GetHeapObjectOrSmi()" : "");
for (const std::string& runtime_type : field_type->GetRuntimeTypes()) {
if (!type_check.empty()) type_check += " || ";
type_check += strong_value + ".Is" + runtime_type + "()";
}
// Many subtypes of JSObject can be verified in partially-initialized states
// where their fields are all undefined. We explicitly allow that here. For
// any such fields that should never be undefined, we can include extra code
// in the custom verifier functions for them.
// TODO(1240798): If Factory::InitializeJSObjectFromMap is updated to use
// correct initial values based on the type of the field, then make this
// check stricter too.
if (class_type.IsSubtypeOf(TypeOracle::GetJSObjectType())) {
type_check += " || " + strong_value + ".IsUndefined(isolate)";
}
cc_contents << " CHECK(" << type_check << ");\n";
}
cc_contents << " }\n";
}
} // namespace
void ImplementationVisitor::GenerateClassVerifiers(
const std::string& output_directory) {
const char* file_name = "class-verifiers-from-dsl";
std::stringstream h_contents;
std::stringstream cc_contents;
h_contents << "#ifndef V8_CLASS_VERIFIERS_FROM_DSL_H_\n"
"#define V8_CLASS_VERIFIERS_FROM_DSL_H_\n"
"\n";
const char* enabled_check = "\n#ifdef VERIFY_HEAP\n";
h_contents << enabled_check;
cc_contents << enabled_check;
h_contents << "\n#include \"src/objects.h\"\n";
for (const std::string& include_path : GlobalContext::CppIncludes()) {
cc_contents << "#include " << StringLiteralQuote(include_path) << "\n";
}
cc_contents << "#include \"torque-generated/" << file_name << ".h\"\n";
cc_contents
<< "\n// Has to be the last include (doesn't have include guards):\n"
"#include \"src/objects/object-macros.h\"\n";
const char* namespaces =
"\nnamespace v8 {\n"
"namespace internal {\n"
"\n";
h_contents << namespaces;
cc_contents << namespaces;
const char* verifier_class = "ClassVerifiersFromDSL";
h_contents << "class " << verifier_class << "{\n";
h_contents << " public:\n";
for (auto i : GlobalContext::GetClasses()) {
ClassType* type = i.second;
if (!type->IsExtern() || !type->ShouldGenerateVerify()) continue;
std::string method_name = i.first + "Verify";
h_contents << " static void " << method_name << "(" << i.first
<< " o, Isolate* isolate);\n";
cc_contents << "void " << verifier_class << "::" << method_name << "("
<< i.first << " o, Isolate* isolate) {\n";
// First, do any verification for the super class. Not all classes have
// verifiers, so skip to the nearest super class that has one.
const ClassType* super_type = type->GetSuperClass();
while (super_type && !super_type->ShouldGenerateVerify()) {
super_type = super_type->GetSuperClass();
}
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";
}
}
// Second, verify that this object is what it claims to be.
cc_contents << " CHECK(o.Is" << i.first << "());\n";
// Third, verify its properties.
for (auto f : type->fields()) {
GenerateClassFieldVerifier(i.first, *i.second, f, h_contents,
cc_contents);
}
cc_contents << "}\n";
}
h_contents << "};\n";
const char* end_namespaces =
"\n} // namespace internal\n"
"} // namespace v8\n";
h_contents << end_namespaces;
cc_contents << end_namespaces;
cc_contents << "\n#include \"src/objects/object-macros-undef.h\"\n";
const char* end_enabled_check = "\n#endif // VERIFY_HEAP\n";
h_contents << end_enabled_check;
cc_contents << end_enabled_check;
h_contents << "\n#endif // V8_CLASS_VERIFIERS_FROM_DSL_H_\n";
ReplaceFileContentsIfDifferent(output_directory + "/" + file_name + ".h",
h_contents.str());
ReplaceFileContentsIfDifferent(output_directory + "/" + file_name + ".cc",
cc_contents.str());
}
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -278,6 +278,7 @@ class ImplementationVisitor {
void GenerateBuiltinDefinitions(std::string& file_name);
void GenerateClassDefinitions(std::string& file_name);
void GeneratePrintDefinitions(std::string& file_name);
void GenerateClassVerifiers(const std::string& output_directory);
VisitResult Visit(Expression* expr);
const Type* Visit(Statement* stmt);
......
......@@ -88,6 +88,8 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
output_directory + "/objects-printer-from-dsl.cc";
implementation_visitor.GeneratePrintDefinitions(output_source_path);
implementation_visitor.GenerateClassVerifiers(output_directory);
for (Namespace* n : GlobalContext::Get().GetNamespaces()) {
implementation_visitor.EndNamespaceFile(n);
implementation_visitor.GenerateImplementation(output_directory, n);
......
......@@ -656,8 +656,9 @@ class AnnotationSet {
base::Optional<ParseResult> MakeClassDeclaration(
ParseResultIterator* child_results) {
AnnotationSet annotations(child_results, {"@generatePrint"});
AnnotationSet annotations(child_results, {"@generatePrint", "@noVerifier"});
bool generate_print = annotations.Contains("@generatePrint");
bool generate_verify = !annotations.Contains("@noVerifier");
auto is_extern = child_results->NextAs<bool>();
auto transient = child_results->NextAs<bool>();
auto name = child_results->NextAs<Identifier*>();
......@@ -681,8 +682,8 @@ base::Optional<ParseResult> MakeClassDeclaration(
});
Declaration* result = MakeNode<ClassDeclaration>(
name, is_extern, generate_print, transient, std::move(extends),
std::move(generates), std::move(methods), fields);
name, is_extern, generate_print, generate_verify, transient,
std::move(extends), std::move(generates), std::move(methods), fields);
return ParseResult{result};
}
......@@ -1258,13 +1259,19 @@ base::Optional<ParseResult> MakeNameAndExpressionFromExpression(
base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) {
auto conditional = child_results->NextAs<base::Optional<std::string>>();
AnnotationSet annotations(child_results, {"@noVerifier"});
bool generate_verify = !annotations.Contains("@noVerifier");
auto weak = child_results->NextAs<bool>();
auto const_qualified = child_results->NextAs<bool>();
auto name = child_results->NextAs<Identifier*>();
auto index = child_results->NextAs<base::Optional<std::string>>();
auto type = child_results->NextAs<TypeExpression*>();
return ParseResult{ClassFieldExpression{
{name, type}, index, conditional, weak, const_qualified}};
return ParseResult{ClassFieldExpression{{name, type},
index,
conditional,
weak,
const_qualified,
generate_verify}};
}
base::Optional<ParseResult> MakeStructField(
......@@ -1484,7 +1491,7 @@ struct TorqueGrammar : Grammar {
Symbol classField = {Rule(
{Optional<std::string>(
Sequence({Token("@ifdef"), Token("("), &identifier, Token(")")})),
CheckIf(Token("weak")), CheckIf(Token("const")), &name,
annotations, CheckIf(Token("weak")), CheckIf(Token("const")), &name,
optionalArraySpecifier, Token(":"), &type, Token(";")},
MakeClassField)};
......
......@@ -35,12 +35,13 @@ class TypeOracle : public ContextualClass<TypeOracle> {
static ClassType* GetClassType(const Type* parent, const std::string& name,
bool is_extern, bool generate_print,
bool transient, const std::string& generates,
bool generate_verify, bool transient,
const std::string& generates,
ClassDeclaration* decl,
const TypeAlias* alias) {
ClassType* result =
new ClassType(parent, CurrentNamespace(), name, is_extern,
generate_print, transient, generates, decl, alias);
ClassType* result = new ClassType(
parent, CurrentNamespace(), name, is_extern, generate_print,
generate_verify, transient, generates, decl, alias);
Get().struct_types_.push_back(std::unique_ptr<ClassType>(result));
return result;
}
......
......@@ -116,7 +116,8 @@ const StructType* TypeVisitor::ComputeType(StructDeclaration* decl) {
{field.name_and_type.name->value, field_type},
offset,
false,
field.const_qualified});
field.const_qualified,
false});
offset += LoweredSlotCount(field_type);
}
DeclareMethods(struct_type, decl->methods);
......@@ -151,7 +152,7 @@ const ClassType* TypeVisitor::ComputeType(ClassDeclaration* decl) {
new_class = TypeOracle::GetClassType(
super_type, decl->name->value, decl->is_extern, decl->generate_print,
decl->transient, generates, decl, alias);
decl->generate_verify, decl->transient, generates, decl, alias);
} else {
if (decl->super) {
ReportError("Only extern classes can inherit.");
......@@ -161,7 +162,8 @@ const ClassType* TypeVisitor::ComputeType(ClassDeclaration* decl) {
}
new_class = TypeOracle::GetClassType(
TypeOracle::GetTaggedType(), decl->name->value, decl->is_extern,
decl->generate_print, decl->transient, "FixedArray", decl, alias);
decl->generate_print, decl->generate_verify, decl->transient,
"FixedArray", decl, alias);
}
GlobalContext::RegisterClass(decl->name->value, new_class);
return new_class;
......@@ -248,7 +250,8 @@ void TypeVisitor::VisitClassFieldsAndMethods(
{field_expression.name_and_type.name->value, field_type},
class_offset,
field_expression.weak,
field_expression.const_qualified});
field_expression.const_qualified,
field_expression.generate_verify});
} else {
if (seen_indexed_field) {
ReportError("cannot declare non-indexable field \"",
......@@ -263,7 +266,8 @@ void TypeVisitor::VisitClassFieldsAndMethods(
{field_expression.name_and_type.name->value, field_type},
class_offset,
field_expression.weak,
field_expression.const_qualified});
field_expression.const_qualified,
field_expression.generate_verify});
size_t field_size;
std::string size_string;
std::string machine_type;
......
......@@ -285,20 +285,19 @@ std::vector<Method*> AggregateType::Methods(const std::string& name) const {
std::string StructType::ToExplicitString() const {
std::stringstream result;
result << "struct " << name() << "{";
PrintCommaSeparatedList(result, fields());
result << "}";
result << "struct " << name();
return result.str();
}
ClassType::ClassType(const Type* parent, Namespace* nspace,
const std::string& name, bool is_extern,
bool generate_print, bool transient,
bool generate_print, bool generate_verify, bool transient,
const std::string& generates, const ClassDeclaration* decl,
const TypeAlias* alias)
: AggregateType(Kind::kClassType, parent, nspace, name),
is_extern_(is_extern),
generate_print_(generate_print),
generate_verify_(generate_verify),
transient_(transient),
size_(0),
has_indexed_field_(false),
......@@ -326,9 +325,7 @@ std::string ClassType::GetGeneratedTypeNameImpl() const {
std::string ClassType::ToExplicitString() const {
std::stringstream result;
result << "class " << name() << "{";
PrintCommaSeparatedList(result, fields());
result << "}";
result << "class " << name();
return result.str();
}
......
......@@ -103,6 +103,7 @@ class Type : public TypeBase {
virtual bool IsTransient() const { return false; }
virtual const Type* NonConstexprVersion() const { return this; }
base::Optional<const ClassType*> ClassSupertype() const;
virtual std::vector<std::string> GetRuntimeTypes() const { return {}; }
static const Type* CommonSupertype(const Type* a, const Type* b);
void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); }
......@@ -154,6 +155,7 @@ struct Field {
size_t offset;
bool is_weak;
bool const_qualified;
bool generate_verify;
};
std::ostream& operator<<(std::ostream& os, const Field& name_and_type);
......@@ -210,6 +212,7 @@ class AbstractType final : public Type {
if (non_constexpr_version_) return non_constexpr_version_;
return this;
}
std::vector<std::string> GetRuntimeTypes() const override { return {name()}; }
private:
friend class TypeOracle;
......@@ -397,6 +400,15 @@ class UnionType final : public Type {
return union_type ? UnionType(*union_type) : UnionType(t);
}
std::vector<std::string> GetRuntimeTypes() const override {
std::vector<std::string> result;
for (const Type* member : types_) {
std::vector<std::string> sub_result = member->GetRuntimeTypes();
result.insert(result.end(), sub_result.begin(), sub_result.end());
}
return result;
}
private:
explicit UnionType(const Type* t) : Type(Kind::kUnionType, t), types_({t}) {}
void RecomputeParent();
......@@ -444,6 +456,7 @@ class AggregateType : public Type {
std::vector<Method*> Methods(const std::string& name) const;
std::vector<const AggregateType*> GetHierarchy() const;
std::vector<std::string> GetRuntimeTypes() const override { return {name_}; }
protected:
AggregateType(Kind kind, const Type* parent, Namespace* nspace,
......@@ -496,6 +509,7 @@ class ClassType final : public AggregateType {
std::string GetGeneratedTNodeTypeNameImpl() const override;
bool IsExtern() const { return is_extern_; }
bool ShouldGeneratePrint() const { return generate_print_; }
bool ShouldGenerateVerify() const { return generate_verify_; }
bool IsTransient() const override { return transient_; }
bool HasIndexedField() const override;
size_t size() const { return size_; }
......@@ -518,12 +532,13 @@ class ClassType final : public AggregateType {
friend class TypeOracle;
friend class TypeVisitor;
ClassType(const Type* parent, Namespace* nspace, const std::string& name,
bool is_extern, bool generate_print, bool transient,
const std::string& generates, const ClassDeclaration* decl,
const TypeAlias* alias);
bool is_extern, bool generate_print, bool generate_verify,
bool transient, const std::string& generates,
const ClassDeclaration* decl, const TypeAlias* alias);
bool is_extern_;
bool generate_print_;
bool generate_verify_;
bool transient_;
size_t size_;
mutable bool has_indexed_field_;
......
......@@ -770,6 +770,7 @@ namespace test {
assert(a.b.GetX() == 2);
}
@noVerifier
extern class TestClassWithAllTypes extends JSObject {
a: int8;
b: uint8;
......@@ -786,6 +787,7 @@ namespace test {
// This class should throw alignment errors if @ifdef decorators aren't
// working.
@noVerifier
extern class PreprocessingTest extends JSObject {
@ifdef(FALSE_FOR_TESTING) a: int8;
@ifdef(TRUE_FOR_TESTING) a: int16;
......@@ -894,8 +896,12 @@ namespace test {
type Baztype = Foo | FooType;
extern class Foo extends JSObject { fooField: FooType; }
@noVerifier
extern class Foo extends JSObject {
fooField: FooType;
}
@noVerifier
extern class Bar extends Foo {
barField: Bartype;
bazfield: Baztype;
......
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