blob: 396119ccb4bb11ec80f4527e2f8cbf3c3c46d537 [file] [log] [blame]
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
extern macro IsCallable(HeapObject): bool;
extern macro IsConstructor(HeapObject): bool;
extern macro IsFeedbackVector(HeapObject): bool;
extern macro IsJSArray(HeapObject): bool;
extern macro IsJSProxy(HeapObject): bool;
extern macro IsJSRegExp(HeapObject): bool;
extern macro IsJSRegExpStringIterator(HeapObject): bool;
extern macro IsMap(HeapObject): bool;
extern macro IsJSFunction(HeapObject): bool;
extern macro IsJSBoundFunction(HeapObject): bool;
extern macro IsJSObject(HeapObject): bool;
extern macro IsJSPromise(HeapObject): bool;
extern macro IsJSTypedArray(HeapObject): bool;
extern macro IsNumberDictionary(HeapObject): bool;
extern macro IsContext(HeapObject): bool;
extern macro IsNativeContext(HeapObject): bool;
extern macro IsJSReceiver(HeapObject): bool;
extern macro TaggedIsCallable(Object): bool;
extern macro IsDetachedBuffer(JSArrayBuffer): bool;
extern macro IsHeapNumber(HeapObject): bool;
extern macro IsBigInt(HeapObject): bool;
extern macro IsFixedArray(HeapObject): bool;
extern macro IsName(HeapObject): bool;
extern macro IsPrivateSymbol(HeapObject): bool;
extern macro IsNumber(Object): bool;
extern macro IsNumberNormalized(Number): bool;
extern macro IsSafeInteger(Object): bool;
extern macro IsOddball(HeapObject): bool;
extern macro IsSymbol(HeapObject): bool;
extern macro IsJSArrayMap(Map): bool;
extern macro IsExtensibleMap(Map): bool;
extern macro IsJSPrimitiveWrapper(HeapObject): bool;
extern macro IsPromiseCapability(HeapObject): bool;
extern macro IsPromiseReaction(HeapObject): bool;
extern macro IsPromiseReactionJobTask(HeapObject): bool;
extern macro IsPromiseRejectReactionJobTask(HeapObject): bool;
extern macro IsPromiseFulfillReactionJobTask(HeapObject): bool;
extern macro IsSharedFunctionInfo(HeapObject): bool;
extern macro IsCustomElementsReceiverInstanceType(int32): bool;
extern macro HeapObjectToJSDataView(HeapObject): JSDataView
labels CastError;
extern macro HeapObjectToJSProxy(HeapObject): JSProxy
labels CastError;
extern macro HeapObjectToJSStringIterator(HeapObject): JSStringIterator
labels CastError;
extern macro HeapObjectToJSArrayBuffer(HeapObject): JSArrayBuffer
labels CastError;
extern macro TaggedToHeapObject(Object): HeapObject
labels CastError;
extern macro TaggedToSmi(Object): Smi
labels CastError;
extern macro TaggedToPositiveSmi(Object): PositiveSmi
labels CastError;
extern macro TaggedToDirectString(Object): DirectString
labels CastError;
extern macro HeapObjectToJSArray(HeapObject): JSArray
labels CastError;
extern macro HeapObjectToCallable(HeapObject): Callable
labels CastError;
extern macro HeapObjectToFixedArray(HeapObject): FixedArray
labels CastError;
extern macro HeapObjectToFixedDoubleArray(HeapObject): FixedDoubleArray
labels CastError;
extern macro HeapObjectToString(HeapObject): String
labels CastError;
extern macro HeapObjectToConstructor(HeapObject): Constructor
labels CastError;
extern macro HeapObjectToJSFunctionWithPrototypeSlot(HeapObject):
JSFunctionWithPrototypeSlot
labels CastError;
extern macro HeapObjectToHeapNumber(HeapObject): HeapNumber
labels CastError;
extern macro HeapObjectToSloppyArgumentsElements(HeapObject):
SloppyArgumentsElements
labels CastError;
extern macro TaggedToNumber(Object): Number
labels CastError;
macro Cast<A : type extends WeakHeapObject>(o: A|Object): A labels CastError {
if (!IsWeakOrCleared(o)) goto CastError;
return %RawDownCast<A>(o);
}
macro Cast<A: type>(o: MaybeObject): A labels CastError;
Cast<Undefined>(o: MaybeObject): Undefined labels CastError {
if (TaggedNotEqual(o, Undefined)) goto CastError;
return %RawDownCast<Undefined>(o);
}
macro Cast<A : type extends Object>(implicit context: Context)(o: Object): A
labels CastError {
return Cast<A>(TaggedToHeapObject(o) otherwise CastError)
otherwise CastError;
}
Cast<Smi>(o: Object): Smi
labels CastError {
return TaggedToSmi(o) otherwise CastError;
}
Cast<PositiveSmi>(o: Object): PositiveSmi
labels CastError {
return TaggedToPositiveSmi(o) otherwise CastError;
}
Cast<Zero>(o: Object): Zero labels CastError {
if (TaggedEqual(o, SmiConstant(0))) return %RawDownCast<Zero>(o);
goto CastError;
}
Cast<Number>(o: Object): Number
labels CastError {
return TaggedToNumber(o) otherwise CastError;
}
Cast<Undefined>(o: Object): Undefined
labels CastError {
const o: MaybeObject = o;
return Cast<Undefined>(o) otherwise CastError;
}
Cast<Numeric>(o: Object): Numeric labels CastError {
typeswitch (o) {
case (o: Number): {
return o;
}
case (o: BigInt): {
return o;
}
case (HeapObject): {
goto CastError;
}
}
}
Cast<TheHole>(o: Object): TheHole labels CastError {
if (o == TheHole) return %RawDownCast<TheHole>(o);
goto CastError;
}
Cast<TheHole>(o: HeapObject): TheHole labels CastError {
const o: Object = o;
return Cast<TheHole>(o) otherwise CastError;
}
Cast<True>(o: Object): True labels CastError {
if (o == True) return %RawDownCast<True>(o);
goto CastError;
}
Cast<True>(o: HeapObject): True labels CastError {
const o: Object = o;
return Cast<True>(o) otherwise CastError;
}
Cast<False>(o: Object): False labels CastError {
if (o == False) return %RawDownCast<False>(o);
goto CastError;
}
Cast<False>(o: HeapObject): False labels CastError {
const o: Object = o;
return Cast<False>(o) otherwise CastError;
}
Cast<Boolean>(o: Object): Boolean labels CastError {
typeswitch (o) {
case (o: True): {
return o;
}
case (o: False): {
return o;
}
case (Object): {
goto CastError;
}
}
}
Cast<Boolean>(o: HeapObject): Boolean labels CastError {
const o: Object = o;
return Cast<Boolean>(o) otherwise CastError;
}
// TODO(tebbi): These trivial casts for union types should be generated
// automatically.
Cast<JSPrimitive>(o: Object): JSPrimitive labels CastError {
typeswitch (o) {
case (o: Numeric): {
return o;
}
case (o: String): {
return o;
}
case (o: Symbol): {
return o;
}
case (o: Boolean): {
return o;
}
case (o: Undefined): {
return o;
}
case (o: Null): {
return o;
}
case (Object): {
goto CastError;
}
}
}
Cast<JSAny>(o: Object): JSAny labels CastError {
typeswitch (o) {
case (o: JSPrimitive): {
return o;
}
case (o: JSReceiver): {
return o;
}
case (Object): {
goto CastError;
}
}
}
Cast<JSAny|TheHole>(o: Object): JSAny|TheHole labels CastError {
typeswitch (o) {
case (o: JSAny): {
return o;
}
case (o: TheHole): {
return o;
}
case (Object): {
goto CastError;
}
}
}
Cast<Number|TheHole>(o: Object): Number|TheHole labels CastError {
typeswitch (o) {
case (o: Number): {
return o;
}
case (o: TheHole): {
return o;
}
case (Object): {
goto CastError;
}
}
}
macro Cast<A : type extends HeapObject>(o: HeapObject): A
labels CastError;
Cast<HeapObject>(o: HeapObject): HeapObject
labels _CastError {
return o;
}
Cast<Null>(o: HeapObject): Null
labels CastError {
if (o != Null) goto CastError;
return %RawDownCast<Null>(o);
}
Cast<Undefined>(o: HeapObject): Undefined
labels CastError {
const o: MaybeObject = o;
return Cast<Undefined>(o) otherwise CastError;
}
Cast<FixedArray>(o: HeapObject): FixedArray
labels CastError {
return HeapObjectToFixedArray(o) otherwise CastError;
}
Cast<FixedDoubleArray>(o: HeapObject): FixedDoubleArray
labels CastError {
return HeapObjectToFixedDoubleArray(o) otherwise CastError;
}
Cast<EmptyFixedArray>(o: Object): EmptyFixedArray
labels CastError {
if (o != kEmptyFixedArray) goto CastError;
return %RawDownCast<EmptyFixedArray>(o);
}
Cast<EmptyFixedArray>(o: HeapObject): EmptyFixedArray
labels CastError {
const o: Object = o;
return Cast<EmptyFixedArray>(o) otherwise CastError;
}
Cast<(FixedDoubleArray | EmptyFixedArray)>(o: HeapObject): FixedDoubleArray|
EmptyFixedArray labels CastError {
typeswitch (o) {
case (o: EmptyFixedArray): {
return o;
}
case (o: FixedDoubleArray): {
return o;
}
case (HeapObject): {
goto CastError;
}
}
}
Cast<SloppyArgumentsElements>(o: HeapObject): SloppyArgumentsElements
labels CastError {
return HeapObjectToSloppyArgumentsElements(o) otherwise CastError;
}
Cast<JSDataView>(o: HeapObject): JSDataView
labels CastError {
return HeapObjectToJSDataView(o) otherwise CastError;
}
Cast<JSProxy>(o: HeapObject): JSProxy
labels CastError {
return HeapObjectToJSProxy(o) otherwise CastError;
}
Cast<JSStringIterator>(o: HeapObject): JSStringIterator
labels CastError {
return HeapObjectToJSStringIterator(o) otherwise CastError;
}
Cast<JSRegExpStringIterator>(o: HeapObject): JSRegExpStringIterator
labels CastError {
if (IsJSRegExpStringIterator(o)) {
return %RawDownCast<JSRegExpStringIterator>(o);
}
goto CastError;
}
Cast<JSTypedArray>(o: HeapObject): JSTypedArray
labels CastError {
if (IsJSTypedArray(o)) return %RawDownCast<JSTypedArray>(o);
goto CastError;
}
Cast<JSTypedArray>(implicit context: Context)(o: Object): JSTypedArray
labels CastError {
const heapObject = Cast<HeapObject>(o) otherwise CastError;
return Cast<JSTypedArray>(heapObject) otherwise CastError;
}
Cast<Callable>(o: HeapObject): Callable
labels CastError {
return HeapObjectToCallable(o) otherwise CastError;
}
Cast<Undefined|Callable>(o: HeapObject): Undefined|Callable
labels CastError {
if (o == Undefined) return Undefined;
return HeapObjectToCallable(o) otherwise CastError;
}
Cast<JSArray>(o: HeapObject): JSArray
labels CastError {
return HeapObjectToJSArray(o) otherwise CastError;
}
Cast<JSArrayBuffer>(o: HeapObject): JSArrayBuffer
labels CastError {
return HeapObjectToJSArrayBuffer(o) otherwise CastError;
}
Cast<Context>(o: HeapObject): Context
labels CastError {
if (IsContext(o)) return %RawDownCast<Context>(o);
goto CastError;
}
Cast<NativeContext>(o: HeapObject): NativeContext
labels CastError {
if (IsNativeContext(o)) return %RawDownCast<NativeContext>(o);
goto CastError;
}
Cast<JSObject>(o: HeapObject): JSObject
labels CastError {
if (IsJSObject(o)) return %RawDownCast<JSObject>(o);
goto CastError;
}
Cast<NumberDictionary>(o: HeapObject): NumberDictionary
labels CastError {
if (IsNumberDictionary(o)) return %RawDownCast<NumberDictionary>(o);
goto CastError;
}
Cast<String>(o: HeapObject): String
labels CastError {
return HeapObjectToString(o) otherwise CastError;
}
Cast<Oddball>(o: HeapObject): Oddball
labels CastError {
if (IsOddball(o)) return %RawDownCast<Oddball>(o);
goto CastError;
}
Cast<Symbol>(o: HeapObject): Symbol
labels CastError {
if (IsSymbol(o)) return %RawDownCast<Symbol>(o);
goto CastError;
}
macro Cast<T : type extends Symbol>(o: Symbol): T labels CastError;
Cast<PublicSymbol>(o: Symbol): PublicSymbol labels CastError {
if (IsPrivateSymbol(o)) goto CastError;
return %RawDownCast<PublicSymbol>(o);
}
Cast<PrivateSymbol>(o: Symbol): PrivateSymbol labels CastError {
if (IsPrivateSymbol(o)) {
return %RawDownCast<PrivateSymbol>(o);
}
goto CastError;
}
Cast<PublicSymbol>(o: HeapObject): PublicSymbol labels CastError {
const o = Cast<Symbol>(o) otherwise CastError;
return Cast<PublicSymbol>(o) otherwise CastError;
}
Cast<PrivateSymbol>(o: HeapObject): PrivateSymbol labels CastError {
const o = Cast<Symbol>(o) otherwise CastError;
return Cast<PrivateSymbol>(o) otherwise CastError;
}
Cast<DirectString>(o: HeapObject): DirectString
labels CastError {
return TaggedToDirectString(o) otherwise CastError;
}
Cast<Constructor>(o: HeapObject): Constructor
labels CastError {
return HeapObjectToConstructor(o) otherwise CastError;
}
Cast<JSFunctionWithPrototypeSlot>(o: HeapObject): JSFunctionWithPrototypeSlot
labels CastError {
return HeapObjectToJSFunctionWithPrototypeSlot(o) otherwise CastError;
}
Cast<HeapNumber>(o: HeapObject): HeapNumber
labels CastError {
if (IsHeapNumber(o)) return %RawDownCast<HeapNumber>(o);
goto CastError;
}
Cast<BigInt>(o: HeapObject): BigInt labels CastError {
if (IsBigInt(o)) return %RawDownCast<BigInt>(o);
goto CastError;
}
Cast<JSRegExp>(o: HeapObject): JSRegExp
labels CastError {
if (IsJSRegExp(o)) return %RawDownCast<JSRegExp>(o);
goto CastError;
}
Cast<JSRegExpResult>(implicit context: Context)(o: HeapObject): JSRegExpResult
labels CastError {
if (regexp::IsRegExpResult(o)) return %RawDownCast<JSRegExpResult>(o);
goto CastError;
}
Cast<Map>(implicit context: Context)(o: HeapObject): Map
labels CastError {
if (IsMap(o)) return %RawDownCast<Map>(o);
goto CastError;
}
Cast<FeedbackVector>(implicit context: Context)(o: HeapObject): FeedbackVector
labels CastError {
if (IsFeedbackVector(o)) return %RawDownCast<FeedbackVector>(o);
goto CastError;
}
Cast<JSPrimitiveWrapper>(o: HeapObject): JSPrimitiveWrapper
labels CastError {
if (IsJSPrimitiveWrapper(o)) return %RawDownCast<JSPrimitiveWrapper>(o);
goto CastError;
}
Cast<JSSloppyArgumentsObject>(implicit context: Context)(o: HeapObject):
JSSloppyArgumentsObject
labels CastError {
const map: Map = o.map;
if (IsFastAliasedArgumentsMap(map) || IsSloppyArgumentsMap(map) ||
IsSlowAliasedArgumentsMap(map)) {
return %RawDownCast<JSSloppyArgumentsObject>(o);
}
goto CastError;
}
Cast<JSStrictArgumentsObject>(implicit context: Context)(o: HeapObject):
JSStrictArgumentsObject
labels CastError {
const map: Map = o.map;
if (!IsStrictArgumentsMap(map)) goto CastError;
return %RawDownCast<JSStrictArgumentsObject>(o);
}
Cast<JSArgumentsObjectWithLength>(implicit context: Context)(o: HeapObject):
JSArgumentsObjectWithLength
labels CastError {
typeswitch (o) {
case (o: JSStrictArgumentsObject): {
return o;
}
case (o: JSSloppyArgumentsObject): {
return o;
}
case (HeapObject): {
goto CastError;
}
}
}
Cast<FastJSRegExp>(implicit context: Context)(o: HeapObject): FastJSRegExp
labels CastError {
// TODO(jgruber): Remove or redesign this. There is no single 'fast' regexp,
// the conditions to make a regexp object fast differ based on the callsite.
// For now, run the strict variant since replace (the only current callsite)
// accesses flag getters.
if (regexp::IsFastRegExpStrict(o)) {
return %RawDownCast<FastJSRegExp>(o);
}
goto CastError;
}
Cast<FastJSArray>(implicit context: Context)(o: HeapObject): FastJSArray
labels CastError {
if (IsForceSlowPath()) goto CastError;
const map: Map = o.map;
if (!IsJSArrayMap(map)) goto CastError;
// Bailout if receiver has slow elements.
const elementsKind: ElementsKind = LoadMapElementsKind(map);
if (!IsFastElementsKind(elementsKind)) goto CastError;
// Verify that our prototype is the initial array prototype.
if (!IsPrototypeInitialArrayPrototype(map)) goto CastError;
if (IsNoElementsProtectorCellInvalid()) goto CastError;
return %RawDownCast<FastJSArray>(o);
}
Cast<FastJSArrayForRead>(implicit context: Context)(o: HeapObject):
FastJSArrayForRead
labels CastError {
const map: Map = o.map;
if (!IsJSArrayMap(map)) goto CastError;
// Bailout if receiver has slow elements.
const elementsKind: ElementsKind = LoadMapElementsKind(map);
if (!IsElementsKindLessThanOrEqual(
elementsKind, ElementsKind::LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND))
goto CastError;
// Verify that our prototype is the initial array prototype.
if (!IsPrototypeInitialArrayPrototype(map)) goto CastError;
if (IsNoElementsProtectorCellInvalid()) goto CastError;
return %RawDownCast<FastJSArrayForRead>(o);
}
Cast<FastJSArrayForCopy>(implicit context: Context)(o: HeapObject):
FastJSArrayForCopy
labels CastError {
if (IsArraySpeciesProtectorCellInvalid()) goto CastError;
const a = Cast<FastJSArray>(o) otherwise CastError;
return %RawDownCast<FastJSArrayForCopy>(a);
}
Cast<FastJSArrayWithNoCustomIteration>(implicit context: Context)(
o: HeapObject): FastJSArrayWithNoCustomIteration
labels CastError {
if (IsArrayIteratorProtectorCellInvalid()) goto CastError;
const a = Cast<FastJSArray>(o) otherwise CastError;
return %RawDownCast<FastJSArrayWithNoCustomIteration>(a);
}
Cast<FastJSArrayForReadWithNoCustomIteration>(implicit context: Context)(
o: HeapObject): FastJSArrayForReadWithNoCustomIteration
labels CastError {
if (IsArrayIteratorProtectorCellInvalid()) goto CastError;
const a = Cast<FastJSArrayForRead>(o) otherwise CastError;
return %RawDownCast<FastJSArrayForReadWithNoCustomIteration>(a);
}
Cast<JSReceiver>(o: HeapObject): JSReceiver
labels CastError {
if (IsJSReceiver(o)) return %RawDownCast<JSReceiver>(o);
goto CastError;
}
Cast<JSFunction>(implicit context: Context)(o: HeapObject): JSFunction
labels CastError {
if (IsJSFunction(o)) return %RawDownCast<JSFunction>(o);
goto CastError;
}
extern macro IsDebugInfo(HeapObject): bool;
Cast<DebugInfo>(implicit context: Context)(o: HeapObject): DebugInfo
labels CastError {
if (IsDebugInfo(o)) return %RawDownCast<DebugInfo>(o);
goto CastError;
}
extern macro IsCoverageInfo(HeapObject): bool;
Cast<CoverageInfo>(implicit context: Context)(o: HeapObject): CoverageInfo
labels CastError {
if (IsCoverageInfo(o)) return %RawDownCast<CoverageInfo>(o);
goto CastError;
}
Cast<JSReceiver|Null>(o: HeapObject): JSReceiver|Null
labels CastError {
typeswitch (o) {
case (o: Null): {
return o;
}
case (o: JSReceiver): {
return o;
}
case (HeapObject): {
goto CastError;
}
}
}
Cast<PromiseReactionJobTask>(o: HeapObject):
PromiseReactionJobTask labels CastError {
if (IsPromiseReactionJobTask(o)) {
return %RawDownCast<PromiseReactionJobTask>(o);
}
goto CastError;
}
Cast<PromiseFulfillReactionJobTask>(o: HeapObject):
PromiseFulfillReactionJobTask labels CastError {
if (IsPromiseFulfillReactionJobTask(o)) {
return %RawDownCast<PromiseFulfillReactionJobTask>(o);
}
goto CastError;
}
Cast<PromiseRejectReactionJobTask>(o: HeapObject):
PromiseRejectReactionJobTask labels CastError {
if (IsPromiseRejectReactionJobTask(o)) {
return %RawDownCast<PromiseRejectReactionJobTask>(o);
}
goto CastError;
}
Cast<PromiseReaction>(o: HeapObject): PromiseReaction labels CastError {
if (IsPromiseReaction(o)) return %RawDownCast<PromiseReaction>(o);
goto CastError;
}
Cast<Smi|PromiseReaction>(o: Object): Smi|PromiseReaction labels CastError {
typeswitch (o) {
case (o: Smi): {
return o;
}
case (o: PromiseReaction): {
return o;
}
case (Object): {
goto CastError;
}
}
}
Cast<String|Callable>(implicit context: Context)(o: Object): String|
Callable labels CastError {
typeswitch (o) {
case (o: String): {
return o;
}
case (o: Callable): {
return o;
}
case (Object): {
goto CastError;
}
}
}
Cast<Zero|PromiseReaction>(implicit context: Context)(o: Object): Zero|
PromiseReaction labels CastError {
typeswitch (o) {
case (o: Zero): {
return o;
}
case (o: PromiseReaction): {
return o;
}
case (Object): {
goto CastError;
}
}
}
Cast<JSBoundFunction>(o: HeapObject): JSBoundFunction labels CastError {
if (IsJSBoundFunction(o)) return %RawDownCast<JSBoundFunction>(o);
goto CastError;
}
Cast<PromiseCapability>(o: HeapObject): PromiseCapability labels CastError {
if (IsPromiseCapability(o)) return %RawDownCast<PromiseCapability>(o);
goto CastError;
}
Cast<SharedFunctionInfo>(o: HeapObject): SharedFunctionInfo labels CastError {
if (IsSharedFunctionInfo(o)) return %RawDownCast<SharedFunctionInfo>(o);
goto CastError;
}
Cast<JSPromise>(o: HeapObject): JSPromise labels CastError {
if (IsJSPromise(o)) return %RawDownCast<JSPromise>(o);
goto CastError;
}
UnsafeCast<RegExpMatchInfo>(implicit context: Context)(o: Object):
RegExpMatchInfo {
assert(Is<FixedArray>(o));
return %RawDownCast<RegExpMatchInfo>(o);
}