Commit 4d05884e authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[torque] Introduce @abstract annotation for Torque classes

This annotation indicates that the class itself is not instantiated,
and does not have its own instance type: The instance types that
logically belong to the class are the instance types of the derived
classes.

Currently, we need the indication @dirtyInstantiatedAbstractClass
for several classes that are used as both, abstract base classes
and concrete classes. The prime example is JSObject which is the
base for many other classes, and also serves as the class to allocate
plain JSObjects. The annotation is purposefully ugly because in the
future we should refactor code to make it unnecessary.

Another annotation we introduce is @hasSameInstanceTypeAsParent,
which indicates another design pattern that currently occurs in the
code-base: Some Torque classes have the same instance types as their
parent class, but rename some fields, or possibly have a different map.
In such cases, the parent class is not abstract and the derived classes
can be seen as refinements of this class (that, for example, narrows the
type of a field). In the future, Torque should accomodate this pattern
better, but at moment we are content with just indicating where it is
used.

Bug: v8:7793
Change-Id: I1892dcc7325250df75d80308bf3d767d6d43bcc2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1607761
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61495}
parent 617b990f
...@@ -30,7 +30,10 @@ type PositiveSmi extends Smi; ...@@ -30,7 +30,10 @@ type PositiveSmi extends Smi;
// The Smi value zero, which is often used as null for HeapObject types. // The Smi value zero, which is often used as null for HeapObject types.
type Zero extends PositiveSmi; type Zero extends PositiveSmi;
extern class HeapObject extends Tagged { map: Map; } @abstract
extern class HeapObject extends Tagged {
map: Map;
}
type Object = Smi | HeapObject; type Object = Smi | HeapObject;
type int32 generates 'TNode<Int32T>' constexpr 'int32_t'; type int32 generates 'TNode<Int32T>' constexpr 'int32_t';
...@@ -78,6 +81,7 @@ type Number = Smi | HeapNumber; ...@@ -78,6 +81,7 @@ type Number = Smi | HeapNumber;
type BigInt extends HeapObject generates 'TNode<BigInt>'; type BigInt extends HeapObject generates 'TNode<BigInt>';
type Numeric = Number | BigInt; type Numeric = Number | BigInt;
@abstract
@noVerifier @noVerifier
extern class Name extends HeapObject { extern class Name extends HeapObject {
hash_field: int32; hash_field: int32;
...@@ -88,14 +92,17 @@ extern class Symbol extends Name { ...@@ -88,14 +92,17 @@ extern class Symbol extends Name {
name: Object; name: Object;
} }
// abstract @abstract
extern class String extends Name { length: uint32; } extern class String extends Name {
length: uint32;
}
extern class ConsString extends String { extern class ConsString extends String {
first: String; first: String;
second: String; second: String;
} }
@abstract
@noVerifier @noVerifier
extern class ExternalString extends String { extern class ExternalString extends String {
resource: RawPtr; resource: RawPtr;
...@@ -108,6 +115,7 @@ extern class ExternalTwoByteString extends ExternalString {} ...@@ -108,6 +115,7 @@ extern class ExternalTwoByteString extends ExternalString {}
extern class InternalizedString extends String {} extern class InternalizedString extends String {}
// TODO(v8:8983): Add declaration for variable-sized region. // TODO(v8:8983): Add declaration for variable-sized region.
@abstract
@noVerifier @noVerifier
extern class SeqString extends String { extern class SeqString extends String {
} }
...@@ -124,16 +132,21 @@ extern class ThinString extends String { actual: String; } ...@@ -124,16 +132,21 @@ extern class ThinString extends String { actual: String; }
// The HeapNumber value NaN // The HeapNumber value NaN
type NaN extends HeapNumber; type NaN extends HeapNumber;
@abstract
@noVerifier @noVerifier
extern class Struct extends HeapObject { extern class Struct extends HeapObject {
} }
@abstract
@dirtyInstantiatedAbstractClass
@generatePrint @generatePrint
extern class Tuple2 extends Struct { extern class Tuple2 extends Struct {
value1: Object; value1: Object;
value2: Object; value2: Object;
} }
@abstract
@dirtyInstantiatedAbstractClass
@generatePrint @generatePrint
extern class Tuple3 extends Tuple2 { extern class Tuple3 extends Tuple2 {
value3: Object; value3: Object;
...@@ -147,6 +160,7 @@ type RootIndex generates 'TNode<Int32T>' constexpr 'RootIndex'; ...@@ -147,6 +160,7 @@ type RootIndex generates 'TNode<Int32T>' constexpr 'RootIndex';
type Map extends HeapObject generates 'TNode<Map>'; type Map extends HeapObject generates 'TNode<Map>';
@abstract
@noVerifier @noVerifier
extern class FixedArrayBase extends HeapObject { extern class FixedArrayBase extends HeapObject {
length: Smi; length: Smi;
...@@ -191,6 +205,7 @@ intrinsic %GetAllocationBaseSize<Class: type>(map: Map): intptr; ...@@ -191,6 +205,7 @@ intrinsic %GetAllocationBaseSize<Class: type>(map: Map): intptr;
intrinsic %Allocate<Class: type>(size: intptr): Class; intrinsic %Allocate<Class: type>(size: intptr): Class;
intrinsic %AllocateInternalClass<Class: type>(slotCount: constexpr intptr): Class; intrinsic %AllocateInternalClass<Class: type>(slotCount: constexpr intptr): Class;
@abstract
@noVerifier @noVerifier
extern class JSReceiver extends HeapObject { extern class JSReceiver extends HeapObject {
properties_or_hash: FixedArrayBase | Smi; properties_or_hash: FixedArrayBase | Smi;
...@@ -198,6 +213,8 @@ extern class JSReceiver extends HeapObject { ...@@ -198,6 +213,8 @@ extern class JSReceiver extends HeapObject {
type Constructor extends JSReceiver; type Constructor extends JSReceiver;
@abstract
@dirtyInstantiatedAbstractClass
extern class JSObject extends JSReceiver { extern class JSObject extends JSReceiver {
@noVerifier elements: FixedArrayBase; @noVerifier elements: FixedArrayBase;
} }
...@@ -254,9 +271,11 @@ extern class JSValue extends JSObject { value: Object; } ...@@ -254,9 +271,11 @@ extern class JSValue extends JSObject { value: Object; }
extern class JSArgumentsObject extends JSObject {} extern class JSArgumentsObject extends JSObject {}
@noVerifier @noVerifier
@hasSameInstanceTypeAsParent
extern class JSArgumentsObjectWithLength extends JSArgumentsObject { extern class JSArgumentsObjectWithLength extends JSArgumentsObject {
length: Object; length: Object;
} }
@hasSameInstanceTypeAsParent
extern class JSSloppyArgumentsObject extends JSArgumentsObjectWithLength { extern class JSSloppyArgumentsObject extends JSArgumentsObjectWithLength {
callee: Object; callee: Object;
} }
...@@ -327,6 +346,7 @@ type NoSharedNameSentinel extends Smi; ...@@ -327,6 +346,7 @@ type NoSharedNameSentinel extends Smi;
type JSModuleNamespace extends JSObject; type JSModuleNamespace extends JSObject;
type WeakArrayList extends HeapObject; type WeakArrayList extends HeapObject;
@abstract
@noVerifier @noVerifier
extern class JSWeakCollection extends JSObject { extern class JSWeakCollection extends JSObject {
table: Object; table: Object;
...@@ -431,7 +451,7 @@ extern operator '.length_intptr' macro LoadAndUntagFixedArrayBaseLength( ...@@ -431,7 +451,7 @@ extern operator '.length_intptr' macro LoadAndUntagFixedArrayBaseLength(
type FixedTypedArray extends FixedTypedArrayBase type FixedTypedArray extends FixedTypedArrayBase
generates 'TNode<FixedTypedArray>'; generates 'TNode<FixedTypedArray>';
extern class SloppyArgumentsElements extends FixedArray {} type SloppyArgumentsElements extends FixedArray;
type NumberDictionary extends HeapObject type NumberDictionary extends HeapObject
generates 'TNode<NumberDictionary>'; generates 'TNode<NumberDictionary>';
...@@ -491,6 +511,7 @@ extern class JSArrayBuffer extends JSObject { ...@@ -491,6 +511,7 @@ extern class JSArrayBuffer extends JSObject {
backing_store: RawPtr; backing_store: RawPtr;
} }
@abstract
extern class JSArrayBufferView extends JSObject { extern class JSArrayBufferView extends JSObject {
buffer: JSArrayBuffer; buffer: JSArrayBuffer;
byte_offset: uintptr; byte_offset: uintptr;
...@@ -537,6 +558,7 @@ extern class JSAccessorPropertyDescriptor extends JSObject { ...@@ -537,6 +558,7 @@ extern class JSAccessorPropertyDescriptor extends JSObject {
configurable: Object; configurable: Object;
} }
@abstract
@noVerifier @noVerifier
extern class JSCollection extends JSObject { extern class JSCollection extends JSObject {
table: Object; table: Object;
...@@ -579,6 +601,7 @@ extern class JSDataPropertyDescriptor extends JSObject { ...@@ -579,6 +601,7 @@ extern class JSDataPropertyDescriptor extends JSObject {
configurable: Object; configurable: Object;
} }
@abstract
extern class TemplateInfo extends Struct { extern class TemplateInfo extends Struct {
tag: Object; tag: Object;
serial_number: Object; serial_number: Object;
...@@ -616,7 +639,7 @@ extern class ObjectTemplateInfo extends TemplateInfo { ...@@ -616,7 +639,7 @@ extern class ObjectTemplateInfo extends TemplateInfo {
extern class PropertyArray extends HeapObject { length_and_hash: Smi; } extern class PropertyArray extends HeapObject { length_and_hash: Smi; }
extern class DependentCode extends WeakFixedArray {} type DependentCode extends WeakFixedArray;
extern class PropertyCell extends HeapObject { extern class PropertyCell extends HeapObject {
name: Name; name: Name;
...@@ -686,6 +709,8 @@ extern class DataHandler extends Struct { ...@@ -686,6 +709,8 @@ extern class DataHandler extends Struct {
@noVerifier weak data_3: Object; @noVerifier weak data_3: Object;
} }
@abstract
@dirtyInstantiatedAbstractClass
extern class JSGeneratorObject extends JSObject { extern class JSGeneratorObject extends JSObject {
function: JSFunction; function: JSFunction;
context: Context; context: Context;
...@@ -710,7 +735,9 @@ extern class JSPromise extends JSObject { ...@@ -710,7 +735,9 @@ extern class JSPromise extends JSObject {
flags: Smi; flags: Smi;
} }
extern class Microtask extends Struct {} @abstract
extern class Microtask extends Struct {
}
extern class CallbackTask extends Microtask { extern class CallbackTask extends Microtask {
callback: Foreign; callback: Foreign;
...@@ -1005,6 +1032,7 @@ extern class PromiseReaction extends Struct { ...@@ -1005,6 +1032,7 @@ extern class PromiseReaction extends Struct {
promise_or_capability: JSPromise | PromiseCapability | Undefined; promise_or_capability: JSPromise | PromiseCapability | Undefined;
} }
@abstract
extern class PromiseReactionJobTask extends Microtask { extern class PromiseReactionJobTask extends Microtask {
argument: Object; argument: Object;
context: Context; context: Context;
...@@ -1061,6 +1089,7 @@ RegExpBuiltinsAssembler::FastLoadLastIndex(FastJSRegExp): Smi; ...@@ -1061,6 +1089,7 @@ RegExpBuiltinsAssembler::FastLoadLastIndex(FastJSRegExp): Smi;
extern operator '.lastIndex=' macro extern operator '.lastIndex=' macro
RegExpBuiltinsAssembler::FastStoreLastIndex(FastJSRegExp, Smi): void; RegExpBuiltinsAssembler::FastStoreLastIndex(FastJSRegExp, Smi): void;
@hasSameInstanceTypeAsParent
extern class JSRegExpResult extends JSArray { extern class JSRegExpResult extends JSArray {
index: Object; index: Object;
input: Object; input: Object;
...@@ -1082,6 +1111,7 @@ macro GetStartOfCaptureIndex(captureIndex: constexpr int31): constexpr int31 { ...@@ -1082,6 +1111,7 @@ macro GetStartOfCaptureIndex(captureIndex: constexpr int31): constexpr int31 {
return kRegExpMatchInfoFirstCaptureIndex + (captureIndex * 2); return kRegExpMatchInfoFirstCaptureIndex + (captureIndex * 2);
} }
@hasSameInstanceTypeAsParent
extern class RegExpMatchInfo extends FixedArray { extern class RegExpMatchInfo extends FixedArray {
GetStartOfCapture(implicit context: Context)(captureIndex: constexpr int31): GetStartOfCapture(implicit context: Context)(captureIndex: constexpr int31):
Smi { Smi {
...@@ -1115,7 +1145,7 @@ extern class AccessorPair extends Struct { ...@@ -1115,7 +1145,7 @@ extern class AccessorPair extends Struct {
extern class BreakPoint extends Tuple2 {} extern class BreakPoint extends Tuple2 {}
extern class BreakPointInfo extends Tuple2 {} extern class BreakPointInfo extends Tuple2 {}
extern class CoverageInfo extends FixedArray {} type CoverageInfo extends FixedArray;
extern class DebugInfo extends Struct { extern class DebugInfo extends Struct {
shared_function_info: SharedFunctionInfo; shared_function_info: SharedFunctionInfo;
...@@ -1187,9 +1217,7 @@ extern class WasmExceptionObject extends JSObject { ...@@ -1187,9 +1217,7 @@ extern class WasmExceptionObject extends JSObject {
extern class WasmExceptionPackage extends JSReceiver { extern class WasmExceptionPackage extends JSReceiver {
} }
@noVerifier type WasmExportedFunction extends JSFunction;
extern class WasmExportedFunction extends JSFunction {
}
extern class AsmWasmData extends Struct { extern class AsmWasmData extends Struct {
managed_native_module: Foreign; // Managed<wasm::NativeModule> managed_native_module: Foreign; // Managed<wasm::NativeModule>
......
...@@ -516,7 +516,8 @@ Node* PromiseBuiltinsAssembler::AllocatePromiseReaction( ...@@ -516,7 +516,8 @@ Node* PromiseBuiltinsAssembler::AllocatePromiseReaction(
Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask( Node* PromiseBuiltinsAssembler::AllocatePromiseReactionJobTask(
Node* map, Node* context, Node* argument, Node* handler, Node* map, Node* context, Node* argument, Node* handler,
Node* promise_or_capability) { Node* promise_or_capability) {
Node* const microtask = Allocate(PromiseReactionJobTask::kSize); Node* const microtask =
Allocate(PromiseReactionJobTask::kSizeOfAllPromiseReactionJobTasks);
StoreMapNoWriteBarrier(microtask, map); StoreMapNoWriteBarrier(microtask, map);
StoreObjectFieldNoWriteBarrier( StoreObjectFieldNoWriteBarrier(
microtask, PromiseReactionJobTask::kArgumentOffset, argument); microtask, PromiseReactionJobTask::kArgumentOffset, argument);
...@@ -640,8 +641,10 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions( ...@@ -640,8 +641,10 @@ Node* PromiseBuiltinsAssembler::TriggerPromiseReactions(
// Morph {current} from a PromiseReaction into a PromiseReactionJobTask // Morph {current} from a PromiseReaction into a PromiseReactionJobTask
// and schedule that on the microtask queue. We try to minimize the number // and schedule that on the microtask queue. We try to minimize the number
// of stores here to avoid screwing up the store buffer. // of stores here to avoid screwing up the store buffer.
STATIC_ASSERT(static_cast<int>(PromiseReaction::kSize) == STATIC_ASSERT(
static_cast<int>(PromiseReactionJobTask::kSize)); static_cast<int>(PromiseReaction::kSize) ==
static_cast<int>(
PromiseReactionJobTask::kSizeOfAllPromiseReactionJobTasks));
if (type == PromiseReaction::kFulfill) { if (type == PromiseReaction::kFulfill) {
StoreMapNoWriteBarrier(current, StoreMapNoWriteBarrier(current,
RootIndex::kPromiseFulfillReactionJobTaskMap); RootIndex::kPromiseFulfillReactionJobTaskMap);
......
...@@ -553,7 +553,7 @@ class PrototypeInfo::BodyDescriptor final : public BodyDescriptorBase { ...@@ -553,7 +553,7 @@ class PrototypeInfo::BodyDescriptor final : public BodyDescriptorBase {
class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase { class JSWeakCollection::BodyDescriptorImpl final : public BodyDescriptorBase {
public: public:
STATIC_ASSERT(kTableOffset + kTaggedSize == kSize); STATIC_ASSERT(kTableOffset + kTaggedSize == kSizeOfAllWeakCollections);
static bool IsValidSlot(Map map, HeapObject obj, int offset) { static bool IsValidSlot(Map map, HeapObject obj, int offset) {
return IsValidJSObjectSlotImpl(map, obj, offset); return IsValidJSObjectSlotImpl(map, obj, offset);
......
...@@ -866,7 +866,7 @@ void JSArgumentsObject::JSArgumentsObjectVerify(Isolate* isolate) { ...@@ -866,7 +866,7 @@ void JSArgumentsObject::JSArgumentsObjectVerify(Isolate* isolate) {
void SloppyArgumentsElements::SloppyArgumentsElementsVerify(Isolate* isolate, void SloppyArgumentsElements::SloppyArgumentsElementsVerify(Isolate* isolate,
JSObject holder) { JSObject holder) {
TorqueGeneratedClassVerifiers::SloppyArgumentsElementsVerify(*this, isolate); FixedArrayVerify(isolate);
// Abort verification if only partially initialized (can't use arguments() // Abort verification if only partially initialized (can't use arguments()
// getter because it does FixedArray::cast()). // getter because it does FixedArray::cast()).
if (get(kArgumentsIndex)->IsUndefined(isolate)) return; if (get(kArgumentsIndex)->IsUndefined(isolate)) return;
......
...@@ -6122,8 +6122,10 @@ Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate, ...@@ -6122,8 +6122,10 @@ Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
} }
if (handler_context.is_null()) handler_context = isolate->native_context(); if (handler_context.is_null()) handler_context = isolate->native_context();
STATIC_ASSERT(static_cast<int>(PromiseReaction::kSize) == STATIC_ASSERT(
static_cast<int>(PromiseReactionJobTask::kSize)); static_cast<int>(PromiseReaction::kSize) ==
static_cast<int>(
PromiseReactionJobTask::kSizeOfAllPromiseReactionJobTasks));
if (type == PromiseReaction::kFulfill) { if (type == PromiseReaction::kFulfill) {
task->synchronized_set_map( task->synchronized_set_map(
ReadOnlyRoots(isolate).promise_fulfill_reaction_job_task_map()); ReadOnlyRoots(isolate).promise_fulfill_reaction_job_task_map());
......
...@@ -100,8 +100,6 @@ class FixedArrayBase : public HeapObject { ...@@ -100,8 +100,6 @@ class FixedArrayBase : public HeapObject {
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
TORQUE_GENERATED_FIXED_ARRAY_BASE_FIELDS) TORQUE_GENERATED_FIXED_ARRAY_BASE_FIELDS)
static const int kHeaderSize = kSize;
protected: protected:
// Special-purpose constructor for subclasses that have fast paths where // Special-purpose constructor for subclasses that have fast paths where
// their ptr() is a Smi. // their ptr() is a Smi.
......
...@@ -44,6 +44,8 @@ class JSSet : public JSCollection { ...@@ -44,6 +44,8 @@ class JSSet : public JSCollection {
// Dispatched behavior. // Dispatched behavior.
DECL_PRINTER(JSSet) DECL_PRINTER(JSSet)
DECL_VERIFIER(JSSet) DECL_VERIFIER(JSSet)
DEFINE_FIELD_OFFSET_CONSTANTS(JSCollection::kHeaderSize,
TORQUE_GENERATED_JSWEAK_SET_FIELDS)
OBJECT_CONSTRUCTORS(JSSet, JSCollection); OBJECT_CONSTRUCTORS(JSSet, JSCollection);
}; };
...@@ -72,6 +74,8 @@ class JSMap : public JSCollection { ...@@ -72,6 +74,8 @@ class JSMap : public JSCollection {
// Dispatched behavior. // Dispatched behavior.
DECL_PRINTER(JSMap) DECL_PRINTER(JSMap)
DECL_VERIFIER(JSMap) DECL_VERIFIER(JSMap)
DEFINE_FIELD_OFFSET_CONSTANTS(JSCollection::kHeaderSize,
TORQUE_GENERATED_JSWEAK_MAP_FIELDS)
OBJECT_CONSTRUCTORS(JSMap, JSCollection); OBJECT_CONSTRUCTORS(JSMap, JSCollection);
}; };
...@@ -121,6 +125,8 @@ class JSWeakCollection : public JSObject { ...@@ -121,6 +125,8 @@ class JSWeakCollection : public JSObject {
// Visit the whole object. // Visit the whole object.
using BodyDescriptor = BodyDescriptorImpl; using BodyDescriptor = BodyDescriptorImpl;
static const int kSizeOfAllWeakCollections = kHeaderSize;
OBJECT_CONSTRUCTORS(JSWeakCollection, JSObject); OBJECT_CONSTRUCTORS(JSWeakCollection, JSObject);
}; };
...@@ -133,6 +139,9 @@ class JSWeakMap : public JSWeakCollection { ...@@ -133,6 +139,9 @@ class JSWeakMap : public JSWeakCollection {
DECL_PRINTER(JSWeakMap) DECL_PRINTER(JSWeakMap)
DECL_VERIFIER(JSWeakMap) DECL_VERIFIER(JSWeakMap)
DEFINE_FIELD_OFFSET_CONSTANTS(JSWeakCollection::kHeaderSize,
TORQUE_GENERATED_JSWEAK_MAP_FIELDS)
STATIC_ASSERT(kSize == kSizeOfAllWeakCollections);
OBJECT_CONSTRUCTORS(JSWeakMap, JSWeakCollection); OBJECT_CONSTRUCTORS(JSWeakMap, JSWeakCollection);
}; };
...@@ -144,6 +153,9 @@ class JSWeakSet : public JSWeakCollection { ...@@ -144,6 +153,9 @@ class JSWeakSet : public JSWeakCollection {
// Dispatched behavior. // Dispatched behavior.
DECL_PRINTER(JSWeakSet) DECL_PRINTER(JSWeakSet)
DECL_VERIFIER(JSWeakSet) DECL_VERIFIER(JSWeakSet)
DEFINE_FIELD_OFFSET_CONSTANTS(JSWeakCollection::kHeaderSize,
TORQUE_GENERATED_JSWEAK_SET_FIELDS)
STATIC_ASSERT(kSize == kSizeOfAllWeakCollections);
OBJECT_CONSTRUCTORS(JSWeakSet, JSWeakCollection); OBJECT_CONSTRUCTORS(JSWeakSet, JSWeakCollection);
}; };
......
...@@ -266,8 +266,6 @@ class JSReceiver : public HeapObject { ...@@ -266,8 +266,6 @@ class JSReceiver : public HeapObject {
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
TORQUE_GENERATED_JSRECEIVER_FIELDS) TORQUE_GENERATED_JSRECEIVER_FIELDS)
static const int kHeaderSize = kSize;
bool HasProxyInPrototype(Isolate* isolate); bool HasProxyInPrototype(Isolate* isolate);
bool HasComplexElements(); bool HasComplexElements();
......
...@@ -71,8 +71,6 @@ class Name : public HeapObject { ...@@ -71,8 +71,6 @@ class Name : public HeapObject {
DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
TORQUE_GENERATED_NAME_FIELDS) TORQUE_GENERATED_NAME_FIELDS)
static const int kHeaderSize = kSize;
// Mask constant for checking if a name has a computed hash code // Mask constant for checking if a name has a computed hash code
// and if it is a string that is an array index. The least significant bit // and if it is a string that is an array index. The least significant bit
// indicates whether a hash code has been computed. If the hash code has // indicates whether a hash code has been computed. If the hash code has
......
...@@ -39,7 +39,7 @@ class PromiseReactionJobTask : public Microtask { ...@@ -39,7 +39,7 @@ class PromiseReactionJobTask : public Microtask {
// Dispatched behavior. // Dispatched behavior.
DECL_CAST(PromiseReactionJobTask) DECL_CAST(PromiseReactionJobTask)
DECL_VERIFIER(PromiseReactionJobTask) DECL_VERIFIER(PromiseReactionJobTask)
static const int kSizeOfAllPromiseReactionJobTasks = kHeaderSize;
OBJECT_CONSTRUCTORS(PromiseReactionJobTask, Microtask); OBJECT_CONSTRUCTORS(PromiseReactionJobTask, Microtask);
}; };
...@@ -51,6 +51,11 @@ class PromiseFulfillReactionJobTask : public PromiseReactionJobTask { ...@@ -51,6 +51,11 @@ class PromiseFulfillReactionJobTask : public PromiseReactionJobTask {
DECL_PRINTER(PromiseFulfillReactionJobTask) DECL_PRINTER(PromiseFulfillReactionJobTask)
DECL_VERIFIER(PromiseFulfillReactionJobTask) DECL_VERIFIER(PromiseFulfillReactionJobTask)
DEFINE_FIELD_OFFSET_CONSTANTS(
PromiseReactionJobTask::kHeaderSize,
TORQUE_GENERATED_PROMISE_FULFILL_REACTION_JOB_TASK_FIELDS)
STATIC_ASSERT(kSize == kSizeOfAllPromiseReactionJobTasks);
OBJECT_CONSTRUCTORS(PromiseFulfillReactionJobTask, PromiseReactionJobTask); OBJECT_CONSTRUCTORS(PromiseFulfillReactionJobTask, PromiseReactionJobTask);
}; };
...@@ -62,6 +67,11 @@ class PromiseRejectReactionJobTask : public PromiseReactionJobTask { ...@@ -62,6 +67,11 @@ class PromiseRejectReactionJobTask : public PromiseReactionJobTask {
DECL_PRINTER(PromiseRejectReactionJobTask) DECL_PRINTER(PromiseRejectReactionJobTask)
DECL_VERIFIER(PromiseRejectReactionJobTask) DECL_VERIFIER(PromiseRejectReactionJobTask)
DEFINE_FIELD_OFFSET_CONSTANTS(
PromiseReactionJobTask::kHeaderSize,
TORQUE_GENERATED_PROMISE_REJECT_REACTION_JOB_TASK_FIELDS)
STATIC_ASSERT(kSize == kSizeOfAllPromiseReactionJobTasks);
OBJECT_CONSTRUCTORS(PromiseRejectReactionJobTask, PromiseReactionJobTask); OBJECT_CONSTRUCTORS(PromiseRejectReactionJobTask, PromiseReactionJobTask);
}; };
......
...@@ -164,7 +164,7 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) { ...@@ -164,7 +164,7 @@ bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
// strings in generated code, we need to bailout to runtime. // strings in generated code, we need to bailout to runtime.
Map new_map; Map new_map;
ReadOnlyRoots roots(heap); ReadOnlyRoots roots(heap);
if (size < ExternalString::kSize) { if (size < ExternalString::kSizeOfAllExternalStrings) {
if (is_internalized) { if (is_internalized) {
new_map = roots.uncached_external_internalized_string_map(); new_map = roots.uncached_external_internalized_string_map();
} else { } else {
...@@ -238,7 +238,7 @@ bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) { ...@@ -238,7 +238,7 @@ bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
// strings in generated code, we need to bailout to runtime. // strings in generated code, we need to bailout to runtime.
Map new_map; Map new_map;
ReadOnlyRoots roots(heap); ReadOnlyRoots roots(heap);
if (size < ExternalString::kSize) { if (size < ExternalString::kSizeOfAllExternalStrings) {
new_map = is_internalized new_map = is_internalized
? roots.uncached_external_one_byte_internalized_string_map() ? roots.uncached_external_one_byte_internalized_string_map()
: roots.uncached_external_one_byte_string_map(); : roots.uncached_external_one_byte_string_map();
......
...@@ -341,8 +341,6 @@ class String : public Name { ...@@ -341,8 +341,6 @@ class String : public Name {
DEFINE_FIELD_OFFSET_CONSTANTS(Name::kHeaderSize, DEFINE_FIELD_OFFSET_CONSTANTS(Name::kHeaderSize,
TORQUE_GENERATED_STRING_FIELDS) TORQUE_GENERATED_STRING_FIELDS)
static const int kHeaderSize = kSize;
// Max char codes. // Max char codes.
static const int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar; static const int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar;
static const uint32_t kMaxOneByteCharCodeU = unibrow::Latin1::kMaxChar; static const uint32_t kMaxOneByteCharCodeU = unibrow::Latin1::kMaxChar;
...@@ -698,6 +696,7 @@ class ExternalString : public String { ...@@ -698,6 +696,7 @@ class ExternalString : public String {
inline void DisposeResource(); inline void DisposeResource();
STATIC_ASSERT(kResourceOffset == Internals::kStringResourceOffset); STATIC_ASSERT(kResourceOffset == Internals::kStringResourceOffset);
static const int kSizeOfAllExternalStrings = kHeaderSize;
OBJECT_CONSTRUCTORS(ExternalString, String); OBJECT_CONSTRUCTORS(ExternalString, String);
}; };
...@@ -734,6 +733,12 @@ class ExternalOneByteString : public ExternalString { ...@@ -734,6 +733,12 @@ class ExternalOneByteString : public ExternalString {
class BodyDescriptor; class BodyDescriptor;
DEFINE_FIELD_OFFSET_CONSTANTS(
ExternalString::kHeaderSize,
TORQUE_GENERATED_EXTERNAL_ONE_BYTE_STRING_FIELDS)
STATIC_ASSERT(kSize == kSizeOfAllExternalStrings);
OBJECT_CONSTRUCTORS(ExternalOneByteString, ExternalString); OBJECT_CONSTRUCTORS(ExternalOneByteString, ExternalString);
}; };
...@@ -772,6 +777,12 @@ class ExternalTwoByteString : public ExternalString { ...@@ -772,6 +777,12 @@ class ExternalTwoByteString : public ExternalString {
class BodyDescriptor; class BodyDescriptor;
DEFINE_FIELD_OFFSET_CONSTANTS(
ExternalString::kHeaderSize,
TORQUE_GENERATED_EXTERNAL_TWO_BYTE_STRING_FIELDS)
STATIC_ASSERT(kSize == kSizeOfAllExternalStrings);
OBJECT_CONSTRUCTORS(ExternalTwoByteString, ExternalString); OBJECT_CONSTRUCTORS(ExternalTwoByteString, ExternalString);
}; };
......
...@@ -169,7 +169,7 @@ class FunctionTemplateInfo : public TemplateInfo { ...@@ -169,7 +169,7 @@ class FunctionTemplateInfo : public TemplateInfo {
static const int kInvalidSerialNumber = 0; static const int kInvalidSerialNumber = 0;
DEFINE_FIELD_OFFSET_CONSTANTS(TemplateInfo::kSize, DEFINE_FIELD_OFFSET_CONSTANTS(TemplateInfo::kHeaderSize,
TORQUE_GENERATED_FUNCTION_TEMPLATE_INFO_FIELDS) TORQUE_GENERATED_FUNCTION_TEMPLATE_INFO_FIELDS)
static Handle<SharedFunctionInfo> GetOrCreateSharedFunctionInfo( static Handle<SharedFunctionInfo> GetOrCreateSharedFunctionInfo(
...@@ -221,7 +221,7 @@ class ObjectTemplateInfo : public TemplateInfo { ...@@ -221,7 +221,7 @@ class ObjectTemplateInfo : public TemplateInfo {
DECL_VERIFIER(ObjectTemplateInfo) DECL_VERIFIER(ObjectTemplateInfo)
// Layout description. // Layout description.
DEFINE_FIELD_OFFSET_CONSTANTS(TemplateInfo::kSize, DEFINE_FIELD_OFFSET_CONSTANTS(TemplateInfo::kHeaderSize,
TORQUE_GENERATED_OBJECT_TEMPLATE_INFO_FIELDS) TORQUE_GENERATED_OBJECT_TEMPLATE_INFO_FIELDS)
// Starting from given object template's constructor walk up the inheritance // Starting from given object template's constructor walk up the inheritance
......
...@@ -67,7 +67,10 @@ enum class ClassFlag { ...@@ -67,7 +67,10 @@ enum class ClassFlag {
kGeneratePrint = 1 << 1, kGeneratePrint = 1 << 1,
kGenerateVerify = 1 << 2, kGenerateVerify = 1 << 2,
kTransient = 1 << 3, kTransient = 1 << 3,
kHasIndexedField = 1 << 4 kAbstract = 1 << 4,
kInstantiatedAbstractClass = 1 << 5,
kHasSameInstanceTypeAsParent = 1 << 6,
kHasIndexedField = 1 << 7
}; };
using ClassFlags = base::Flags<ClassFlag>; using ClassFlags = base::Flags<ClassFlag>;
......
...@@ -164,13 +164,15 @@ void ImplementationVisitor::Visit(TypeAlias* alias) { ...@@ -164,13 +164,15 @@ void ImplementationVisitor::Visit(TypeAlias* alias) {
// TODO(danno): This is a pretty cheesy hack for now. There should be a more // TODO(danno): This is a pretty cheesy hack for now. There should be a more
// robust mechanism for this, e.g. declaring classes 'extern' or something. // robust mechanism for this, e.g. declaring classes 'extern' or something.
if (class_type->nspace()->IsTestNamespace()) { if (class_type->nspace()->IsTestNamespace()) {
std::string class_name{ const ClassType* super = class_type->GetSuperClass();
class_type->GetSuperClass()->GetGeneratedTNodeTypeName()}; std::string class_name{super->GetGeneratedTNodeTypeName()};
header_out() << " class " << class_type->name() << " : public " header_out() << " class " << class_type->name() << " : public "
<< class_name << " {\n"; << class_name << " {\n";
header_out() << " public:\n"; header_out() << " public:\n";
header_out() << " DEFINE_FIELD_OFFSET_CONSTANTS(" << class_name header_out() << " DEFINE_FIELD_OFFSET_CONSTANTS(" << class_name
<< "::kSize, TORQUE_GENERATED_" << "::";
header_out() << (super->IsAbstract() ? "kHeaderSize" : "kSize");
header_out() << ", TORQUE_GENERATED_"
<< CapifyStringWithUnderscores(class_type->name()) << CapifyStringWithUnderscores(class_type->name())
<< "_FIELDS)\n"; << "_FIELDS)\n";
header_out() << " };\n"; header_out() << " };\n";
...@@ -2954,7 +2956,6 @@ void ImplementationVisitor::GenerateClassFieldOffsets( ...@@ -2954,7 +2956,6 @@ void ImplementationVisitor::GenerateClassFieldOffsets(
new_contents_stream << "V(k" << CamelifyString(f.name_and_type.name) new_contents_stream << "V(k" << CamelifyString(f.name_and_type.name)
<< "Offset, " << size_string << ") \\\n"; << "Offset, " << size_string << ") \\\n";
} }
ProcessFieldInSection(&section, &completed_sections, ProcessFieldInSection(&section, &completed_sections,
FieldSectionType::kNoSection, &new_contents_stream); FieldSectionType::kNoSection, &new_contents_stream);
CompleteFieldSection(&section, &completed_sections, CompleteFieldSection(&section, &completed_sections,
...@@ -2964,7 +2965,12 @@ void ImplementationVisitor::GenerateClassFieldOffsets( ...@@ -2964,7 +2965,12 @@ void ImplementationVisitor::GenerateClassFieldOffsets(
FieldSectionType::kStrongSection, FieldSectionType::kStrongSection,
&new_contents_stream); &new_contents_stream);
new_contents_stream << "V(kSize, 0) \\\n"; if (type->IsAbstract()) {
new_contents_stream << "V(kHeaderSize, 0) \\\n";
}
if (!type->IsAbstract() || type->IsInstantiatedAbstractClass()) {
new_contents_stream << "V(kSize, 0) \\\n";
}
new_contents_stream << "\n"; new_contents_stream << "\n";
} }
} }
......
...@@ -656,13 +656,24 @@ class AnnotationSet { ...@@ -656,13 +656,24 @@ class AnnotationSet {
base::Optional<ParseResult> MakeClassDeclaration( base::Optional<ParseResult> MakeClassDeclaration(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
AnnotationSet annotations(child_results, AnnotationSet annotations(
{"@generatePrint", "@noVerifier"}); child_results,
{"@generatePrint", "@noVerifier", "@abstract",
"@dirtyInstantiatedAbstractClass", "@hasSameInstanceTypeAsParent"});
ClassFlags flags = ClassFlag::kNone; ClassFlags flags = ClassFlag::kNone;
bool generate_print = annotations.Contains("@generatePrint"); bool generate_print = annotations.Contains("@generatePrint");
if (generate_print) flags |= ClassFlag::kGeneratePrint; if (generate_print) flags |= ClassFlag::kGeneratePrint;
bool generate_verify = !annotations.Contains("@noVerifier"); bool generate_verify = !annotations.Contains("@noVerifier");
if (generate_verify) flags |= ClassFlag::kGenerateVerify; if (generate_verify) flags |= ClassFlag::kGenerateVerify;
if (annotations.Contains("@abstract")) {
flags |= ClassFlag::kAbstract;
}
if (annotations.Contains("@dirtyInstantiatedAbstractClass")) {
flags |= ClassFlag::kInstantiatedAbstractClass;
}
if (annotations.Contains("@hasSameInstanceTypeAsParent")) {
flags |= ClassFlag::kHasSameInstanceTypeAsParent;
}
auto is_extern = child_results->NextAs<bool>(); auto is_extern = child_results->NextAs<bool>();
if (is_extern) flags |= ClassFlag::kExtern; if (is_extern) flags |= ClassFlag::kExtern;
auto transient = child_results->NextAs<bool>(); auto transient = child_results->NextAs<bool>();
......
...@@ -329,7 +329,8 @@ std::string ClassType::ToExplicitString() const { ...@@ -329,7 +329,8 @@ std::string ClassType::ToExplicitString() const {
} }
bool ClassType::AllowInstantiation() const { bool ClassType::AllowInstantiation() const {
return !IsExtern() || nspace()->IsDefaultNamespace(); return (!IsExtern() || nspace()->IsDefaultNamespace()) &&
(!IsAbstract() || IsInstantiatedAbstractClass());
} }
void ClassType::Finalize() const { void ClassType::Finalize() const {
...@@ -339,6 +340,14 @@ void ClassType::Finalize() const { ...@@ -339,6 +340,14 @@ void ClassType::Finalize() const {
if (parent()) { if (parent()) {
if (const ClassType* super_class = ClassType::DynamicCast(parent())) { if (const ClassType* super_class = ClassType::DynamicCast(parent())) {
if (super_class->HasIndexedField()) flags_ |= ClassFlag::kHasIndexedField; if (super_class->HasIndexedField()) flags_ |= ClassFlag::kHasIndexedField;
if (!super_class->IsAbstract() && !HasSameInstanceTypeAsParent()) {
ReportLintError(
"Super class must either be abstract (annotate super class with "
"@abstract) "
"or this class must have the same instance type as the super class "
"(annotate this class with @hasSameInstanceTypeAsParent).",
this->decl_->name->pos);
}
} }
} }
TypeVisitor::VisitClassFieldsAndMethods(const_cast<ClassType*>(this), TypeVisitor::VisitClassFieldsAndMethods(const_cast<ClassType*>(this),
......
...@@ -517,6 +517,13 @@ class ClassType final : public AggregateType { ...@@ -517,6 +517,13 @@ class ClassType final : public AggregateType {
return flags_ & ClassFlag::kGenerateVerify; return flags_ & ClassFlag::kGenerateVerify;
} }
bool IsTransient() const override { return flags_ & ClassFlag::kTransient; } bool IsTransient() const override { return flags_ & ClassFlag::kTransient; }
bool IsAbstract() const { return flags_ & ClassFlag::kAbstract; }
bool IsInstantiatedAbstractClass() const {
return flags_ & ClassFlag::kInstantiatedAbstractClass;
}
bool HasSameInstanceTypeAsParent() const {
return flags_ & ClassFlag::kHasSameInstanceTypeAsParent;
}
bool HasIndexedField() const override; bool HasIndexedField() const override;
size_t size() const { return size_; } size_t size() const { return size_; }
const ClassType* GetSuperClass() const { const ClassType* GetSuperClass() const {
......
...@@ -896,6 +896,7 @@ namespace test { ...@@ -896,6 +896,7 @@ namespace test {
type Baztype = Foo | FooType; type Baztype = Foo | FooType;
@abstract
@noVerifier @noVerifier
extern class Foo extends JSObject { extern class Foo extends JSObject {
fooField: FooType; fooField: FooType;
......
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