blob: 1562b7b4ddc0a28ff9f97186668ed8f95cd148d9 [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 IsBigInt(HeapObject): bool;
extern macro IsConstructor(HeapObject): bool;
extern macro IsCustomElementsReceiverInstanceType(int32): bool;
extern macro IsExtensibleMap(Map): bool;
extern macro IsNumberNormalized(Number): bool;
extern macro IsSafeInteger(Object): bool;
@export
macro IsAccessorInfo(o: HeapObject): bool {
return Is<AccessorInfo>(o);
}
@export
macro IsAccessorPair(o: HeapObject): bool {
return Is<AccessorPair>(o);
}
@export
macro IsAllocationSite(o: HeapObject): bool {
return Is<AllocationSite>(o);
}
@export
macro IsCell(o: HeapObject): bool {
return Is<Cell>(o);
}
@export
macro IsCode(o: HeapObject): bool {
return Is<Code>(o);
}
@export
macro IsContext(o: HeapObject): bool {
return Is<Context>(o);
}
@export
macro IsCoverageInfo(o: HeapObject): bool {
return Is<CoverageInfo>(o);
}
@export
macro IsDebugInfo(o: HeapObject): bool {
return Is<DebugInfo>(o);
}
@export
macro IsFixedDoubleArray(o: HeapObject): bool {
return Is<FixedDoubleArray>(o);
}
@export
macro IsFeedbackCell(o: HeapObject): bool {
return Is<FeedbackCell>(o);
}
@export
macro IsFeedbackVector(o: HeapObject): bool {
return Is<FeedbackVector>(o);
}
@export
macro IsHeapNumber(o: HeapObject): bool {
return Is<HeapNumber>(o);
}
@export
macro IsNativeContext(o: HeapObject): bool {
return Is<NativeContext>(o);
}
@export
macro IsNumber(o: Object): bool {
return Is<Number>(o);
}
@export
macro IsPrivateSymbol(o: HeapObject): bool {
return Is<PrivateSymbol>(o);
}
@export
macro IsPromiseCapability(o: HeapObject): bool {
return Is<PromiseCapability>(o);
}
@export
macro IsPromiseFulfillReactionJobTask(o: HeapObject): bool {
return Is<PromiseFulfillReactionJobTask>(o);
}
@export
macro IsPromiseReaction(o: HeapObject): bool {
return Is<PromiseReaction>(o);
}
@export
macro IsPromiseRejectReactionJobTask(o: HeapObject): bool {
return Is<PromiseRejectReactionJobTask>(o);
}
@export
macro IsSharedFunctionInfo(o: HeapObject): bool {
return Is<SharedFunctionInfo>(o);
}
@export
macro IsSymbol(o: HeapObject): bool {
return Is<Symbol>(o);
}
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 HeapObjectToCallable(HeapObject): Callable
labels CastError;
extern macro HeapObjectToConstructor(HeapObject): Constructor
labels CastError;
extern macro HeapObjectToJSFunctionWithPrototypeSlot(HeapObject):
JSFunctionWithPrototypeSlot
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 extends Object>(implicit context: Context)(o: MaybeObject):
A labels CastError {
typeswitch (o) {
case (WeakHeapObject): {
goto CastError;
}
case (o: Object): {
return Cast<A>(o) otherwise 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 {
typeswitch (o) {
case (s: Smi): {
return s;
}
case (n: HeapNumber): {
return n;
}
case (Object): {
goto 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<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<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;
}
macro Cast<T : type extends Symbol>(o: Symbol): T labels CastError;
Cast<PublicSymbol>(s: Symbol): PublicSymbol labels CastError {
if (s.flags.is_private) goto CastError;
return %RawDownCast<PublicSymbol>(s);
}
Cast<PrivateSymbol>(s: Symbol): PrivateSymbol labels CastError {
if (s.flags.is_private) return %RawDownCast<PrivateSymbol>(s);
goto CastError;
}
Cast<PublicSymbol>(o: HeapObject): PublicSymbol labels CastError {
const s = Cast<Symbol>(o) otherwise CastError;
return Cast<PublicSymbol>(s) otherwise CastError;
}
Cast<PrivateSymbol>(o: HeapObject): PrivateSymbol labels CastError {
const s = Cast<Symbol>(o) otherwise CastError;
return Cast<PrivateSymbol>(s) 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<BigInt>(o: HeapObject): BigInt labels CastError {
if (IsBigInt(o)) return %RawDownCast<BigInt>(o);
goto CastError;
}
Cast<JSRegExpResult>(implicit context: Context)(o: HeapObject): JSRegExpResult
labels CastError {
if (regexp::IsRegExpResult(o)) return %RawDownCast<JSRegExpResult>(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;
if (!Is<JSArray>(o)) goto CastError;
// Bailout if receiver has slow elements.
const map: Map = o.map;
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 {
if (!Is<JSArray>(o)) goto CastError;
// Bailout if receiver has slow elements.
const map: Map = o.map;
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<SeqOneByteString>(o: HeapObject): SeqOneByteString labels CastError {
if (!IsSeqOneByteString(o)) goto CastError;
return %RawDownCast<SeqOneByteString>(o);
}
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<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<JSFunction|JSBoundFunction>(implicit context: Context)(o: Object):
JSFunction|JSBoundFunction labels CastError {
typeswitch (o) {
case (o: JSFunction): {
return o;
}
case (o: JSBoundFunction): {
return o;
}
case (Object): {
goto CastError;
}
}
}
Cast<FixedArray|Undefined>(o: HeapObject): FixedArray|
Undefined labels CastError {
typeswitch (o) {
case (o: Undefined): {
return o;
}
case (o: FixedArray): {
return o;
}
case (Object): {
goto CastError;
}
}
}
Cast<JSProxy|Null>(o: HeapObject): JSProxy|Null labels CastError {
typeswitch (o) {
case (o: Null): {
return o;
}
case (o: JSProxy): {
return o;
}
case (Object): {
goto CastError;
}
}
}
macro Is<A : type extends Object, B : type extends Object>(
implicit context: Context)(o: B): bool {
Cast<A>(o) otherwise return false;
return true;
}
macro UnsafeCast<A : type extends Object>(implicit context: Context)(o: Object):
A {
assert(Is<A>(o));
return %RawDownCast<A>(o);
}
macro UnsafeConstCast<T: type>(r: const &T):&T {
return %RawDownCast<&T>(r);
}
UnsafeCast<RegExpMatchInfo>(implicit context: Context)(o: Object):
RegExpMatchInfo {
assert(Is<FixedArray>(o));
return %RawDownCast<RegExpMatchInfo>(o);
}
macro CastOrDefault<T: type, Arg: type, Default: type>(
implicit context: Context)(x: Arg, default: Default): T|Default {
return Cast<T>(x) otherwise return default;
}