Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: src/builtins/builtins-typedarray.cc

Issue 2752143004: [refactor] Separate generated builtins and C++ builtins into separate files (Closed)
Patch Set: tentative gcmole fix Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins-symbol-gen.cc ('k') | src/builtins/builtins-typedarray-gen.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/builtins/builtins-utils.h" 5 #include "src/builtins/builtins-utils.h"
6 #include "src/builtins/builtins.h" 6 #include "src/builtins/builtins.h"
7 #include "src/code-stub-assembler.h"
8 #include "src/counters.h" 7 #include "src/counters.h"
9 #include "src/elements.h" 8 #include "src/elements.h"
10 #include "src/objects-inl.h" 9 #include "src/objects-inl.h"
11 10
12 namespace v8 { 11 namespace v8 {
13 namespace internal { 12 namespace internal {
14 13
15 class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
16 public:
17 explicit TypedArrayBuiltinsAssembler(compiler::CodeAssemblerState* state)
18 : CodeStubAssembler(state) {}
19
20 protected:
21 void GenerateTypedArrayPrototypeGetter(const char* method_name,
22 int object_offset);
23 template <IterationKind kIterationKind>
24 void GenerateTypedArrayPrototypeIterationMethod(const char* method_name);
25
26 void LoadMapAndElementsSize(Node* const array, Variable* typed_map,
27 Variable* size);
28
29 void CalculateExternalPointer(Node* const backing_store,
30 Node* const byte_offset,
31 Variable* external_pointer);
32 void DoInitialize(Node* const holder, Node* length, Node* const maybe_buffer,
33 Node* const byte_offset, Node* byte_length,
34 Node* const initialize, Node* const context);
35 };
36
37 void TypedArrayBuiltinsAssembler::LoadMapAndElementsSize(Node* const array,
38 Variable* typed_map,
39 Variable* size) {
40 Label unreachable(this), done(this);
41 Label uint8_elements(this), uint8_clamped_elements(this), int8_elements(this),
42 uint16_elements(this), int16_elements(this), uint32_elements(this),
43 int32_elements(this), float32_elements(this), float64_elements(this);
44 Label* elements_kind_labels[] = {
45 &uint8_elements, &uint8_clamped_elements, &int8_elements,
46 &uint16_elements, &int16_elements, &uint32_elements,
47 &int32_elements, &float32_elements, &float64_elements};
48 int32_t elements_kinds[] = {
49 UINT8_ELEMENTS, UINT8_CLAMPED_ELEMENTS, INT8_ELEMENTS,
50 UINT16_ELEMENTS, INT16_ELEMENTS, UINT32_ELEMENTS,
51 INT32_ELEMENTS, FLOAT32_ELEMENTS, FLOAT64_ELEMENTS};
52 const size_t kTypedElementsKindCount = LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND -
53 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND +
54 1;
55 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds));
56 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels));
57
58 Node* array_map = LoadMap(array);
59 Node* elements_kind = LoadMapElementsKind(array_map);
60 Switch(elements_kind, &unreachable, elements_kinds, elements_kind_labels,
61 kTypedElementsKindCount);
62
63 for (int i = 0; i < static_cast<int>(kTypedElementsKindCount); i++) {
64 Bind(elements_kind_labels[i]);
65 {
66 ElementsKind kind = static_cast<ElementsKind>(elements_kinds[i]);
67 ExternalArrayType type =
68 isolate()->factory()->GetArrayTypeFromElementsKind(kind);
69 Handle<Map> map(isolate()->heap()->MapForFixedTypedArray(type));
70 typed_map->Bind(HeapConstant(map));
71 size->Bind(SmiConstant(static_cast<int>(
72 isolate()->factory()->GetExternalArrayElementSize(type))));
73 Goto(&done);
74 }
75 }
76
77 Bind(&unreachable);
78 { Unreachable(); }
79 Bind(&done);
80 }
81
82 // The byte_offset can be higher than Smi range, in which case to perform the
83 // pointer arithmetic necessary to calculate external_pointer, converting
84 // byte_offset to an intptr is more difficult. The max byte_offset is 8 * MaxSmi
85 // on the particular platform. 32 bit platforms are self-limiting, because we
86 // can't allocate an array bigger than our 32-bit arithmetic range anyway. 64
87 // bit platforms could theoretically have an offset up to 2^35 - 1, so we may
88 // need to convert the float heap number to an intptr.
89 void TypedArrayBuiltinsAssembler::CalculateExternalPointer(
90 Node* const backing_store, Node* const byte_offset,
91 Variable* external_pointer) {
92 Label offset_is_smi(this), offset_not_smi(this), done(this);
93 Branch(TaggedIsSmi(byte_offset), &offset_is_smi, &offset_not_smi);
94
95 Bind(&offset_is_smi);
96 {
97 external_pointer->Bind(IntPtrAdd(backing_store, SmiToWord(byte_offset)));
98 Goto(&done);
99 }
100
101 Bind(&offset_not_smi);
102 {
103 Node* heap_number = LoadHeapNumberValue(byte_offset);
104 Node* intrptr_value = ChangeFloat64ToUintPtr(heap_number);
105 external_pointer->Bind(IntPtrAdd(backing_store, intrptr_value));
106 Goto(&done);
107 }
108
109 Bind(&done);
110 }
111
112 void TypedArrayBuiltinsAssembler::DoInitialize(Node* const holder, Node* length,
113 Node* const maybe_buffer,
114 Node* const byte_offset,
115 Node* byte_length,
116 Node* const initialize,
117 Node* const context) {
118 static const int32_t fta_base_data_offset =
119 FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
120
121 Label setup_holder(this), alloc_array_buffer(this), aligned(this),
122 allocate_elements(this), attach_buffer(this), done(this);
123 Variable fixed_typed_map(this, MachineRepresentation::kTagged);
124 Variable element_size(this, MachineRepresentation::kTagged);
125 Variable total_size(this, MachineType::PointerRepresentation());
126
127 // Make sure length is a Smi. The caller guarantees this is the case.
128 length = ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero);
129 CSA_ASSERT(this, TaggedIsSmi(length));
130
131 // byte_length can be -0, get rid of it.
132 byte_length =
133 ToInteger(context, byte_length, CodeStubAssembler::kTruncateMinusZero);
134
135 GotoIfNot(IsNull(maybe_buffer), &setup_holder);
136 // If the buffer is null, then we need a Smi byte_length. The caller
137 // guarantees this is the case, because when byte_length >
138 // TypedArrayMaxSizeInHeap, a buffer is allocated and passed in here.
139 CSA_ASSERT(this, TaggedIsSmi(byte_length));
140 Goto(&setup_holder);
141
142 Bind(&setup_holder);
143 {
144 LoadMapAndElementsSize(holder, &fixed_typed_map, &element_size);
145 // Setup the holder (JSArrayBufferView).
146 // - Set the length.
147 // - Set the byte_offset.
148 // - Set the byte_length.
149 // - Set InternalFields to 0.
150 StoreObjectField(holder, JSTypedArray::kLengthOffset, length);
151 StoreObjectField(holder, JSArrayBufferView::kByteOffsetOffset, byte_offset);
152 StoreObjectField(holder, JSArrayBufferView::kByteLengthOffset, byte_length);
153 for (int offset = JSTypedArray::kSize;
154 offset < JSTypedArray::kSizeWithInternalFields;
155 offset += kPointerSize) {
156 StoreObjectField(holder, offset, SmiConstant(Smi::kZero));
157 }
158
159 Branch(IsNull(maybe_buffer), &alloc_array_buffer, &attach_buffer);
160 }
161
162 Bind(&alloc_array_buffer);
163 {
164 // Allocate a new ArrayBuffer and initialize it with empty properties and
165 // elements.
166 Node* const native_context = LoadNativeContext(context);
167 Node* const map =
168 LoadContextElement(native_context, Context::ARRAY_BUFFER_MAP_INDEX);
169 Node* empty_fixed_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex);
170
171 Node* const buffer = Allocate(JSArrayBuffer::kSizeWithInternalFields);
172 StoreMapNoWriteBarrier(buffer, map);
173 StoreObjectFieldNoWriteBarrier(buffer, JSArray::kPropertiesOffset,
174 empty_fixed_array);
175 StoreObjectFieldNoWriteBarrier(buffer, JSArray::kElementsOffset,
176 empty_fixed_array);
177 // Setup the ArrayBuffer.
178 // - Set BitField to 0.
179 // - Set IsExternal and IsNeuterable bits of BitFieldSlot.
180 // - Set the byte_length field to byte_length.
181 // - Set backing_store to null/Smi(0).
182 // - Set all internal fields to Smi(0).
183 StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBitFieldSlot,
184 SmiConstant(Smi::kZero));
185 int32_t bitfield_value = (1 << JSArrayBuffer::IsExternal::kShift) |
186 (1 << JSArrayBuffer::IsNeuterable::kShift);
187 StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBitFieldOffset,
188 Int32Constant(bitfield_value),
189 MachineRepresentation::kWord32);
190
191 StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kByteLengthOffset,
192 byte_length);
193 StoreObjectFieldNoWriteBarrier(buffer, JSArrayBuffer::kBackingStoreOffset,
194 SmiConstant(Smi::kZero));
195 for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
196 int offset = JSArrayBuffer::kSize + i * kPointerSize;
197 StoreObjectFieldNoWriteBarrier(buffer, offset, SmiConstant(Smi::kZero));
198 }
199
200 StoreObjectField(holder, JSArrayBufferView::kBufferOffset, buffer);
201
202 // Check the alignment.
203 GotoIf(SmiEqual(SmiMod(element_size.value(), SmiConstant(kObjectAlignment)),
204 SmiConstant(0)),
205 &aligned);
206
207 // Fix alignment if needed.
208 DCHECK_EQ(0, FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask);
209 Node* aligned_header_size =
210 IntPtrConstant(FixedTypedArrayBase::kHeaderSize + kObjectAlignmentMask);
211 Node* size = IntPtrAdd(SmiToWord(byte_length), aligned_header_size);
212 total_size.Bind(WordAnd(size, IntPtrConstant(~kObjectAlignmentMask)));
213 Goto(&allocate_elements);
214 }
215
216 Bind(&aligned);
217 {
218 Node* header_size = IntPtrConstant(FixedTypedArrayBase::kHeaderSize);
219 total_size.Bind(IntPtrAdd(SmiToWord(byte_length), header_size));
220 Goto(&allocate_elements);
221 }
222
223 Bind(&allocate_elements);
224 {
225 // Allocate a FixedTypedArray and set the length, base pointer and external
226 // pointer.
227 CSA_ASSERT(this, IsRegularHeapObjectSize(total_size.value()));
228 Node* elements = Allocate(total_size.value());
229
230 StoreMapNoWriteBarrier(elements, fixed_typed_map.value());
231 StoreObjectFieldNoWriteBarrier(elements, FixedArray::kLengthOffset, length);
232 StoreObjectFieldNoWriteBarrier(
233 elements, FixedTypedArrayBase::kBasePointerOffset, elements);
234 StoreObjectFieldNoWriteBarrier(elements,
235 FixedTypedArrayBase::kExternalPointerOffset,
236 IntPtrConstant(fta_base_data_offset),
237 MachineType::PointerRepresentation());
238
239 StoreObjectField(holder, JSObject::kElementsOffset, elements);
240
241 GotoIf(IsFalse(initialize), &done);
242 // Initialize the backing store by filling it with 0s.
243 Node* backing_store = IntPtrAdd(BitcastTaggedToWord(elements),
244 IntPtrConstant(fta_base_data_offset));
245 // Call out to memset to perform initialization.
246 Node* memset =
247 ExternalConstant(ExternalReference::libc_memset_function(isolate()));
248 CallCFunction3(MachineType::AnyTagged(), MachineType::Pointer(),
249 MachineType::IntPtr(), MachineType::UintPtr(), memset,
250 backing_store, IntPtrConstant(0), SmiToWord(byte_length));
251 Goto(&done);
252 }
253
254 Bind(&attach_buffer);
255 {
256 StoreObjectField(holder, JSArrayBufferView::kBufferOffset, maybe_buffer);
257
258 Node* elements = Allocate(FixedTypedArrayBase::kHeaderSize);
259 StoreMapNoWriteBarrier(elements, fixed_typed_map.value());
260 StoreObjectFieldNoWriteBarrier(elements, FixedArray::kLengthOffset, length);
261 StoreObjectFieldNoWriteBarrier(
262 elements, FixedTypedArrayBase::kBasePointerOffset, SmiConstant(0));
263
264 Variable external_pointer(this, MachineType::PointerRepresentation());
265 Node* backing_store =
266 LoadObjectField(maybe_buffer, JSArrayBuffer::kBackingStoreOffset,
267 MachineType::Pointer());
268
269 CalculateExternalPointer(backing_store, byte_offset, &external_pointer);
270 StoreObjectFieldNoWriteBarrier(
271 elements, FixedTypedArrayBase::kExternalPointerOffset,
272 external_pointer.value(), MachineType::PointerRepresentation());
273
274 StoreObjectField(holder, JSObject::kElementsOffset, elements);
275 Goto(&done);
276 }
277
278 Bind(&done);
279 Return(UndefinedConstant());
280 }
281
282 TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) {
283 Node* const holder = Parameter(1);
284 Node* length = Parameter(2);
285 Node* const maybe_buffer = Parameter(3);
286 Node* const byte_offset = Parameter(4);
287 Node* byte_length = Parameter(5);
288 Node* const initialize = Parameter(6);
289 Node* const context = Parameter(9);
290
291 DoInitialize(holder, length, maybe_buffer, byte_offset, byte_length,
292 initialize, context);
293 }
294
295 // ----------------------------------------------------------------------------- 14 // -----------------------------------------------------------------------------
296 // ES6 section 22.2 TypedArray Objects 15 // ES6 section 22.2 TypedArray Objects
297 16
298 // ES6 section 22.2.4.2 TypedArray ( length )
299 TF_BUILTIN(TypedArrayConstructByLength, TypedArrayBuiltinsAssembler) {
300 // We know that holder cannot be an object if this builtin was called.
301 Node* holder = Parameter(1);
302 Node* length = Parameter(2);
303 Node* element_size = Parameter(3);
304 Node* context = Parameter(6);
305
306 Variable maybe_buffer(this, MachineRepresentation::kTagged);
307 maybe_buffer.Bind(NullConstant());
308 Node* byte_offset = SmiConstant(0);
309 Node* initialize = BooleanConstant(true);
310
311 Label external_buffer(this), call_init(this), invalid_length(this);
312
313 length = ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero);
314 // The maximum length of a TypedArray is MaxSmi().
315 // Note: this is not per spec, but rather a constraint of our current
316 // representation (which uses smi's).
317 GotoIf(TaggedIsNotSmi(length), &invalid_length);
318 GotoIf(SmiLessThan(length, SmiConstant(0)), &invalid_length);
319
320 // For byte_length < typed_array_max_size_in_heap, we allocate the buffer on
321 // the heap. Otherwise we allocate it externally and attach it.
322 Node* byte_length = SmiMul(length, element_size);
323 GotoIf(TaggedIsNotSmi(byte_length), &external_buffer);
324 Branch(SmiLessThanOrEqual(byte_length,
325 SmiConstant(FLAG_typed_array_max_size_in_heap)),
326 &call_init, &external_buffer);
327
328 Bind(&external_buffer);
329 {
330 Node* const buffer_constructor = LoadContextElement(
331 LoadNativeContext(context), Context::ARRAY_BUFFER_FUN_INDEX);
332 maybe_buffer.Bind(ConstructJS(CodeFactory::Construct(isolate()), context,
333 buffer_constructor, byte_length));
334 Goto(&call_init);
335 }
336
337 Bind(&call_init);
338 {
339 DoInitialize(holder, length, maybe_buffer.value(), byte_offset, byte_length,
340 initialize, context);
341 }
342
343 Bind(&invalid_length);
344 {
345 CallRuntime(Runtime::kThrowRangeError, context,
346 SmiConstant(MessageTemplate::kInvalidTypedArrayLength));
347 Unreachable();
348 }
349 }
350
351 // ES6 section 22.2.4.5 TypedArray ( buffer [ , byteOffset [ , length ] ] )
352 TF_BUILTIN(TypedArrayConstructByArrayBuffer, TypedArrayBuiltinsAssembler) {
353 Node* const holder = Parameter(1);
354 Node* const buffer = Parameter(2);
355 Node* byte_offset = Parameter(3);
356 Node* const length = Parameter(4);
357 Node* const element_size = Parameter(5);
358 CSA_ASSERT(this, TaggedIsSmi(element_size));
359 Node* const context = Parameter(8);
360 Node* const initialize = BooleanConstant(true);
361
362 Variable new_byte_length(this, MachineRepresentation::kTagged,
363 SmiConstant(0));
364
365 Label start_offset_error(this), byte_length_error(this),
366 invalid_offset_error(this);
367 Label call_init(this), invalid_length(this), length_undefined(this),
368 length_defined(this);
369
370 Callable add = CodeFactory::Add(isolate());
371 Callable div = CodeFactory::Divide(isolate());
372 Callable equal = CodeFactory::Equal(isolate());
373 Callable greater_than = CodeFactory::GreaterThan(isolate());
374 Callable less_than = CodeFactory::LessThan(isolate());
375 Callable mod = CodeFactory::Modulus(isolate());
376 Callable sub = CodeFactory::Subtract(isolate());
377
378 byte_offset =
379 ToInteger(context, byte_offset, CodeStubAssembler::kTruncateMinusZero);
380 GotoIf(IsTrue(CallStub(less_than, context, byte_offset, SmiConstant(0))),
381 &invalid_length);
382
383 Node* remainder = CallStub(mod, context, byte_offset, element_size);
384 // Remainder can be a heap number.
385 GotoIf(IsFalse(CallStub(equal, context, remainder, SmiConstant(0))),
386 &start_offset_error);
387
388 // TODO(petermarshall): Throw on detached typedArray.
389 Branch(IsUndefined(length), &length_undefined, &length_defined);
390
391 Bind(&length_undefined);
392 {
393 Node* buffer_byte_length =
394 LoadObjectField(buffer, JSArrayBuffer::kByteLengthOffset);
395
396 Node* remainder = CallStub(mod, context, buffer_byte_length, element_size);
397 // Remainder can be a heap number.
398 GotoIf(IsFalse(CallStub(equal, context, remainder, SmiConstant(0))),
399 &byte_length_error);
400
401 new_byte_length.Bind(
402 CallStub(sub, context, buffer_byte_length, byte_offset));
403
404 Branch(IsTrue(CallStub(less_than, context, new_byte_length.value(),
405 SmiConstant(0))),
406 &invalid_offset_error, &call_init);
407 }
408
409 Bind(&length_defined);
410 {
411 Node* new_length = ToSmiIndex(length, context, &invalid_length);
412 new_byte_length.Bind(SmiMul(new_length, element_size));
413 // Reading the byte length must come after the ToIndex operation, which
414 // could cause the buffer to become detached.
415 Node* buffer_byte_length =
416 LoadObjectField(buffer, JSArrayBuffer::kByteLengthOffset);
417
418 Node* end = CallStub(add, context, byte_offset, new_byte_length.value());
419
420 Branch(IsTrue(CallStub(greater_than, context, end, buffer_byte_length)),
421 &invalid_length, &call_init);
422 }
423
424 Bind(&call_init);
425 {
426 Node* new_length =
427 CallStub(div, context, new_byte_length.value(), element_size);
428 // Force the result into a Smi, or throw a range error if it doesn't fit.
429 new_length = ToSmiIndex(new_length, context, &invalid_length);
430
431 DoInitialize(holder, new_length, buffer, byte_offset,
432 new_byte_length.value(), initialize, context);
433 }
434
435 Bind(&invalid_offset_error);
436 {
437 CallRuntime(Runtime::kThrowRangeError, context,
438 SmiConstant(MessageTemplate::kInvalidOffset), byte_offset);
439 Unreachable();
440 }
441
442 Bind(&start_offset_error);
443 {
444 Node* holder_map = LoadMap(holder);
445 Node* problem_string = HeapConstant(
446 factory()->NewStringFromAsciiChecked("start offset", TENURED));
447 CallRuntime(Runtime::kThrowInvalidTypedArrayAlignment, context, holder_map,
448 problem_string);
449
450 Unreachable();
451 }
452
453 Bind(&byte_length_error);
454 {
455 Node* holder_map = LoadMap(holder);
456 Node* problem_string = HeapConstant(
457 factory()->NewStringFromAsciiChecked("byte length", TENURED));
458 CallRuntime(Runtime::kThrowInvalidTypedArrayAlignment, context, holder_map,
459 problem_string);
460
461 Unreachable();
462 }
463
464 Bind(&invalid_length);
465 {
466 CallRuntime(Runtime::kThrowRangeError, context,
467 SmiConstant(MessageTemplate::kInvalidTypedArrayLength));
468 Unreachable();
469 }
470 }
471
472 // ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer 17 // ES6 section 22.2.3.1 get %TypedArray%.prototype.buffer
473 BUILTIN(TypedArrayPrototypeBuffer) { 18 BUILTIN(TypedArrayPrototypeBuffer) {
474 HandleScope scope(isolate); 19 HandleScope scope(isolate);
475 CHECK_RECEIVER(JSTypedArray, typed_array, "get TypedArray.prototype.buffer"); 20 CHECK_RECEIVER(JSTypedArray, typed_array, "get TypedArray.prototype.buffer");
476 return *typed_array->GetBuffer(); 21 return *typed_array->GetBuffer();
477 } 22 }
478 23
479 void TypedArrayBuiltinsAssembler::GenerateTypedArrayPrototypeGetter(
480 const char* method_name, int object_offset) {
481 Node* receiver = Parameter(0);
482 Node* context = Parameter(3);
483
484 // Check if the {receiver} is actually a JSTypedArray.
485 Label receiver_is_incompatible(this, Label::kDeferred);
486 GotoIf(TaggedIsSmi(receiver), &receiver_is_incompatible);
487 GotoIfNot(HasInstanceType(receiver, JS_TYPED_ARRAY_TYPE),
488 &receiver_is_incompatible);
489
490 // Check if the {receiver}'s JSArrayBuffer was neutered.
491 Node* receiver_buffer =
492 LoadObjectField(receiver, JSTypedArray::kBufferOffset);
493 Label if_receiverisneutered(this, Label::kDeferred);
494 GotoIf(IsDetachedBuffer(receiver_buffer), &if_receiverisneutered);
495 Return(LoadObjectField(receiver, object_offset));
496
497 Bind(&if_receiverisneutered);
498 {
499 // The {receiver}s buffer was neutered, default to zero.
500 Return(SmiConstant(0));
501 }
502
503 Bind(&receiver_is_incompatible);
504 {
505 // The {receiver} is not a valid JSTypedArray.
506 CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context,
507 HeapConstant(
508 factory()->NewStringFromAsciiChecked(method_name, TENURED)),
509 receiver);
510 Unreachable();
511 }
512 }
513
514 // ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength
515 TF_BUILTIN(TypedArrayPrototypeByteLength, TypedArrayBuiltinsAssembler) {
516 GenerateTypedArrayPrototypeGetter("get TypedArray.prototype.byteLength",
517 JSTypedArray::kByteLengthOffset);
518 }
519
520 // ES6 section 22.2.3.3 get %TypedArray%.prototype.byteOffset
521 TF_BUILTIN(TypedArrayPrototypeByteOffset, TypedArrayBuiltinsAssembler) {
522 GenerateTypedArrayPrototypeGetter("get TypedArray.prototype.byteOffset",
523 JSTypedArray::kByteOffsetOffset);
524 }
525
526 // ES6 section 22.2.3.18 get %TypedArray%.prototype.length
527 TF_BUILTIN(TypedArrayPrototypeLength, TypedArrayBuiltinsAssembler) {
528 GenerateTypedArrayPrototypeGetter("get TypedArray.prototype.length",
529 JSTypedArray::kLengthOffset);
530 }
531
532 template <IterationKind kIterationKind>
533 void TypedArrayBuiltinsAssembler::GenerateTypedArrayPrototypeIterationMethod(
534 const char* method_name) {
535 Node* receiver = Parameter(0);
536 Node* context = Parameter(3);
537
538 Label throw_bad_receiver(this, Label::kDeferred);
539 Label throw_typeerror(this, Label::kDeferred);
540
541 GotoIf(TaggedIsSmi(receiver), &throw_bad_receiver);
542
543 Node* map = LoadMap(receiver);
544 Node* instance_type = LoadMapInstanceType(map);
545 GotoIf(Word32NotEqual(instance_type, Int32Constant(JS_TYPED_ARRAY_TYPE)),
546 &throw_bad_receiver);
547
548 // Check if the {receiver}'s JSArrayBuffer was neutered.
549 Node* receiver_buffer =
550 LoadObjectField(receiver, JSTypedArray::kBufferOffset);
551 Label if_receiverisneutered(this, Label::kDeferred);
552 GotoIf(IsDetachedBuffer(receiver_buffer), &if_receiverisneutered);
553
554 Return(CreateArrayIterator(receiver, map, instance_type, context,
555 kIterationKind));
556
557 Variable var_message(this, MachineRepresentation::kTagged);
558 Bind(&throw_bad_receiver);
559 var_message.Bind(SmiConstant(MessageTemplate::kNotTypedArray));
560 Goto(&throw_typeerror);
561
562 Bind(&if_receiverisneutered);
563 var_message.Bind(
564 SmiConstant(Smi::FromInt(MessageTemplate::kDetachedOperation)));
565 Goto(&throw_typeerror);
566
567 Bind(&throw_typeerror);
568 {
569 Node* method_arg = HeapConstant(
570 isolate()->factory()->NewStringFromAsciiChecked(method_name, TENURED));
571 Node* result = CallRuntime(Runtime::kThrowTypeError, context,
572 var_message.value(), method_arg);
573 Return(result);
574 }
575 }
576
577 TF_BUILTIN(TypedArrayPrototypeValues, TypedArrayBuiltinsAssembler) {
578 GenerateTypedArrayPrototypeIterationMethod<IterationKind::kValues>(
579 "%TypedArray%.prototype.values()");
580 }
581
582 TF_BUILTIN(TypedArrayPrototypeEntries, TypedArrayBuiltinsAssembler) {
583 GenerateTypedArrayPrototypeIterationMethod<IterationKind::kEntries>(
584 "%TypedArray%.prototype.entries()");
585 }
586
587 TF_BUILTIN(TypedArrayPrototypeKeys, TypedArrayBuiltinsAssembler) {
588 GenerateTypedArrayPrototypeIterationMethod<IterationKind::kKeys>(
589 "%TypedArray%.prototype.keys()");
590 }
591
592 namespace { 24 namespace {
593 25
594 int64_t CapRelativeIndex(Handle<Object> num, int64_t minimum, int64_t maximum) { 26 int64_t CapRelativeIndex(Handle<Object> num, int64_t minimum, int64_t maximum) {
595 int64_t relative; 27 int64_t relative;
596 if (V8_LIKELY(num->IsSmi())) { 28 if (V8_LIKELY(num->IsSmi())) {
597 relative = Smi::cast(*num)->value(); 29 relative = Smi::cast(*num)->value();
598 } else { 30 } else {
599 DCHECK(num->IsHeapNumber()); 31 DCHECK(num->IsHeapNumber());
600 double fp = HeapNumber::cast(*num)->value(); 32 double fp = HeapNumber::cast(*num)->value();
601 if (V8_UNLIKELY(!std::isfinite(fp))) { 33 if (V8_UNLIKELY(!std::isfinite(fp))) {
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 ElementsAccessor* elements = array->GetElementsAccessor(); 167 ElementsAccessor* elements = array->GetElementsAccessor();
736 Maybe<int64_t> result = elements->IndexOfValue(isolate, array, search_element, 168 Maybe<int64_t> result = elements->IndexOfValue(isolate, array, search_element,
737 static_cast<uint32_t>(index), 169 static_cast<uint32_t>(index),
738 static_cast<uint32_t>(len)); 170 static_cast<uint32_t>(len));
739 MAYBE_RETURN(result, isolate->heap()->exception()); 171 MAYBE_RETURN(result, isolate->heap()->exception());
740 return *isolate->factory()->NewNumberFromInt64(result.FromJust()); 172 return *isolate->factory()->NewNumberFromInt64(result.FromJust());
741 } 173 }
742 174
743 } // namespace internal 175 } // namespace internal
744 } // namespace v8 176 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-symbol-gen.cc ('k') | src/builtins/builtins-typedarray-gen.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698