1// Copyright 2020 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 5#include 'src/builtins/builtins-wasm-gen.h' 6 7namespace runtime { 8extern runtime WasmMemoryGrow(Context, WasmInstanceObject, Smi): Smi; 9extern runtime WasmRefFunc(Context, WasmInstanceObject, Smi): JSAny; 10extern runtime WasmTableInit( 11 Context, WasmInstanceObject, Object, Object, Smi, Smi, Smi): JSAny; 12extern runtime WasmTableCopy( 13 Context, WasmInstanceObject, Object, Object, Smi, Smi, Smi): JSAny; 14extern runtime WasmTableFill( 15 Context, WasmInstanceObject, Smi, Smi, Object, Smi): JSAny; 16extern runtime WasmTableGrow( 17 Context, WasmInstanceObject, Smi, Object, Smi): Smi; 18extern runtime WasmFunctionTableGet( 19 Context, WasmInstanceObject, Smi, Smi): JSAny; 20extern runtime WasmFunctionTableSet( 21 Context, WasmInstanceObject, Smi, Smi, Object): JSAny; 22extern runtime ThrowWasmError(Context, Smi): JSAny; 23extern runtime WasmThrow(Context, Object, FixedArray): JSAny; 24extern runtime WasmReThrow(Context, Object): JSAny; 25extern runtime WasmTriggerTierUp(Context, WasmInstanceObject): JSAny; 26extern runtime WasmStackGuard(Context): JSAny; 27extern runtime ThrowWasmStackOverflow(Context): JSAny; 28extern runtime WasmTraceMemory(Context, Smi): JSAny; 29extern runtime WasmTraceEnter(Context): JSAny; 30extern runtime WasmTraceExit(Context, Smi): JSAny; 31extern runtime WasmAtomicNotify( 32 Context, WasmInstanceObject, Number, Number): Smi; 33extern runtime WasmI32AtomicWait( 34 Context, WasmInstanceObject, Number, Number, BigInt): Smi; 35extern runtime WasmI64AtomicWait( 36 Context, WasmInstanceObject, Number, BigInt, BigInt): Smi; 37extern runtime WasmArrayCopy( 38 Context, WasmArray, Smi, WasmArray, Smi, Smi): JSAny; 39extern runtime WasmArrayInitFromData( 40 Context, WasmInstanceObject, Smi, Smi, Smi, Map): Object; 41} 42 43namespace unsafe { 44extern macro TimesTaggedSize(intptr): intptr; 45extern macro Allocate(intptr, constexpr AllocationFlag): HeapObject; 46extern macro AllocateWasmArray( 47 intptr, constexpr InitializationMode): HeapObject; 48} 49 50namespace wasm { 51const kAnyTableType: constexpr int31 52 generates 'wasm::kWasmAnyRef.raw_bit_field()'; 53const kAnyNonNullTableType: constexpr int31 54 generates 'wasm::kWasmAnyNonNullableRef.raw_bit_field()'; 55 56extern macro WasmBuiltinsAssembler::LoadInstanceFromFrame(): WasmInstanceObject; 57 58// WasmInstanceObject has a field layout that Torque can't handle yet. 59// TODO(bbudge) Eliminate these functions when Torque is ready. 60extern macro WasmBuiltinsAssembler::LoadContextFromInstance(WasmInstanceObject): 61 NativeContext; 62extern macro WasmBuiltinsAssembler::LoadTablesFromInstance(WasmInstanceObject): 63 FixedArray; 64extern macro WasmBuiltinsAssembler::LoadInternalFunctionsFromInstance( 65 WasmInstanceObject): FixedArray; 66extern macro WasmBuiltinsAssembler::LoadManagedObjectMapsFromInstance( 67 WasmInstanceObject): FixedArray; 68 69macro LoadContextFromFrame(): NativeContext { 70 return LoadContextFromInstance(LoadInstanceFromFrame()); 71} 72 73builtin WasmInt32ToHeapNumber(val: int32): HeapNumber { 74 return AllocateHeapNumberWithValue(Convert<float64>(val)); 75} 76 77builtin WasmFuncRefToJS(val: WasmInternalFunction|Null): JSFunction|Null| 78 Undefined { 79 typeswitch (val) { 80 case (Null): { 81 return Null; 82 } 83 case (func: WasmInternalFunction): { 84 return func.external; 85 } 86 } 87} 88 89builtin WasmTaggedNonSmiToInt32(implicit context: Context)(val: JSAnyNotSmi): 90 int32 { 91 return ChangeTaggedNonSmiToInt32(val); 92} 93 94builtin WasmTaggedToFloat64(implicit context: Context)(val: JSAny): float64 { 95 return ChangeTaggedToFloat64(val); 96} 97 98builtin WasmMemoryGrow(numPages: int32): int32 { 99 if (!IsValidPositiveSmi(ChangeInt32ToIntPtr(numPages))) 100 return Int32Constant(-1); 101 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 102 const context: NativeContext = LoadContextFromInstance(instance); 103 const result: Smi = 104 runtime::WasmMemoryGrow(context, instance, SmiFromInt32(numPages)); 105 return SmiToInt32(result); 106} 107 108builtin WasmTableInit( 109 dstRaw: uint32, srcRaw: uint32, sizeRaw: uint32, tableIndex: Smi, 110 segmentIndex: Smi): JSAny { 111 try { 112 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 113 const dst: Smi = Convert<PositiveSmi>(dstRaw) otherwise TableOutOfBounds; 114 const src: Smi = Convert<PositiveSmi>(srcRaw) otherwise TableOutOfBounds; 115 const size: Smi = Convert<PositiveSmi>(sizeRaw) otherwise TableOutOfBounds; 116 tail runtime::WasmTableInit( 117 LoadContextFromInstance(instance), instance, tableIndex, segmentIndex, 118 dst, src, size); 119 } label TableOutOfBounds deferred { 120 tail ThrowWasmTrapTableOutOfBounds(); 121 } 122} 123 124builtin WasmTableCopy( 125 dstRaw: uint32, srcRaw: uint32, sizeRaw: uint32, dstTable: Smi, 126 srcTable: Smi): JSAny { 127 try { 128 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 129 const dst: Smi = Convert<PositiveSmi>(dstRaw) otherwise TableOutOfBounds; 130 const src: Smi = Convert<PositiveSmi>(srcRaw) otherwise TableOutOfBounds; 131 const size: Smi = Convert<PositiveSmi>(sizeRaw) otherwise TableOutOfBounds; 132 tail runtime::WasmTableCopy( 133 LoadContextFromInstance(instance), instance, dstTable, srcTable, dst, 134 src, size); 135 } label TableOutOfBounds deferred { 136 tail ThrowWasmTrapTableOutOfBounds(); 137 } 138} 139 140builtin WasmTableFill( 141 table: Smi, startRaw: uint32, countRaw: uint32, value: Object): JSAny { 142 try { 143 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 144 const start: Smi = 145 Convert<PositiveSmi>(startRaw) otherwise TableOutOfBounds; 146 const count: Smi = 147 Convert<PositiveSmi>(countRaw) otherwise TableOutOfBounds; 148 tail runtime::WasmTableFill( 149 LoadContextFromInstance(instance), instance, table, start, value, 150 count); 151 } label TableOutOfBounds deferred { 152 tail ThrowWasmTrapTableOutOfBounds(); 153 } 154} 155 156builtin WasmTableGrow(table: Smi, deltaRaw: uint32, value: Object): Smi { 157 try { 158 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 159 const delta: Smi = 160 Convert<PositiveSmi>(deltaRaw) otherwise TableOutOfBounds; 161 tail runtime::WasmTableGrow( 162 LoadContextFromInstance(instance), instance, table, value, delta); 163 } label TableOutOfBounds deferred { 164 return -1; 165 } 166} 167 168builtin WasmTableGet(tableIndex: intptr, index: int32): Object { 169 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 170 const entryIndex: intptr = ChangeInt32ToIntPtr(index); 171 try { 172 dcheck(IsValidPositiveSmi(tableIndex)); 173 if (!IsValidPositiveSmi(entryIndex)) goto IndexOutOfRange; 174 175 const tables: FixedArray = LoadTablesFromInstance(instance); 176 const table: WasmTableObject = %RawDownCast<WasmTableObject>( 177 LoadFixedArrayElement(tables, tableIndex)); 178 const entriesCount: intptr = Convert<intptr, Smi>(table.current_length); 179 if (entryIndex >= entriesCount) goto IndexOutOfRange; 180 181 const entries: FixedArray = table.entries; 182 const entry: Object = LoadFixedArrayElement(entries, entryIndex); 183 184 try { 185 const entryObject: HeapObject = 186 TaggedToHeapObject<HeapObject>(entry) otherwise ReturnEntry; 187 if (IsTuple2Map(entryObject.map)) goto CallRuntime; 188 goto ReturnEntry; 189 } label ReturnEntry { 190 return entry; 191 } 192 } label CallRuntime deferred { 193 tail runtime::WasmFunctionTableGet( 194 LoadContextFromInstance(instance), instance, SmiFromIntPtr(tableIndex), 195 SmiFromIntPtr(entryIndex)); 196 } label IndexOutOfRange deferred { 197 tail ThrowWasmTrapTableOutOfBounds(); 198 } 199} 200 201builtin WasmTableSet(tableIndex: intptr, index: int32, value: Object): Object { 202 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 203 const entryIndex: intptr = ChangeInt32ToIntPtr(index); 204 try { 205 dcheck(IsValidPositiveSmi(tableIndex)); 206 if (!IsValidPositiveSmi(entryIndex)) goto IndexOutOfRange; 207 208 const tables: FixedArray = LoadTablesFromInstance(instance); 209 const table: WasmTableObject = %RawDownCast<WasmTableObject>( 210 LoadFixedArrayElement(tables, tableIndex)); 211 212 // Fall back to the runtime to set funcrefs, since we have to update 213 // function dispatch tables. 214 // TODO(7748): Update this if further table types are supported. 215 const tableType: Smi = table.raw_type; 216 if (tableType != SmiConstant(kAnyTableType) && 217 tableType != SmiConstant(kAnyNonNullTableType)) { 218 goto CallRuntime; 219 } 220 221 const entriesCount: intptr = Convert<intptr, Smi>(table.current_length); 222 if (entryIndex >= entriesCount) goto IndexOutOfRange; 223 224 const entries: FixedArray = table.entries; 225 StoreFixedArrayElement(entries, entryIndex, value); 226 return Undefined; 227 } label CallRuntime deferred { 228 tail runtime::WasmFunctionTableSet( 229 LoadContextFromInstance(instance), instance, SmiFromIntPtr(tableIndex), 230 SmiFromIntPtr(entryIndex), value); 231 } label IndexOutOfRange deferred { 232 tail ThrowWasmTrapTableOutOfBounds(); 233 } 234} 235 236builtin WasmRefFunc(index: uint32): Object { 237 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 238 try { 239 const table: FixedArray = LoadInternalFunctionsFromInstance(instance); 240 if (table == Undefined) goto CallRuntime; 241 const functionIndex: intptr = Signed(ChangeUint32ToWord(index)); 242 const result: Object = LoadFixedArrayElement(table, functionIndex); 243 if (result == Undefined) goto CallRuntime; 244 return result; 245 } label CallRuntime deferred { 246 tail runtime::WasmRefFunc( 247 LoadContextFromInstance(instance), instance, SmiFromUint32(index)); 248 } 249} 250 251builtin WasmAllocateFixedArray(size: intptr): FixedArray { 252 if (size == 0) return kEmptyFixedArray; 253 return UnsafeCast<FixedArray>(AllocateFixedArray( 254 ElementsKind::PACKED_ELEMENTS, size, AllocationFlag::kNone)); 255} 256 257builtin WasmThrow(tag: Object, values: FixedArray): JSAny { 258 tail runtime::WasmThrow(LoadContextFromFrame(), tag, values); 259} 260 261builtin WasmRethrow(exception: Object): JSAny { 262 if (exception == Null) tail ThrowWasmTrapRethrowNull(); 263 tail runtime::WasmReThrow(LoadContextFromFrame(), exception); 264} 265 266// We need this for frames that do not have the instance in the parameters. 267// Currently, this is CapiCallWrapper frames. 268builtin WasmRethrowExplicitContext( 269 exception: Object, explicitContext: Context): JSAny { 270 if (exception == Null) tail ThrowWasmTrapRethrowNull(); 271 tail runtime::WasmReThrow(explicitContext, exception); 272} 273 274builtin WasmTriggerTierUp(): JSAny { 275 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 276 tail runtime::WasmTriggerTierUp(LoadContextFromFrame(), instance); 277} 278 279builtin WasmStackGuard(): JSAny { 280 tail runtime::WasmStackGuard(LoadContextFromFrame()); 281} 282 283builtin WasmStackOverflow(): JSAny { 284 tail runtime::ThrowWasmStackOverflow(LoadContextFromFrame()); 285} 286 287builtin WasmTraceMemory(info: Smi): JSAny { 288 tail runtime::WasmTraceMemory(LoadContextFromFrame(), info); 289} 290 291builtin WasmTraceEnter(): JSAny { 292 tail runtime::WasmTraceEnter(LoadContextFromFrame()); 293} 294 295builtin WasmTraceExit(info: Smi): JSAny { 296 tail runtime::WasmTraceExit(LoadContextFromFrame(), info); 297} 298 299builtin WasmAllocateJSArray(implicit context: Context)(size: Smi): JSArray { 300 const map: Map = GetFastPackedElementsJSArrayMap(); 301 return AllocateJSArray(ElementsKind::PACKED_ELEMENTS, map, size, size); 302} 303 304builtin WasmAllocateStructWithRtt(rtt: Map): HeapObject { 305 const typeInfo: WasmTypeInfo = %RawDownCast<WasmTypeInfo>( 306 rtt.constructor_or_back_pointer_or_native_context); 307 const instanceSize: intptr = SmiUntag(typeInfo.instance_size); 308 const result: HeapObject = unsafe::Allocate( 309 instanceSize, AllocationFlag::kAllowLargeObjectAllocation); 310 *UnsafeConstCast(&result.map) = rtt; 311 // TODO(ishell): consider removing properties_or_hash field from WasmObjects. 312 %RawDownCast<WasmStruct>(result).properties_or_hash = kEmptyFixedArray; 313 return result; 314} 315 316macro WasmAllocateArray( 317 rtt: Map, length: uint32, elementSize: uint32, 318 initializationMode: constexpr InitializationMode): HeapObject { 319 // instanceSize = RoundUp(elementSize * length, kObjectAlignment) 320 // + WasmArray::kHeaderSize 321 const instanceSize: intptr = 322 torque_internal::AlignTagged( 323 Convert<intptr>(length) * Convert<intptr>(elementSize)) + 324 Convert<intptr>(kWasmArrayHeaderSize); 325 const result: HeapObject = 326 unsafe::AllocateWasmArray(instanceSize, initializationMode); 327 *UnsafeConstCast(&result.map) = rtt; 328 // TODO(ishell): consider removing properties_or_hash field from WasmObjects. 329 %RawDownCast<WasmArray>(result).properties_or_hash = kEmptyFixedArray; 330 %RawDownCast<WasmArray>(result).length = length; 331 return result; 332} 333 334builtin WasmAllocateArray_Uninitialized( 335 rtt: Map, length: uint32, elementSize: uint32): HeapObject { 336 return WasmAllocateArray( 337 rtt, length, elementSize, InitializationMode::kUninitialized); 338} 339 340builtin WasmAllocateArray_InitZero( 341 rtt: Map, length: uint32, elementSize: uint32): HeapObject { 342 return WasmAllocateArray( 343 rtt, length, elementSize, InitializationMode::kInitializeToZero); 344} 345 346builtin WasmAllocateArray_InitNull( 347 rtt: Map, length: uint32, elementSize: uint32): HeapObject { 348 return WasmAllocateArray( 349 rtt, length, elementSize, InitializationMode::kInitializeToNull); 350} 351 352builtin WasmArrayInitFromData( 353 dataSegment: uint32, offset: uint32, length: uint32, rtt: Map): Object { 354 const instance = LoadInstanceFromFrame(); 355 tail runtime::WasmArrayInitFromData( 356 LoadContextFromInstance(instance), instance, SmiFromUint32(dataSegment), 357 SmiFromUint32(offset), SmiFromUint32(length), rtt); 358} 359 360// We put all uint32 parameters at the beginning so that they are assigned to 361// registers. 362builtin WasmArrayCopyWithChecks( 363 dstIndex: uint32, srcIndex: uint32, length: uint32, dstObject: Object, 364 srcObject: Object): JSAny { 365 if (dstObject == Null) tail ThrowWasmTrapNullDereference(); 366 if (srcObject == Null) tail ThrowWasmTrapNullDereference(); 367 const dstArray = %RawDownCast<WasmArray>(dstObject); 368 const srcArray = %RawDownCast<WasmArray>(srcObject); 369 // Check that the end of the copying range is in-bounds and that the range 370 // does not overflow. 371 if (dstIndex + length > dstArray.length || dstIndex + length < dstIndex || 372 srcIndex + length > srcArray.length || srcIndex + length < srcIndex) { 373 tail ThrowWasmTrapArrayOutOfBounds(); 374 } 375 if (length == 0) return Undefined; 376 tail runtime::WasmArrayCopy( 377 LoadContextFromFrame(), dstArray, SmiFromUint32(dstIndex), srcArray, 378 SmiFromUint32(srcIndex), SmiFromUint32(length)); 379} 380 381builtin WasmArrayCopy( 382 dstIndex: uint32, srcIndex: uint32, length: uint32, dstArray: WasmArray, 383 srcArray: WasmArray): JSAny { 384 if (length == 0) return Undefined; 385 tail runtime::WasmArrayCopy( 386 LoadContextFromFrame(), dstArray, SmiFromUint32(dstIndex), srcArray, 387 SmiFromUint32(srcIndex), SmiFromUint32(length)); 388} 389 390// Redeclaration with different typing (value is an Object, not JSAny). 391extern transitioning runtime 392CreateDataProperty(implicit context: Context)(JSReceiver, JSAny, Object): void; 393 394transitioning builtin WasmAllocateObjectWrapper(implicit context: Context)( 395 obj: Object): JSObject { 396 // Note: {obj} can be null, or i31ref. The code below is agnostic to that. 397 const wrapper = NewJSObject(); 398 const symbol = WasmWrappedObjectSymbolConstant(); 399 CreateDataProperty(wrapper, symbol, obj); 400 return wrapper; 401} 402 403builtin WasmSubtypeCheck(objectSupertypes: FixedArray, rtt: Map): int32 { 404 const rttSupertypeLength: Smi = 405 %RawDownCast<WasmTypeInfo>( 406 rtt.constructor_or_back_pointer_or_native_context) 407 .supertypes.length; 408 409 if (objectSupertypes.length <= rttSupertypeLength) { 410 return 0; 411 } 412 413 const supertype: Map = %RawDownCast<Map>( 414 LoadFixedArrayElement(objectSupertypes, rttSupertypeLength)); 415 416 if (supertype == rtt) return 1; 417 return 0; 418} 419 420builtin WasmInt32ToNumber(value: int32): Number { 421 return ChangeInt32ToTagged(value); 422} 423 424builtin WasmUint32ToNumber(value: uint32): Number { 425 return ChangeUint32ToTagged(value); 426} 427 428builtin UintPtr53ToNumber(value: uintptr): Number { 429 if (value <= kSmiMaxValue) return Convert<Smi>(Convert<intptr>(value)); 430 const valueFloat = ChangeUintPtrToFloat64(value); 431 // Values need to be within [0..2^53], such that they can be represented as 432 // float64. 433 dcheck(ChangeFloat64ToUintPtr(valueFloat) == value); 434 return AllocateHeapNumberWithValue(valueFloat); 435} 436 437extern builtin I64ToBigInt(intptr): BigInt; 438 439builtin WasmAtomicNotify(offset: uintptr, count: uint32): uint32 { 440 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 441 const result: Smi = runtime::WasmAtomicNotify( 442 LoadContextFromInstance(instance), instance, UintPtr53ToNumber(offset), 443 WasmUint32ToNumber(count)); 444 return Unsigned(SmiToInt32(result)); 445} 446 447builtin WasmI32AtomicWait64( 448 offset: uintptr, expectedValue: int32, timeout: intptr): uint32 { 449 if constexpr (Is64()) { 450 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 451 const result: Smi = runtime::WasmI32AtomicWait( 452 LoadContextFromInstance(instance), instance, UintPtr53ToNumber(offset), 453 WasmInt32ToNumber(expectedValue), I64ToBigInt(timeout)); 454 return Unsigned(SmiToInt32(result)); 455 } else { 456 unreachable; 457 } 458} 459 460builtin WasmI64AtomicWait64( 461 offset: uintptr, expectedValue: intptr, timeout: intptr): uint32 { 462 if constexpr (Is64()) { 463 const instance: WasmInstanceObject = LoadInstanceFromFrame(); 464 const result: Smi = runtime::WasmI64AtomicWait( 465 LoadContextFromInstance(instance), instance, UintPtr53ToNumber(offset), 466 I64ToBigInt(expectedValue), I64ToBigInt(timeout)); 467 return Unsigned(SmiToInt32(result)); 468 } else { 469 unreachable; 470 } 471} 472 473// Type feedback collection support for `call_ref`. 474 475extern macro GetCodeEntry(Code): RawPtr; 476extern macro GetCodeEntry(CodeDataContainer): RawPtr; 477 478struct TargetAndInstance { 479 target: RawPtr; 480 instance: HeapObject; // WasmInstanceObject or WasmApiFunctionRef 481} 482 483macro GetTargetAndInstance(funcref: WasmInternalFunction): TargetAndInstance { 484 const ref = funcref.ref; 485 let target = funcref.foreign_address_ptr; 486 if (Signed(target) == IntPtrConstant(0)) { 487 target = GetCodeEntry(funcref.code); 488 } 489 return TargetAndInstance{target: target, instance: ref}; 490} 491 492// Vector format: 493// Two slots per call_ref instruction. These slots' values can be: 494// - uninitialized: (0, <unused>). Note: we use {0} as the sentinel because 495// it also works as default for vector slots used as counts. 496// - monomorphic: (funcref, count (smi)). The second slot is a counter for how 497// often the funcref in the first slot has been seen. 498// - polymorphic: (fixed_array, <unused>). In this case, the array 499// contains 2..4 pairs (funcref, count (smi)) (like monomorphic data). 500// - megamorphic: ("megamorphic" sentinel, <unused>) 501// 502// TODO(rstz): The counter might overflow if it exceeds the range of a Smi. 503// This can lead to incorrect inlining decisions. 504builtin CallRefIC( 505 vector: FixedArray, index: intptr, 506 funcref: WasmInternalFunction): TargetAndInstance { 507 const value = vector.objects[index]; 508 if (value == funcref) { 509 // Monomorphic hit. Check for this case first to maximize its performance. 510 const count = UnsafeCast<Smi>(vector.objects[index + 1]) + SmiConstant(1); 511 vector.objects[index + 1] = count; 512 return GetTargetAndInstance(funcref); 513 } 514 // Check for polymorphic hit; its performance is second-most-important. 515 if (Is<FixedArray>(value)) { 516 const entries = UnsafeCast<FixedArray>(value); 517 for (let i: intptr = 0; i < entries.length_intptr; i += 2) { 518 if (entries.objects[i] == funcref) { 519 // Polymorphic hit. 520 const count = UnsafeCast<Smi>(entries.objects[i + 1]) + SmiConstant(1); 521 entries.objects[i + 1] = count; 522 return GetTargetAndInstance(funcref); 523 } 524 } 525 } 526 // All other cases are some sort of miss and must compute the target/ 527 // instance. They all fall through to returning the computed data. 528 const result = GetTargetAndInstance(funcref); 529 if (TaggedEqual(value, SmiConstant(0))) { 530 // Was uninitialized. 531 vector.objects[index] = funcref; 532 vector.objects[index + 1] = SmiConstant(1); 533 } else if (Is<FixedArray>(value)) { 534 // Polymorphic miss. 535 const entries = UnsafeCast<FixedArray>(value); 536 if (entries.length == SmiConstant(8)) { // 4 entries, 2 slots each. 537 vector.objects[index] = ic::kMegamorphicSymbol; 538 vector.objects[index + 1] = ic::kMegamorphicSymbol; 539 } else { 540 const newEntries = UnsafeCast<FixedArray>(AllocateFixedArray( 541 ElementsKind::PACKED_ELEMENTS, entries.length_intptr + 2, 542 AllocationFlag::kNone)); 543 for (let i: intptr = 0; i < entries.length_intptr; i++) { 544 newEntries.objects[i] = entries.objects[i]; 545 } 546 const newIndex = entries.length_intptr; 547 newEntries.objects[newIndex] = funcref; 548 newEntries.objects[newIndex + 1] = SmiConstant(1); 549 vector.objects[index] = newEntries; 550 } 551 } else if (Is<WasmInternalFunction>(value)) { 552 // Monomorphic miss. 553 const newEntries = UnsafeCast<FixedArray>(AllocateFixedArray( 554 ElementsKind::PACKED_ELEMENTS, 4, AllocationFlag::kNone)); 555 newEntries.objects[0] = value; 556 newEntries.objects[1] = vector.objects[index + 1]; 557 newEntries.objects[2] = funcref; 558 newEntries.objects[3] = SmiConstant(1); 559 vector.objects[index] = newEntries; 560 // Clear the first entry's counter; the specific value we write doesn't 561 // matter. 562 vector.objects[index + 1] = Undefined; 563 } 564 // The "ic::IsMegamorphic(value)" case doesn't need to do anything. 565 return result; 566} 567 568extern macro TryHasOwnProperty(HeapObject, Map, InstanceType, Name): never 569 labels Found, NotFound, Bailout; 570type OnNonExistent constexpr 'OnNonExistent'; 571const kReturnUndefined: constexpr OnNonExistent 572 generates 'OnNonExistent::kReturnUndefined'; 573extern macro SmiConstant(constexpr OnNonExistent): Smi; 574extern transitioning builtin GetPropertyWithReceiver(implicit context: Context)( 575 JSAny, Name, JSAny, Smi): JSAny; 576 577transitioning builtin WasmGetOwnProperty(implicit context: Context)( 578 object: Object, uniqueName: Name): JSAny { 579 try { 580 const heapObject: HeapObject = 581 TaggedToHeapObject(object) otherwise NotFound; 582 const receiver: JSReceiver = 583 Cast<JSReceiver>(heapObject) otherwise NotFound; 584 try { 585 TryHasOwnProperty( 586 receiver, receiver.map, receiver.instanceType, uniqueName) 587 otherwise Found, NotFound, NotFound; 588 } label Found { 589 tail GetPropertyWithReceiver( 590 receiver, uniqueName, receiver, SmiConstant(kReturnUndefined)); 591 } 592 } label NotFound deferred { 593 return Undefined; 594 } 595} 596 597// Trap builtins. 598 599builtin WasmTrap(error: Smi): JSAny { 600 tail runtime::ThrowWasmError(LoadContextFromFrame(), error); 601} 602 603builtin ThrowWasmTrapUnreachable(): JSAny { 604 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapUnreachable)); 605} 606 607builtin ThrowWasmTrapMemOutOfBounds(): JSAny { 608 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapMemOutOfBounds)); 609} 610 611builtin ThrowWasmTrapUnalignedAccess(): JSAny { 612 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapUnalignedAccess)); 613} 614 615builtin ThrowWasmTrapDivByZero(): JSAny { 616 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapDivByZero)); 617} 618 619builtin ThrowWasmTrapDivUnrepresentable(): JSAny { 620 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapDivUnrepresentable)); 621} 622 623builtin ThrowWasmTrapRemByZero(): JSAny { 624 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapRemByZero)); 625} 626 627builtin ThrowWasmTrapFloatUnrepresentable(): JSAny { 628 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapFloatUnrepresentable)); 629} 630 631builtin ThrowWasmTrapFuncSigMismatch(): JSAny { 632 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapFuncSigMismatch)); 633} 634 635builtin ThrowWasmTrapDataSegmentOutOfBounds(): JSAny { 636 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapDataSegmentOutOfBounds)); 637} 638 639builtin ThrowWasmTrapElemSegmentDropped(): JSAny { 640 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapElemSegmentDropped)); 641} 642 643builtin ThrowWasmTrapTableOutOfBounds(): JSAny { 644 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapTableOutOfBounds)); 645} 646 647builtin ThrowWasmTrapRethrowNull(): JSAny { 648 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapRethrowNull)); 649} 650 651builtin ThrowWasmTrapNullDereference(): JSAny { 652 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapNullDereference)); 653} 654 655builtin ThrowWasmTrapIllegalCast(): JSAny { 656 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapIllegalCast)); 657} 658 659builtin ThrowWasmTrapArrayOutOfBounds(): JSAny { 660 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapArrayOutOfBounds)); 661} 662 663builtin ThrowWasmTrapArrayTooLarge(): JSAny { 664 tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapArrayTooLarge)); 665} 666} 667