v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
builtins-typed-array-gen.cc
Go to the documentation of this file.
1// Copyright 2017 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
6
16
17namespace v8 {
18namespace internal {
19
21
22// -----------------------------------------------------------------------------
23// ES6 section 22.2 TypedArray Objects
24
25// Sets the embedder fields to 0 for a TypedArray which is under construction.
27 TNode<JSTypedArray> holder) {
29 for (int offset = JSTypedArray::kHeaderSize;
31 // TODO(v8:10391, saelo): Handle external pointers in EmbedderDataSlot
33 }
34}
35
36// Allocate a new ArrayBuffer and initialize it with empty properties and
37// elements.
38// TODO(bmeurer,v8:4153): Rename this and maybe fix up the implementation a bit.
40 TNode<Context> context) {
42 TNode<Map> map =
43 CAST(LoadContextElement(native_context, Context::ARRAY_BUFFER_MAP_INDEX));
44 TNode<FixedArray> empty_fixed_array = EmptyFixedArrayConstant();
45
48 StoreMapNoWriteBarrier(buffer, map);
49 StoreObjectFieldNoWriteBarrier(buffer, JSArray::kPropertiesOrHashOffset,
50 empty_fixed_array);
51 StoreObjectFieldNoWriteBarrier(buffer, JSArray::kElementsOffset,
52 empty_fixed_array);
53 // Setup the ArrayBuffer.
54 // - Set BitField to 0.
55 // - Set IsExternal and IsDetachable bits of BitFieldSlot.
56 // - Set the byte_length field to zero.
57 // - Set backing_store to null/Tagged<Smi>(0).
58 // - Set extension to null.
59 // - Set all embedder fields to Tagged<Smi>(0).
60 if (FIELD_SIZE(JSArrayBuffer::kOptionalPaddingOffset) != 0) {
61 DCHECK_EQ(4, FIELD_SIZE(JSArrayBuffer::kOptionalPaddingOffset));
63 buffer, JSArrayBuffer::kOptionalPaddingOffset, Int32Constant(0));
64 }
65 int32_t bitfield_value = (1 << JSArrayBuffer::IsExternalBit::kShift) |
66 (1 << JSArrayBuffer::IsDetachableBit::kShift);
67 StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBitFieldOffset,
68 Int32Constant(bitfield_value));
69
70 StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kDetachKeyOffset,
71 UndefinedConstant());
72 StoreBoundedSizeToObject(buffer, JSArrayBuffer::kRawByteLengthOffset,
74 StoreBoundedSizeToObject(buffer, JSArrayBuffer::kRawMaxByteLengthOffset,
76 StoreSandboxedPointerToObject(buffer, JSArrayBuffer::kBackingStoreOffset,
78#ifdef V8_COMPRESS_POINTERS
79 // When pointer compression is enabled, the extension slot contains a
80 // (lazily-initialized) external pointer handle.
81 StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kExtensionOffset,
83#else
84 StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kExtensionOffset,
86#endif
88 for (int offset = JSArrayBuffer::kHeaderSize;
90 // TODO(v8:10391, saelo): Handle external pointers in EmbedderDataSlot
92 }
93 return buffer;
94}
95
96TF_BUILTIN(TypedArrayBaseConstructor, TypedArrayBuiltinsAssembler) {
97 auto context = Parameter<Context>(Descriptor::kContext);
98 ThrowTypeError(context, MessageTemplate::kConstructAbstractClass,
99 "TypedArray");
100}
101
102// ES #sec-typedarray-constructors
104 auto context = Parameter<Context>(Descriptor::kContext);
105 auto target = Parameter<JSFunction>(Descriptor::kJSTarget);
106 auto new_target = Parameter<Object>(Descriptor::kJSNewTarget);
107 TNode<IntPtrT> argc = ChangeInt32ToIntPtr(
108 UncheckedParameter<Int32T>(Descriptor::kJSActualArgumentsCount));
109 CodeStubArguments args(this, argc);
110 TNode<Object> arg1 = args.GetOptionalArgumentValue(0);
111 TNode<Object> arg2 = args.GetOptionalArgumentValue(1);
112 TNode<Object> arg3 = args.GetOptionalArgumentValue(2);
113
114 // If NewTarget is undefined, throw a TypeError exception.
115 // All the TypedArray constructors have this as the first step:
116 // https://tc39.github.io/ecma262/#sec-typedarray-constructors
117 Label throwtypeerror(this, Label::kDeferred);
118 GotoIf(IsUndefined(new_target), &throwtypeerror);
119
121 CallBuiltin<JSAny>(Builtin::kCreateTypedArray, context, target,
122 new_target, arg1, arg2, arg3);
123 args.PopAndReturn(result);
124
125 BIND(&throwtypeerror);
126 {
127 TNode<String> name =
128 CAST(CallRuntime(Runtime::kGetFunctionName, context, target));
129 ThrowTypeError(context, MessageTemplate::kConstructorNotFunction, name);
130 }
131}
132
133// ES6 #sec-get-%typedarray%.prototype.bytelength
134TF_BUILTIN(TypedArrayPrototypeByteLength, TypedArrayBuiltinsAssembler) {
135 const char* const kMethodName = "get TypedArray.prototype.byteLength";
136 auto context = Parameter<Context>(Descriptor::kContext);
137 auto receiver = Parameter<Object>(Descriptor::kReceiver);
138
139 // Check if the {receiver} is actually a JSTypedArray.
140 ThrowIfNotInstanceType(context, receiver, JS_TYPED_ARRAY_TYPE, kMethodName);
141
142 TNode<JSTypedArray> receiver_array = CAST(receiver);
143 TNode<JSArrayBuffer> receiver_buffer =
144 LoadJSArrayBufferViewBuffer(receiver_array);
145
146 Label variable_length(this), normal(this);
147 Branch(IsVariableLengthJSArrayBufferView(receiver_array), &variable_length,
148 &normal);
149 BIND(&variable_length);
150 {
151 Return(ChangeUintPtrToTagged(LoadVariableLengthJSTypedArrayByteLength(
152 context, receiver_array, receiver_buffer)));
153 }
154
155 BIND(&normal);
156 {
157 // Default to zero if the {receiver}s buffer was detached.
158 TNode<UintPtrT> byte_length = Select<UintPtrT>(
159 IsDetachedBuffer(receiver_buffer),
160 [=, this] { return UintPtrConstant(0); },
161 [=, this] { return LoadJSArrayBufferViewByteLength(receiver_array); });
162 Return(ChangeUintPtrToTagged(byte_length));
163 }
164}
165
166// ES6 #sec-get-%typedarray%.prototype.byteoffset
167TF_BUILTIN(TypedArrayPrototypeByteOffset, TypedArrayBuiltinsAssembler) {
168 const char* const kMethodName = "get TypedArray.prototype.byteOffset";
169 auto context = Parameter<Context>(Descriptor::kContext);
170 auto receiver = Parameter<Object>(Descriptor::kReceiver);
171
172 // Check if the {receiver} is actually a JSTypedArray.
173 ThrowIfNotInstanceType(context, receiver, JS_TYPED_ARRAY_TYPE, kMethodName);
174
175 // Default to zero if the {receiver}s buffer was detached / out of bounds.
176 Label detached_or_oob(this), not_detached_nor_oob(this);
177 IsJSArrayBufferViewDetachedOrOutOfBounds(CAST(receiver), &detached_or_oob,
178 &not_detached_nor_oob);
179 BIND(&detached_or_oob);
180 Return(ChangeUintPtrToTagged(UintPtrConstant(0)));
181
182 BIND(&not_detached_nor_oob);
183 Return(
184 ChangeUintPtrToTagged(LoadJSArrayBufferViewByteOffset(CAST(receiver))));
185}
186
187// ES6 #sec-get-%typedarray%.prototype.length
188TF_BUILTIN(TypedArrayPrototypeLength, TypedArrayBuiltinsAssembler) {
189 const char* const kMethodName = "get TypedArray.prototype.length";
190 auto context = Parameter<Context>(Descriptor::kContext);
191 auto receiver = Parameter<Object>(Descriptor::kReceiver);
192
193 // Check if the {receiver} is actually a JSTypedArray.
194 ThrowIfNotInstanceType(context, receiver, JS_TYPED_ARRAY_TYPE, kMethodName);
195
196 TNode<JSTypedArray> receiver_array = CAST(receiver);
197 TVARIABLE(UintPtrT, length);
198 Label detached(this), end(this);
199 length = LoadJSTypedArrayLengthAndCheckDetached(receiver_array, &detached);
200 Return(ChangeUintPtrToTagged(length.value()));
201 BIND(&detached);
202 Return(ChangeUintPtrToTagged(UintPtrConstant(0)));
203}
204
207 return Word32Or(
208 Word32Or(Word32Equal(kind, Int32Constant(UINT8_ELEMENTS)),
209 Word32Equal(kind, Int32Constant(UINT8_CLAMPED_ELEMENTS))),
210 Word32Or(
211 Word32Equal(kind, Int32Constant(RAB_GSAB_UINT8_ELEMENTS)),
212 Word32Equal(kind, Int32Constant(RAB_GSAB_UINT8_CLAMPED_ELEMENTS))));
213}
214
217 static_assert(BIGUINT64_ELEMENTS + 1 == BIGINT64_ELEMENTS);
218 return Word32Or(
219 IsElementsKindInRange(kind, BIGUINT64_ELEMENTS, BIGINT64_ELEMENTS),
220 IsElementsKindInRange(kind, RAB_GSAB_BIGUINT64_ELEMENTS,
221 RAB_GSAB_BIGINT64_ELEMENTS));
222}
223
225 TNode<Int32T> elements_kind) {
226 TVARIABLE(IntPtrT, element_size);
227
229 elements_kind,
230 [&](ElementsKind el_kind, int size, int typed_array_fun_index) {
231 element_size = IntPtrConstant(size);
232 });
233
234 return element_size.value();
235}
236
237TorqueStructTypedArrayElementsInfo
242
243TorqueStructTypedArrayElementsInfo
245 TNode<Int32T> elements_kind = LoadMapElementsKind(map);
246 TVARIABLE(UintPtrT, var_size_log2);
247 TVARIABLE(Map, var_map);
248 ReadOnlyRoots roots(isolate());
249
251 elements_kind,
252 [&](ElementsKind kind, int size, int typed_array_fun_index) {
253 DCHECK_GT(size, 0);
255 });
256
257 return TorqueStructTypedArrayElementsInfo{var_size_log2.value(),
258 elements_kind};
259}
260
262 TNode<Context> context, TNode<JSTypedArray> exemplar) {
263 TVARIABLE(IntPtrT, context_slot);
264 TNode<Int32T> elements_kind = LoadElementsKind(exemplar);
265
267 elements_kind,
268 [&](ElementsKind el_kind, int size, int typed_array_function_index) {
269 context_slot = IntPtrConstant(typed_array_function_index);
270 });
271
272 return CAST(
273 LoadContextElement(LoadNativeContext(context), context_slot.value()));
274}
275
277 TNode<Context> context, TNode<Object> obj, const char* method_name) {
278 // If it is not a typed array, throw
279 ThrowIfNotInstanceType(context, obj, JS_TYPED_ARRAY_TYPE, method_name);
280
281 // If the typed array's buffer is detached, throw
282 ThrowIfArrayBufferViewBufferIsDetached(context, CAST(obj), method_name);
283
284 // TODO(v8:11111): Throw if the RAB / GSAB is OOB.
285 return CAST(obj);
286}
287
289 TNode<Context> context, TNode<Object> obj, const char* method_name) {
290 // If it is not a typed array, throw
291 ThrowIfNotInstanceType(context, obj, JS_TYPED_ARRAY_TYPE, method_name);
292
293 Label detached_or_oob(this), not_detached_nor_oob(this);
294 TNode<UintPtrT> length =
295 LoadJSTypedArrayLengthAndCheckDetached(CAST(obj), &detached_or_oob);
296 Goto(&not_detached_nor_oob);
297
298 BIND(&detached_or_oob);
299 ThrowTypeError(context, MessageTemplate::kDetachedOperation, method_name);
300
301 BIND(&not_detached_nor_oob);
302 return length;
303}
304
306 TNode<RawPtrT> src_ptr,
307 TNode<UintPtrT> byte_length) {
309 ExternalConstant(ExternalReference::libc_memmove_function());
311 std::make_pair(MachineType::Pointer(), dest_ptr),
312 std::make_pair(MachineType::Pointer(), src_ptr),
313 std::make_pair(MachineType::UintPtr(), byte_length));
314}
315
317 TNode<RawPtrT> dest_ptr, TNode<RawPtrT> src_ptr,
318 TNode<UintPtrT> byte_length) {
320 ExternalConstant(ExternalReference::relaxed_memmove_function());
322 std::make_pair(MachineType::Pointer(), dest_ptr),
323 std::make_pair(MachineType::Pointer(), src_ptr),
324 std::make_pair(MachineType::UintPtr(), byte_length));
325}
326
328 TNode<RawPtrT> src_ptr,
329 TNode<UintPtrT> byte_length) {
331 ExternalConstant(ExternalReference::libc_memcpy_function());
333 std::make_pair(MachineType::Pointer(), dest_ptr),
334 std::make_pair(MachineType::Pointer(), src_ptr),
335 std::make_pair(MachineType::UintPtr(), byte_length));
336}
337
339 TNode<RawPtrT> dest_ptr, TNode<RawPtrT> src_ptr,
340 TNode<UintPtrT> byte_length) {
342 ExternalConstant(ExternalReference::relaxed_memcpy_function());
344 std::make_pair(MachineType::Pointer(), dest_ptr),
345 std::make_pair(MachineType::Pointer(), src_ptr),
346 std::make_pair(MachineType::UintPtr(), byte_length));
347}
348
350 TNode<IntPtrT> value,
351 TNode<UintPtrT> length) {
353 ExternalConstant(ExternalReference::libc_memset_function());
355 std::make_pair(MachineType::Pointer(), dest_ptr),
356 std::make_pair(MachineType::IntPtr(), value),
357 std::make_pair(MachineType::UintPtr(), length));
358}
359
363 TNode<UintPtrT> source_length, TNode<UintPtrT> offset) {
364 CSA_DCHECK(this,
365 Word32BinaryNot(IsBigInt64ElementsKind(LoadElementsKind(dest))));
367 ExternalReference::copy_fast_number_jsarray_elements_to_typed_array());
369 std::make_pair(MachineType::AnyTagged(), context),
370 std::make_pair(MachineType::AnyTagged(), source),
371 std::make_pair(MachineType::AnyTagged(), dest),
372 std::make_pair(MachineType::UintPtr(), source_length),
373 std::make_pair(MachineType::UintPtr(), offset));
374}
375
378 TNode<UintPtrT> source_length, TNode<UintPtrT> offset) {
380 ExternalReference::copy_typed_array_elements_to_typed_array());
382 std::make_pair(MachineType::AnyTagged(), source),
383 std::make_pair(MachineType::AnyTagged(), dest),
384 std::make_pair(MachineType::UintPtr(), source_length),
385 std::make_pair(MachineType::UintPtr(), offset));
386}
387
392 ExternalConstant(ExternalReference::copy_typed_array_elements_slice());
394 std::make_pair(MachineType::AnyTagged(), source),
395 std::make_pair(MachineType::AnyTagged(), dest),
396 std::make_pair(MachineType::UintPtr(), start),
397 std::make_pair(MachineType::UintPtr(), end));
398}
399
401 TNode<Word32T> elements_kind, const TypedArraySwitchCase& case_function) {
402 Label next(this), if_unknown_type(this, Label::kDeferred);
403
404 int32_t elements_kinds[] = {
405#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) TYPE##_ELEMENTS,
407#undef TYPED_ARRAY_CASE
408 };
409
410#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) Label if_##type##array(this);
413#undef TYPED_ARRAY_CASE
414
415 Label* elements_kind_labels[] = {
416#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) &if_##type##array,
418#undef TYPED_ARRAY_CASE
419 };
420 static_assert(arraysize(elements_kinds) == arraysize(elements_kind_labels));
421
422 Switch(elements_kind, &if_unknown_type, elements_kinds, elements_kind_labels,
423 arraysize(elements_kinds));
424
425#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
426 BIND(&if_##type##array); \
427 { \
428 case_function(TYPE##_ELEMENTS, sizeof(ctype), \
429 Context::TYPE##_ARRAY_FUN_INDEX); \
430 Goto(&next); \
431 }
433#undef TYPED_ARRAY_CASE
434
435#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, NON_RAB_GSAB_TYPE) \
436 BIND(&if_##type##array); \
437 { \
438 case_function(TYPE##_ELEMENTS, sizeof(ctype), \
439 Context::NON_RAB_GSAB_TYPE##_ARRAY_FUN_INDEX); \
440 Goto(&next); \
441 }
443#undef TYPED_ARRAY_CASE
444
445 BIND(&if_unknown_type);
446 Unreachable();
447
448 BIND(&next);
449}
450
455 offset);
458 TNode<Int32T> compressed_base = TruncateIntPtrToInt32(full_base);
459 // TODO(v8:9706): Add a way to directly use kRootRegister value.
460 TNode<IntPtrT> ptr_compr_cage_base =
461 IntPtrSub(full_base, Signed(ChangeUint32ToWord(compressed_base)));
462 // Add JSTypedArray::ExternalPointerCompensationForOnHeapArray() to offset.
463 // See JSTypedArray::AddExternalPointerCompensationForDeserialization().
464 DCHECK_EQ(
465 isolate()->cage_base(),
467 offset = Unsigned(IntPtrAdd(offset, ptr_compr_cage_base));
468 }
469
470 StoreJSTypedArrayBasePointer(holder, base);
472}
473
482
484 TNode<Context> context, TNode<JSTypedArray> typed_array,
485 TNode<UintPtrT> index, TNode<Numeric> value, ElementsKind elements_kind) {
486 TNode<RawPtrT> data_ptr = LoadJSTypedArrayDataPtr(typed_array);
487 switch (elements_kind) {
488 case UINT8_ELEMENTS:
489 case UINT8_CLAMPED_ELEMENTS:
490 case INT8_ELEMENTS:
491 case UINT16_ELEMENTS:
492 case INT16_ELEMENTS:
493 StoreElement(data_ptr, elements_kind, index, SmiToInt32(CAST(value)));
494 break;
495 case UINT32_ELEMENTS:
496 case INT32_ELEMENTS:
497 StoreElement(data_ptr, elements_kind, index,
498 TruncateTaggedToWord32(context, value));
499 break;
500 case FLOAT16_ELEMENTS:
501 StoreElement(data_ptr, elements_kind, index,
503 break;
504 case FLOAT32_ELEMENTS:
505 StoreElement(data_ptr, elements_kind, index,
506 TruncateFloat64ToFloat32(LoadHeapNumberValue(CAST(value))));
507 break;
508 case FLOAT64_ELEMENTS:
509 StoreElement(data_ptr, elements_kind, index,
510 LoadHeapNumberValue(CAST(value)));
511 break;
512 case BIGUINT64_ELEMENTS:
513 case BIGINT64_ELEMENTS:
514 StoreElement(data_ptr, elements_kind, index,
515 UncheckedCast<BigInt>(value));
516 break;
517 default:
518 UNREACHABLE();
519 }
520}
521
522template <typename TValue>
524 TNode<Context> context, TNode<JSTypedArray> typed_array,
525 TNode<UintPtrT> index, TNode<TValue> prepared_value,
526 ElementsKind elements_kind, Label* if_detached_or_out_of_bounds) {
527 static_assert(std::is_same_v<TValue, Word32T> ||
528 std::is_same_v<TValue, Float16RawBitsT> ||
529 std::is_same_v<TValue, Float32T> ||
530 std::is_same_v<TValue, Float64T> ||
531 std::is_same_v<TValue, BigInt>,
532 "Only Word32T, Float16T, Float32T, Float64T or BigInt values "
533 "are allowed");
534 // ToNumber/ToBigInt (or other functions called by the upper level) may
535 // execute JavaScript code, which could detach the TypedArray's buffer or make
536 // the TypedArray out of bounds.
538 typed_array, if_detached_or_out_of_bounds);
539 GotoIf(UintPtrGreaterThanOrEqual(index, length),
540 if_detached_or_out_of_bounds);
541
542 TNode<RawPtrT> data_ptr = LoadJSTypedArrayDataPtr(typed_array);
543 StoreElement(data_ptr, elements_kind, index, prepared_value);
544}
545
547 TNode<Context> context, TNode<JSTypedArray> typed_array,
548 TNode<UintPtrT> index, TNode<Object> value, ElementsKind elements_kind,
549 Label* if_detached_or_out_of_bounds) {
550 switch (elements_kind) {
551 case UINT8_ELEMENTS:
552 case INT8_ELEMENTS:
553 case UINT16_ELEMENTS:
554 case INT16_ELEMENTS:
555 case UINT32_ELEMENTS:
556 case INT32_ELEMENTS:
557 case UINT8_CLAMPED_ELEMENTS: {
558 auto prepared_value = PrepareValueForWriteToTypedArray<Word32T>(
559 value, elements_kind, context);
560 StoreJSTypedArrayElementFromPreparedValue(context, typed_array, index,
561 prepared_value, elements_kind,
562 if_detached_or_out_of_bounds);
563 break;
564 }
565 case FLOAT16_ELEMENTS: {
567 value, elements_kind, context);
568 StoreJSTypedArrayElementFromPreparedValue(context, typed_array, index,
569 prepared_value, elements_kind,
570 if_detached_or_out_of_bounds);
571 break;
572 }
573 case FLOAT32_ELEMENTS: {
574 auto prepared_value = PrepareValueForWriteToTypedArray<Float32T>(
575 value, elements_kind, context);
576 StoreJSTypedArrayElementFromPreparedValue(context, typed_array, index,
577 prepared_value, elements_kind,
578 if_detached_or_out_of_bounds);
579 break;
580 }
581 case FLOAT64_ELEMENTS: {
582 auto prepared_value = PrepareValueForWriteToTypedArray<Float64T>(
583 value, elements_kind, context);
584 StoreJSTypedArrayElementFromPreparedValue(context, typed_array, index,
585 prepared_value, elements_kind,
586 if_detached_or_out_of_bounds);
587 break;
588 }
589 case BIGINT64_ELEMENTS:
590 case BIGUINT64_ELEMENTS: {
591 auto prepared_value = PrepareValueForWriteToTypedArray<BigInt>(
592 value, elements_kind, context);
593 StoreJSTypedArrayElementFromPreparedValue(context, typed_array, index,
594 prepared_value, elements_kind,
595 if_detached_or_out_of_bounds);
596 break;
597 }
598 default:
599 UNREACHABLE();
600 }
601}
602
603// ES #sec-get-%typedarray%.prototype-@@tostringtag
604TF_BUILTIN(TypedArrayPrototypeToStringTag, TypedArrayBuiltinsAssembler) {
605 auto receiver = Parameter<Object>(Descriptor::kReceiver);
606 Label if_receiverisheapobject(this), return_undefined(this);
607 Branch(TaggedIsSmi(receiver), &return_undefined, &if_receiverisheapobject);
608
609 // Dispatch on the elements kind, offset by
610 // FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND.
611 static_assert(LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1 ==
613 size_t const kTypedElementsKindCount =
616#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
617 Label return_##type##array(this); \
618 BIND(&return_##type##array); \
619 Return(StringConstant(#Type "Array"));
621#undef TYPED_ARRAY_CASE
622
623 // clang-format off
624 Label* elements_kind_labels[kTypedElementsKindCount] = {
625 // The TYPED_ARRAYS macro is invoked twice because while the RAB/GSAB-backed
626 // TAs have distinct ElementsKinds internally, they have the same "class"
627 // name for toString output.
628#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) &return_##type##array,
631#undef TYPED_ARRAY_CASE
632 };
633
634 int32_t elements_kinds[kTypedElementsKindCount] = {
635#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
636 TYPE##_ELEMENTS - FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
637 // The use of FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND below is not a typo! This
638 // computes an index into elements_kind_labels, and all TypedArray
639 // ElementsKind values are contiguous.
640#define RAB_GSAB_TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
641 TYPE##_ELEMENTS - FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND,
644#undef TYPED_ARRAY_CASE
645#undef RAB_GSAB_TYPED_ARRAY_CASE
646 };
647 // clang-format on
648
649 // We offset the dispatch by FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND, so that
650 // this can be turned into a non-sparse table switch for ideal performance.
651 BIND(&if_receiverisheapobject);
652 TNode<HeapObject> receiver_heap_object = CAST(receiver);
653 TNode<Int32T> elements_kind =
654 Int32Sub(LoadElementsKind(receiver_heap_object),
656 Switch(elements_kind, &return_undefined, elements_kinds, elements_kind_labels,
657 kTypedElementsKindCount);
658
659 BIND(&return_undefined);
660 Return(UndefinedConstant());
661}
662
664
665} // namespace internal
666} // namespace v8
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)
#define BIND(label)
#define TVARIABLE(...)
#define CSA_DCHECK(csa,...)
#define RAB_GSAB_TYPED_ARRAY_CASE(Type, type, TYPE, ctype)
#define TF_BUILTIN(Name, AssemblerBase)
Builtins::Kind kind
Definition builtins.cc:40
TNode< BoolT > IsElementsKindInRange(TNode< Int32T > target_kind, ElementsKind lower_reference_kind, ElementsKind higher_reference_kind)
TNode< UintPtrT > LoadJSTypedArrayLengthAndCheckDetached(TNode< JSTypedArray > typed_array, Label *detached)
TNode< Float16RawBitsT > TruncateFloat64ToFloat16(TNode< Float64T > value)
void StoreSandboxedPointerToObject(TNode< HeapObject > object, int offset, TNode< RawPtrT > pointer)
TNode< Int32T > TruncateIntPtrToInt32(TNode< IntPtrT > value)
void ThrowIfNotInstanceType(TNode< Context > context, TNode< Object > value, InstanceType instance_type, char const *method_name)
TNode< RawPtrT > EmptyBackingStoreBufferConstant()
void ThrowTypeError(TNode< Context > context, MessageTemplate message, char const *arg0=nullptr, char const *arg1=nullptr)
TNode< HeapObject > Allocate(TNode< IntPtrT > size, AllocationFlags flags=AllocationFlag::kNone)
void ThrowIfArrayBufferViewBufferIsDetached(TNode< Context > context, TNode< JSArrayBufferView > array_buffer_view, const char *method_name)
void InitializeJSAPIObjectWithEmbedderSlotsCppHeapWrapperPtr(TNode< JSAPIObjectWithEmbedderSlots > holder)
TNode< RawPtrT > LoadJSTypedArrayDataPtr(TNode< JSTypedArray > typed_array)
void StoreElement(TNode< RawPtrT > elements, ElementsKind kind, TNode< TIndex > index, TNode< TValue > value)
void StoreJSTypedArrayExternalPointerPtr(TNode< JSTypedArray > holder, TNode< RawPtrT > value)
TNode< Int32T > LoadElementsKind(TNode< HeapObject > object)
TNode< Word32T > TruncateTaggedToWord32(TNode< Context > context, TNode< Object > value)
void StoreObjectFieldNoWriteBarrier(TNode< HeapObject > object, TNode< IntPtrT > offset, TNode< T > value)
TNode< NativeContext > LoadNativeContext(TNode< Context > context)
TNode< T > PrepareValueForWriteToTypedArray(TNode< Object > input, ElementsKind elements_kind, TNode< Context > context)
TNode< Float64T > LoadHeapNumberValue(TNode< HeapObject > object)
void StoreBoundedSizeToObject(TNode< HeapObject > object, int offset, TNode< UintPtrT > value)
TNode< Map > LoadMap(TNode< HeapObject > object)
TNode< Int32T > SmiToInt32(TNode< Smi > value)
TNode< Int32T > LoadMapElementsKind(TNode< Map > map)
void StoreObjectField(TNode< HeapObject > object, int offset, TNode< Smi > value)
void StoreMapNoWriteBarrier(TNode< HeapObject > object, RootIndex map_root_index)
static constexpr int kSizeWithEmbedderFields
static Address ExternalPointerCompensationForOnHeapArray(PtrComprCageBase cage_base)
static constexpr int kSizeWithEmbedderFields
static constexpr MachineType Pointer()
static constexpr MachineType AnyTagged()
static constexpr MachineType UintPtr()
static constexpr MachineType IntPtr()
void StoreJSTypedArrayElementFromPreparedValue(TNode< Context > context, TNode< JSTypedArray > typed_array, TNode< UintPtrT > index_node, TNode< TValue > value, ElementsKind elements_kind, Label *if_detached_or_out_of_bounds)
TNode< JSFunction > GetDefaultConstructor(TNode< Context > context, TNode< JSTypedArray > exemplar)
ElementsInfo GetTypedArrayElementsInfo(TNode< JSTypedArray > typed_array)
void SetJSTypedArrayOffHeapDataPtr(TNode< JSTypedArray > holder, TNode< RawPtrT > base, TNode< UintPtrT > offset)
void CallCMemset(TNode< RawPtrT > dest_ptr, TNode< IntPtrT > value, TNode< UintPtrT > length)
TNode< UintPtrT > ValidateTypedArrayAndGetLength(TNode< Context > context, TNode< Object > obj, const char *method_name)
void CallCRelaxedMemcpy(TNode< RawPtrT > dest_ptr, TNode< RawPtrT > src_ptr, TNode< UintPtrT > byte_length)
std::function< void(ElementsKind, int, int)> TypedArraySwitchCase
void CallCCopyTypedArrayElementsSlice(TNode< JSTypedArray > source, TNode< JSTypedArray > dest, TNode< UintPtrT > start, TNode< UintPtrT > end)
void CallCCopyFastNumberJSArrayElementsToTypedArray(TNode< Context > context, TNode< JSArray > source, TNode< JSTypedArray > dest, TNode< UintPtrT > source_length, TNode< UintPtrT > offset)
void CallCRelaxedMemmove(TNode< RawPtrT > dest_ptr, TNode< RawPtrT > src_ptr, TNode< UintPtrT > byte_length)
void CallCMemcpy(TNode< RawPtrT > dest_ptr, TNode< RawPtrT > src_ptr, TNode< UintPtrT > byte_length)
void CallCCopyTypedArrayElementsToTypedArray(TNode< JSTypedArray > source, TNode< JSTypedArray > dest, TNode< UintPtrT > source_length, TNode< UintPtrT > offset)
void StoreJSTypedArrayElementFromTagged(TNode< Context > context, TNode< JSTypedArray > typed_array, TNode< UintPtrT > index_node, TNode< Object > value, ElementsKind elements_kind, Label *if_detached_or_out_of_bounds)
void DispatchTypedArrayByElementsKind(TNode< Word32T > elements_kind, const TypedArraySwitchCase &case_function)
void StoreJSTypedArrayElementFromNumeric(TNode< Context > context, TNode< JSTypedArray > typed_array, TNode< UintPtrT > index_node, TNode< Numeric > value, ElementsKind elements_kind)
TNode< JSArrayBuffer > AllocateEmptyOnHeapBuffer(TNode< Context > context)
void CallCMemmove(TNode< RawPtrT > dest_ptr, TNode< RawPtrT > src_ptr, TNode< UintPtrT > byte_length)
TNode< IntPtrT > GetTypedArrayElementSize(TNode< Int32T > elements_kind)
void SetJSTypedArrayOnHeapDataPtr(TNode< JSTypedArray > holder, TNode< ByteArray > base, TNode< UintPtrT > offset)
TNode< JSTypedArray > ValidateTypedArray(TNode< Context > context, TNode< Object > obj, const char *method_name)
TNode< BoolT > IsUint8ElementsKind(TNode< Int32T > kind)
TNode< BoolT > IsBigInt64ElementsKind(TNode< Int32T > kind)
void SetupTypedArrayEmbedderFields(TNode< JSTypedArray > holder)
TNode< IntPtrT > IntPtrAdd(TNode< IntPtrT > left, TNode< IntPtrT > right)
TNode< Int32T > Signed(TNode< Word32T > x)
TNode< IntPtrT > IntPtrConstant(intptr_t value)
TNode< UintPtrT > ChangeUint32ToWord(TNode< Word32T > value)
TNode< T > UncheckedCast(Node *value)
TNode< Uint32T > Unsigned(TNode< Word32T > x)
TNode< T > ReinterpretCast(Node *value)
TNode< IntPtrT > BitcastTaggedToWord(TNode< Smi > node)
TNode< Smi > SmiConstant(Tagged< Smi > value)
void GotoIf(TNode< IntegralT > condition, Label *true_label, GotoHint goto_hint=GotoHint::kNone)
TNode< Int32T > Word32Or(TNode< Int32T > left, TNode< Int32T > right)
void Switch(Node *index, Label *default_label, const int32_t *case_values, Label **case_labels, size_t case_count)
TNode< ExternalPointerHandleT > ExternalPointerHandleNullConstant()
TNode< IntPtrT > IntPtrSub(TNode< IntPtrT > left, TNode< IntPtrT > right)
TNode< ExternalReference > ExternalConstant(ExternalReference address)
TNode< Int32T > Int32Constant(int32_t value)
Node * CallCFunction(Node *function, std::optional< MachineType > return_type, CArgs... cargs)
TNode< BoolT > Word32Equal(TNode< Word32T > left, TNode< Word32T > right)
TNode< UintPtrT > UintPtrConstant(uintptr_t value)
TNode< RawPtrT > RawPtrAdd(TNode< RawPtrT > left, TNode< IntPtrT > right)
TNode< UintPtrT > UintPtrAdd(TNode< UintPtrT > left, TNode< UintPtrT > right)
#define CAST(x)
#define COMPRESS_POINTERS_BOOL
Definition globals.h:99
int start
int end
#define RAB_GSAB_TYPED_ARRAYS_WITH_NON_RAB_GSAB_ELEMENTS_KIND(V)
#define RAB_GSAB_TYPED_ARRAYS(V)
#define TYPED_ARRAYS(V)
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
DirectHandle< Object > new_target
Definition execution.cc:75
int32_t offset
TNode< Object > receiver
ZoneVector< RpoNumber > & result
constexpr int kTaggedSize
Definition globals.h:542
@ FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND
@ LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND
@ FIRST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND
@ LAST_RAB_GSAB_FIXED_TYPED_ARRAY_ELEMENTS_KIND
constexpr int ElementsKindToShiftSize(ElementsKind elements_kind)
const int kHeapObjectTag
Definition v8-internal.h:72
void relaxed_memcpy(volatile base::Atomic8 *dest, volatile const base::Atomic8 *src, size_t n)
!IsContextMap !IsContextMap native_context
Definition map-inl.h:877
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define DCHECK_GT(v1, v2)
Definition logging.h:487
#define arraysize(array)
Definition macros.h:67
#define OFFSET_OF_DATA_START(Type)
#define FIELD_SIZE(Name)
Definition utils.h:259