1// Copyright 2019 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5extern macro IsBigInt(HeapObject): bool; 6extern macro IsConstructor(HeapObject): bool; 7extern macro IsCustomElementsReceiverInstanceType(int32): bool; 8extern macro IsExtensibleMap(Map): bool; 9extern macro IsNumberNormalized(Number): bool; 10extern macro IsSafeInteger(Object): bool; 11 12@export 13macro IsAccessorInfo(o: HeapObject): bool { 14 return Is<AccessorInfo>(o); 15} 16 17@export 18macro IsAccessorPair(o: HeapObject): bool { 19 return Is<AccessorPair>(o); 20} 21 22@export 23macro IsAllocationSite(o: HeapObject): bool { 24 return Is<AllocationSite>(o); 25} 26 27@export 28macro IsCell(o: HeapObject): bool { 29 return Is<Cell>(o); 30} 31 32@export 33macro IsCode(o: HeapObject): bool { 34 return Is<Code>(o); 35} 36 37@export 38macro IsCodeDataContainer(o: HeapObject): bool { 39 return Is<CodeDataContainer>(o); 40} 41 42@export 43macro IsContext(o: HeapObject): bool { 44 return Is<Context>(o); 45} 46 47@export 48macro IsCoverageInfo(o: HeapObject): bool { 49 return Is<CoverageInfo>(o); 50} 51 52@export 53macro IsDebugInfo(o: HeapObject): bool { 54 return Is<DebugInfo>(o); 55} 56 57@export 58macro IsFixedDoubleArray(o: HeapObject): bool { 59 return Is<FixedDoubleArray>(o); 60} 61 62@export 63macro IsFeedbackCell(o: HeapObject): bool { 64 return Is<FeedbackCell>(o); 65} 66 67@export 68macro IsFeedbackVector(o: HeapObject): bool { 69 return Is<FeedbackVector>(o); 70} 71 72@export 73macro IsHeapNumber(o: HeapObject): bool { 74 return Is<HeapNumber>(o); 75} 76 77@export 78macro IsNativeContext(o: HeapObject): bool { 79 return Is<NativeContext>(o); 80} 81 82@export 83macro IsNumber(o: Object): bool { 84 return Is<Number>(o); 85} 86 87@export 88macro IsPrivateSymbol(o: HeapObject): bool { 89 return Is<PrivateSymbol>(o); 90} 91 92@export 93macro IsPromiseCapability(o: HeapObject): bool { 94 return Is<PromiseCapability>(o); 95} 96 97@export 98macro IsPromiseFulfillReactionJobTask(o: HeapObject): bool { 99 return Is<PromiseFulfillReactionJobTask>(o); 100} 101 102@export 103macro IsPromiseReaction(o: HeapObject): bool { 104 return Is<PromiseReaction>(o); 105} 106 107@export 108macro IsPromiseRejectReactionJobTask(o: HeapObject): bool { 109 return Is<PromiseRejectReactionJobTask>(o); 110} 111 112@export 113macro IsSharedFunctionInfo(o: HeapObject): bool { 114 return Is<SharedFunctionInfo>(o); 115} 116 117@export 118macro IsSymbol(o: HeapObject): bool { 119 return Is<Symbol>(o); 120} 121 122extern macro TaggedToHeapObject(Object): HeapObject 123 labels CastError; 124extern macro TaggedToSmi(Object): Smi 125 labels CastError; 126extern macro TaggedToPositiveSmi(Object): PositiveSmi 127 labels CastError; 128extern macro TaggedToDirectString(Object): DirectString 129 labels CastError; 130extern macro HeapObjectToCallable(HeapObject): Callable 131 labels CastError; 132extern macro HeapObjectToConstructor(HeapObject): Constructor 133 labels CastError; 134extern macro HeapObjectToJSFunctionWithPrototypeSlot(HeapObject): 135 JSFunctionWithPrototypeSlot 136 labels CastError; 137 138macro Cast<A : type extends WeakHeapObject>(o: A|Object): A labels CastError { 139 if (!IsWeakOrCleared(o)) goto CastError; 140 return %RawDownCast<A>(o); 141} 142 143macro Cast<A : type extends Object>(implicit context: Context)(o: MaybeObject): 144 A labels CastError { 145 typeswitch (o) { 146 case (WeakHeapObject): { 147 goto CastError; 148 } 149 case (o: Object): { 150 return Cast<A>(o) otherwise CastError; 151 } 152 } 153} 154 155Cast<Undefined>(o: MaybeObject): Undefined labels CastError { 156 if (TaggedNotEqual(o, Undefined)) goto CastError; 157 return %RawDownCast<Undefined>(o); 158} 159 160macro Cast<A : type extends Object>(implicit context: Context)(o: Object): A 161 labels CastError { 162 return Cast<A>(TaggedToHeapObject(o) otherwise CastError) 163 otherwise CastError; 164} 165 166// This is required for casting MaybeObject to Object. 167Cast<Smi>(o: Object): Smi 168 labels CastError { 169 return TaggedToSmi(o) otherwise CastError; 170} 171 172Cast<PositiveSmi>(o: Object): PositiveSmi 173 labels CastError { 174 return TaggedToPositiveSmi(o) otherwise CastError; 175} 176 177Cast<Zero>(o: Object): Zero labels CastError { 178 if (TaggedEqual(o, SmiConstant(0))) return %RawDownCast<Zero>(o); 179 goto CastError; 180} 181 182Cast<Number>(o: Object): Number 183 labels CastError { 184 typeswitch (o) { 185 case (s: Smi): { 186 return s; 187 } 188 case (n: HeapNumber): { 189 return n; 190 } 191 case (Object): { 192 goto CastError; 193 } 194 } 195} 196 197Cast<Undefined>(o: Object): Undefined 198 labels CastError { 199 const o: MaybeObject = o; 200 return Cast<Undefined>(o) otherwise CastError; 201} 202 203Cast<Numeric>(o: Object): Numeric labels CastError { 204 typeswitch (o) { 205 case (o: Number): { 206 return o; 207 } 208 case (o: BigInt): { 209 return o; 210 } 211 case (HeapObject): { 212 goto CastError; 213 } 214 } 215} 216 217Cast<TheHole>(o: Object): TheHole labels CastError { 218 if (o == TheHole) return %RawDownCast<TheHole>(o); 219 goto CastError; 220} 221 222Cast<TheHole>(o: HeapObject): TheHole labels CastError { 223 const o: Object = o; 224 return Cast<TheHole>(o) otherwise CastError; 225} 226 227Cast<True>(o: Object): True labels CastError { 228 if (o == True) return %RawDownCast<True>(o); 229 goto CastError; 230} 231 232Cast<True>(o: HeapObject): True labels CastError { 233 const o: Object = o; 234 return Cast<True>(o) otherwise CastError; 235} 236 237Cast<False>(o: Object): False labels CastError { 238 if (o == False) return %RawDownCast<False>(o); 239 goto CastError; 240} 241 242Cast<False>(o: HeapObject): False labels CastError { 243 const o: Object = o; 244 return Cast<False>(o) otherwise CastError; 245} 246 247Cast<Boolean>(o: Object): Boolean labels CastError { 248 typeswitch (o) { 249 case (o: True): { 250 return o; 251 } 252 case (o: False): { 253 return o; 254 } 255 case (Object): { 256 goto CastError; 257 } 258 } 259} 260 261Cast<Boolean>(o: HeapObject): Boolean labels CastError { 262 const o: Object = o; 263 return Cast<Boolean>(o) otherwise CastError; 264} 265 266// TODO(turbofan): These trivial casts for union types should be generated 267// automatically. 268 269Cast<JSPrimitive>(o: Object): JSPrimitive labels CastError { 270 typeswitch (o) { 271 case (o: Numeric): { 272 return o; 273 } 274 case (o: String): { 275 return o; 276 } 277 case (o: Symbol): { 278 return o; 279 } 280 case (o: Boolean): { 281 return o; 282 } 283 case (o: Undefined): { 284 return o; 285 } 286 case (o: Null): { 287 return o; 288 } 289 case (Object): { 290 goto CastError; 291 } 292 } 293} 294 295Cast<JSAny>(o: Object): JSAny labels CastError { 296 typeswitch (o) { 297 case (o: JSPrimitive): { 298 return o; 299 } 300 case (o: JSReceiver): { 301 return o; 302 } 303 case (Object): { 304 goto CastError; 305 } 306 } 307} 308 309Cast<JSAny|TheHole>(o: Object): JSAny|TheHole labels CastError { 310 typeswitch (o) { 311 case (o: JSAny): { 312 return o; 313 } 314 case (o: TheHole): { 315 return o; 316 } 317 case (Object): { 318 goto CastError; 319 } 320 } 321} 322 323Cast<Number|TheHole>(o: Object): Number|TheHole labels CastError { 324 typeswitch (o) { 325 case (o: Number): { 326 return o; 327 } 328 case (o: TheHole): { 329 return o; 330 } 331 case (Object): { 332 goto CastError; 333 } 334 } 335} 336 337Cast<Context|Zero|Undefined>(o: Object): Context|Zero|Undefined 338 labels CastError { 339 typeswitch (o) { 340 case (o: Context): { 341 return o; 342 } 343 case (o: Zero): { 344 return o; 345 } 346 case (o: Undefined): { 347 return o; 348 } 349 case (Object): { 350 goto CastError; 351 } 352 } 353} 354 355macro Cast<A : type extends HeapObject>(o: HeapObject): A 356 labels CastError; 357 358Cast<HeapObject>(o: HeapObject): HeapObject 359labels _CastError { 360 return o; 361} 362 363Cast<Null>(o: HeapObject): Null 364 labels CastError { 365 if (o != Null) goto CastError; 366 return %RawDownCast<Null>(o); 367} 368 369Cast<Undefined>(o: HeapObject): Undefined 370 labels CastError { 371 const o: MaybeObject = o; 372 return Cast<Undefined>(o) otherwise CastError; 373} 374 375Cast<EmptyFixedArray>(o: Object): EmptyFixedArray 376 labels CastError { 377 if (o != kEmptyFixedArray) goto CastError; 378 return %RawDownCast<EmptyFixedArray>(o); 379} 380Cast<EmptyFixedArray>(o: HeapObject): EmptyFixedArray 381 labels CastError { 382 const o: Object = o; 383 return Cast<EmptyFixedArray>(o) otherwise CastError; 384} 385 386Cast<(FixedDoubleArray | EmptyFixedArray)>(o: HeapObject): FixedDoubleArray| 387 EmptyFixedArray labels CastError { 388 typeswitch (o) { 389 case (o: EmptyFixedArray): { 390 return o; 391 } 392 case (o: FixedDoubleArray): { 393 return o; 394 } 395 case (HeapObject): { 396 goto CastError; 397 } 398 } 399} 400 401Cast<Callable>(o: HeapObject): Callable 402 labels CastError { 403 return HeapObjectToCallable(o) otherwise CastError; 404} 405 406Cast<Undefined|Callable>(o: HeapObject): Undefined|Callable 407 labels CastError { 408 if (o == Undefined) return Undefined; 409 return HeapObjectToCallable(o) otherwise CastError; 410} 411 412Cast<Undefined|JSFunction>(o: HeapObject): Undefined|JSFunction 413 labels CastError { 414 if (o == Undefined) return Undefined; 415 return Cast<JSFunction>(o) otherwise CastError; 416} 417 418macro Cast<T : type extends Symbol>(o: Symbol): T labels CastError; 419Cast<PublicSymbol>(s: Symbol): PublicSymbol labels CastError { 420 if (s.flags.is_private) goto CastError; 421 return %RawDownCast<PublicSymbol>(s); 422} 423Cast<PrivateSymbol>(s: Symbol): PrivateSymbol labels CastError { 424 if (s.flags.is_private) return %RawDownCast<PrivateSymbol>(s); 425 goto CastError; 426} 427Cast<PublicSymbol>(o: HeapObject): PublicSymbol labels CastError { 428 const s = Cast<Symbol>(o) otherwise CastError; 429 return Cast<PublicSymbol>(s) otherwise CastError; 430} 431Cast<PrivateSymbol>(o: HeapObject): PrivateSymbol labels CastError { 432 const s = Cast<Symbol>(o) otherwise CastError; 433 return Cast<PrivateSymbol>(s) otherwise CastError; 434} 435 436Cast<DirectString>(o: String): DirectString 437 labels CastError { 438 return TaggedToDirectString(o) otherwise CastError; 439} 440 441Cast<Constructor>(o: HeapObject): Constructor 442 labels CastError { 443 return HeapObjectToConstructor(o) otherwise CastError; 444} 445 446Cast<JSFunctionWithPrototypeSlot>(o: HeapObject): JSFunctionWithPrototypeSlot 447 labels CastError { 448 return HeapObjectToJSFunctionWithPrototypeSlot(o) otherwise CastError; 449} 450 451Cast<BigInt>(o: HeapObject): BigInt labels CastError { 452 if (IsBigInt(o)) return %RawDownCast<BigInt>(o); 453 goto CastError; 454} 455 456Cast<JSRegExpResult>(implicit context: Context)(o: HeapObject): JSRegExpResult 457 labels CastError { 458 if (regexp::IsRegExpResult(o)) return %RawDownCast<JSRegExpResult>(o); 459 goto CastError; 460} 461 462Cast<JSSloppyArgumentsObject>(implicit context: Context)(o: HeapObject): 463 JSSloppyArgumentsObject 464 labels CastError { 465 const map: Map = o.map; 466 if (IsFastAliasedArgumentsMap(map) || IsSloppyArgumentsMap(map) || 467 IsSlowAliasedArgumentsMap(map)) { 468 return %RawDownCast<JSSloppyArgumentsObject>(o); 469 } 470 goto CastError; 471} 472 473Cast<JSStrictArgumentsObject>(implicit context: Context)(o: HeapObject): 474 JSStrictArgumentsObject 475 labels CastError { 476 const map: Map = o.map; 477 if (!IsStrictArgumentsMap(map)) goto CastError; 478 return %RawDownCast<JSStrictArgumentsObject>(o); 479} 480 481Cast<JSArgumentsObjectWithLength>(implicit context: Context)(o: HeapObject): 482 JSArgumentsObjectWithLength 483 labels CastError { 484 typeswitch (o) { 485 case (o: JSStrictArgumentsObject): { 486 return o; 487 } 488 case (o: JSSloppyArgumentsObject): { 489 return o; 490 } 491 case (HeapObject): { 492 goto CastError; 493 } 494 } 495} 496 497Cast<FastJSRegExp>(implicit context: Context)(o: HeapObject): FastJSRegExp 498 labels CastError { 499 // TODO(jgruber): Remove or redesign this. There is no single 'fast' regexp, 500 // the conditions to make a regexp object fast differ based on the callsite. 501 // For now, run the strict variant since replace (the only current callsite) 502 // accesses flag getters. 503 if (regexp::IsFastRegExpStrict(o)) { 504 return %RawDownCast<FastJSRegExp>(o); 505 } 506 goto CastError; 507} 508 509Cast<FastJSArray>(implicit context: Context)(o: HeapObject): FastJSArray 510 labels CastError { 511 if (IsForceSlowPath()) goto CastError; 512 513 if (!Is<JSArray>(o)) goto CastError; 514 515 // Bailout if receiver has slow elements. 516 const map: Map = o.map; 517 const elementsKind: ElementsKind = LoadMapElementsKind(map); 518 if (!IsFastElementsKind(elementsKind)) goto CastError; 519 520 // Verify that our prototype is the initial array prototype. 521 if (!IsPrototypeInitialArrayPrototype(map)) goto CastError; 522 523 if (IsNoElementsProtectorCellInvalid()) goto CastError; 524 return %RawDownCast<FastJSArray>(o); 525} 526 527Cast<FastJSArrayForRead>(implicit context: Context)(o: HeapObject): 528 FastJSArrayForRead 529 labels CastError { 530 if (!Is<JSArray>(o)) goto CastError; 531 532 // Bailout if receiver has slow elements. 533 const map: Map = o.map; 534 const elementsKind: ElementsKind = LoadMapElementsKind(map); 535 if (!IsElementsKindLessThanOrEqual( 536 elementsKind, ElementsKind::LAST_ANY_NONEXTENSIBLE_ELEMENTS_KIND)) 537 goto CastError; 538 539 // Verify that our prototype is the initial array prototype. 540 if (!IsPrototypeInitialArrayPrototype(map)) goto CastError; 541 542 if (IsNoElementsProtectorCellInvalid()) goto CastError; 543 return %RawDownCast<FastJSArrayForRead>(o); 544} 545 546Cast<FastJSArrayForCopy>(implicit context: Context)(o: HeapObject): 547 FastJSArrayForCopy 548 labels CastError { 549 if (IsArraySpeciesProtectorCellInvalid()) goto CastError; 550 // TODO(victorgomes): Check if we can cast from FastJSArrayForRead instead. 551 const a = Cast<FastJSArray>(o) otherwise CastError; 552 return %RawDownCast<FastJSArrayForCopy>(a); 553} 554 555Cast<FastJSArrayForConcat>(implicit context: Context)(o: HeapObject): 556 FastJSArrayForConcat 557 labels CastError { 558 if (IsIsConcatSpreadableProtectorCellInvalid()) goto CastError; 559 const a = Cast<FastJSArrayForCopy>(o) otherwise CastError; 560 return %RawDownCast<FastJSArrayForConcat>(a); 561} 562 563Cast<FastJSArrayWithNoCustomIteration>(implicit context: Context)( 564 o: HeapObject): FastJSArrayWithNoCustomIteration 565 labels CastError { 566 if (IsArrayIteratorProtectorCellInvalid()) goto CastError; 567 const a = Cast<FastJSArray>(o) otherwise CastError; 568 return %RawDownCast<FastJSArrayWithNoCustomIteration>(a); 569} 570 571Cast<FastJSArrayForReadWithNoCustomIteration>(implicit context: Context)( 572 o: HeapObject): FastJSArrayForReadWithNoCustomIteration 573 labels CastError { 574 if (IsArrayIteratorProtectorCellInvalid()) goto CastError; 575 const a = Cast<FastJSArrayForRead>(o) otherwise CastError; 576 return %RawDownCast<FastJSArrayForReadWithNoCustomIteration>(a); 577} 578 579macro Cast<T: type>(o: String): T labels CastError; 580 581Cast<SeqOneByteString>(o: HeapObject): SeqOneByteString labels CastError { 582 return Cast<SeqOneByteString>(Cast<String>(o) otherwise CastError) 583 otherwise CastError; 584} 585 586Cast<SeqOneByteString>(o: String): SeqOneByteString labels CastError { 587 const instanceType = o.StringInstanceType(); 588 // Using & instead of && enables Turbofan to merge the two checks into one. 589 if (!(instanceType.representation == StringRepresentationTag::kSeqStringTag & 590 instanceType.is_one_byte)) { 591 goto CastError; 592 } 593 return %RawDownCast<SeqOneByteString>(o); 594} 595 596Cast<SeqTwoByteString>(o: HeapObject): SeqTwoByteString labels CastError { 597 return Cast<SeqTwoByteString>(Cast<String>(o) otherwise CastError) 598 otherwise CastError; 599} 600 601Cast<SeqTwoByteString>(o: String): SeqTwoByteString labels CastError { 602 const instanceType = o.StringInstanceType(); 603 // Using & instead of && enables Turbofan to merge the two checks into one. 604 if (!(instanceType.representation == StringRepresentationTag::kSeqStringTag & 605 !instanceType.is_one_byte)) { 606 goto CastError; 607 } 608 return %RawDownCast<SeqTwoByteString>(o); 609} 610 611Cast<ThinString>(o: HeapObject): ThinString labels CastError { 612 return Cast<ThinString>(Cast<String>(o) otherwise CastError) 613 otherwise CastError; 614} 615 616Cast<ThinString>(o: String): ThinString labels CastError { 617 const instanceType = o.StringInstanceType(); 618 if (instanceType.representation != StringRepresentationTag::kThinStringTag) { 619 goto CastError; 620 } 621 return %RawDownCast<ThinString>(o); 622} 623 624Cast<ConsString>(o: HeapObject): ConsString labels CastError { 625 return Cast<ConsString>(Cast<String>(o) otherwise CastError) 626 otherwise CastError; 627} 628 629Cast<ConsString>(o: String): ConsString labels CastError { 630 const instanceType = o.StringInstanceType(); 631 if (instanceType.representation != StringRepresentationTag::kConsStringTag) { 632 goto CastError; 633 } 634 return %RawDownCast<ConsString>(o); 635} 636 637Cast<SlicedString>(o: HeapObject): SlicedString labels CastError { 638 return Cast<SlicedString>(Cast<String>(o) otherwise CastError) 639 otherwise CastError; 640} 641 642Cast<SlicedString>(o: String): SlicedString labels CastError { 643 const instanceType = o.StringInstanceType(); 644 if (instanceType.representation != 645 StringRepresentationTag::kSlicedStringTag) { 646 goto CastError; 647 } 648 return %RawDownCast<SlicedString>(o); 649} 650 651Cast<ExternalOneByteString>(o: HeapObject): 652 ExternalOneByteString labels CastError { 653 return Cast<ExternalOneByteString>(Cast<String>(o) otherwise CastError) 654 otherwise CastError; 655} 656 657Cast<ExternalOneByteString>(o: String): ExternalOneByteString labels CastError { 658 const instanceType = o.StringInstanceType(); 659 // Using & instead of && enables Turbofan to merge the two checks into one. 660 if (!(instanceType.representation == 661 StringRepresentationTag::kExternalStringTag & 662 instanceType.is_one_byte)) { 663 goto CastError; 664 } 665 return %RawDownCast<ExternalOneByteString>(o); 666} 667 668Cast<ExternalTwoByteString>(o: HeapObject): 669 ExternalTwoByteString labels CastError { 670 return Cast<ExternalTwoByteString>(Cast<String>(o) otherwise CastError) 671 otherwise CastError; 672} 673 674Cast<ExternalTwoByteString>(o: String): ExternalTwoByteString labels CastError { 675 const instanceType = o.StringInstanceType(); 676 // Using & instead of && enables Turbofan to merge the two checks into one. 677 if (!(instanceType.representation == 678 StringRepresentationTag::kExternalStringTag & 679 !instanceType.is_one_byte)) { 680 goto CastError; 681 } 682 return %RawDownCast<ExternalTwoByteString>(o); 683} 684 685Cast<JSReceiver|Null>(o: HeapObject): JSReceiver|Null 686 labels CastError { 687 typeswitch (o) { 688 case (o: Null): { 689 return o; 690 } 691 case (o: JSReceiver): { 692 return o; 693 } 694 case (HeapObject): { 695 goto CastError; 696 } 697 } 698} 699 700Cast<Smi|PromiseReaction>(o: Object): Smi|PromiseReaction labels CastError { 701 typeswitch (o) { 702 case (o: Smi): { 703 return o; 704 } 705 case (o: PromiseReaction): { 706 return o; 707 } 708 case (Object): { 709 goto CastError; 710 } 711 } 712} 713 714Cast<String|Callable>(implicit context: Context)(o: Object): String| 715 Callable labels CastError { 716 typeswitch (o) { 717 case (o: String): { 718 return o; 719 } 720 case (o: Callable): { 721 return o; 722 } 723 case (Object): { 724 goto CastError; 725 } 726 } 727} 728 729Cast<Zero|PromiseReaction>(implicit context: Context)(o: Object): Zero| 730 PromiseReaction labels CastError { 731 typeswitch (o) { 732 case (o: Zero): { 733 return o; 734 } 735 case (o: PromiseReaction): { 736 return o; 737 } 738 case (Object): { 739 goto CastError; 740 } 741 } 742} 743 744Cast<JSFunction|JSBoundFunction|JSWrappedFunction>(implicit context: Context)( 745 o: Object): JSFunction|JSBoundFunction|JSWrappedFunction labels CastError { 746 typeswitch (o) { 747 case (o: JSFunction): { 748 return o; 749 } 750 case (o: JSBoundFunction): { 751 return o; 752 } 753 case (o: JSWrappedFunction): { 754 return o; 755 } 756 case (Object): { 757 goto CastError; 758 } 759 } 760} 761 762Cast<FixedArray|Undefined>(o: HeapObject): FixedArray| 763 Undefined labels CastError { 764 typeswitch (o) { 765 case (o: Undefined): { 766 return o; 767 } 768 case (o: FixedArray): { 769 return o; 770 } 771 case (Object): { 772 goto CastError; 773 } 774 } 775} 776 777Cast<JSProxy|Null>(o: HeapObject): JSProxy|Null labels CastError { 778 typeswitch (o) { 779 case (o: Null): { 780 return o; 781 } 782 case (o: JSProxy): { 783 return o; 784 } 785 case (Object): { 786 goto CastError; 787 } 788 } 789} 790 791macro Is<A : type extends Object, B : type extends Object>( 792 implicit context: Context)(o: B): bool { 793 Cast<A>(o) otherwise return false; 794 return true; 795} 796 797macro UnsafeCast<A : type extends Object>(implicit context: Context)(o: Object): 798 A { 799 dcheck(Is<A>(o)); 800 return %RawDownCast<A>(o); 801} 802 803macro UnsafeConstCast<T: type>(r: const &T):&T { 804 return %RawDownCast<&T>(r); 805} 806 807UnsafeCast<RegExpMatchInfo>(implicit context: Context)(o: Object): 808 RegExpMatchInfo { 809 dcheck(Is<FixedArray>(o)); 810 return %RawDownCast<RegExpMatchInfo>(o); 811} 812 813macro UnsafeCast<A : type extends WeakHeapObject>(o: A|Object): A { 814 dcheck(IsWeakOrCleared(o)); 815 return %RawDownCast<A>(o); 816} 817 818macro 819CastOrDefault<T: type, Arg: type, Default: type>(implicit context: Context)( 820 x: Arg, default: Default): T|Default { 821 return Cast<T>(x) otherwise return default; 822} 823 824// This is required for casting MaybeObject to Object. 825Cast<Object>(o: Object): Object 826labels _CastError { 827 return o; 828} 829