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

Side by Side Diff: src/compiler/js-builtin-reducer.cc

Issue 2484003002: [builtins] implement JSBuiltinReducer for ArrayIteratorNext() (Closed)
Patch Set: fix it more Created 4 years, 1 month 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
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/compiler/js-builtin-reducer.h" 5 #include "src/compiler/js-builtin-reducer.h"
6 6
7 #include "src/compilation-dependencies.h" 7 #include "src/compilation-dependencies.h"
8 #include "src/compiler/access-builder.h" 8 #include "src/compiler/access-builder.h"
9 #include "src/compiler/js-graph.h" 9 #include "src/compiler/js-graph.h"
10 #include "src/compiler/node-matchers.h" 10 #include "src/compiler/node-matchers.h"
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 IsFastElementsKind(receiver_map->elements_kind()) && 170 IsFastElementsKind(receiver_map->elements_kind()) &&
171 !receiver_map->is_dictionary_map() && receiver_map->is_extensible() && 171 !receiver_map->is_dictionary_map() && receiver_map->is_extensible() &&
172 (!receiver_map->is_prototype_map() || receiver_map->is_stable()) && 172 (!receiver_map->is_prototype_map() || receiver_map->is_stable()) &&
173 isolate->IsFastArrayConstructorPrototypeChainIntact() && 173 isolate->IsFastArrayConstructorPrototypeChainIntact() &&
174 isolate->IsAnyInitialArrayPrototype(receiver_prototype) && 174 isolate->IsAnyInitialArrayPrototype(receiver_prototype) &&
175 !IsReadOnlyLengthDescriptor(receiver_map); 175 !IsReadOnlyLengthDescriptor(receiver_map);
176 } 176 }
177 177
178 } // namespace 178 } // namespace
179 179
180 Reduction JSBuiltinReducer::ReduceArrayIterator(Node* node,
181 IterationKind kind) {
182 Handle<Map> receiver_map;
183 Node* receiver = NodeProperties::GetValueInput(node, 1);
184 Node* effect = NodeProperties::GetEffectInput(node);
185 Node* control = NodeProperties::GetControlInput(node);
186
187 if (GetMapWitness(node).ToHandle(&receiver_map)) {
188 int map_index = -1;
189 Node* object_map = jsgraph()->UndefinedConstant();
190 switch (receiver_map->instance_type()) {
191 case JS_ARRAY_TYPE:
192 if (kind == IterationKind::kKeys) {
193 map_index = Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX;
194 } else {
195 map_index =
196 kind == IterationKind::kValues
197 ? Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX
198 : Context::FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
199
200 if (IsFastElementsKind(receiver_map->elements_kind()) &&
Benedikt Meurer 2016/11/08 08:30:00 For holey arrays you first need to check whether a
caitp 2016/11/08 17:53:07 I did some creative stuff to have (I think) exactl
201 (!IsFastHoleyElementsKind(receiver_map->elements_kind()) ||
202 receiver_map->prototype() ==
203 native_context()->initial_array_prototype())) {
204 // Use `generic` elements for holey arrays if there may be elements
205 // on the prototype chain.
206 map_index += static_cast<int>(receiver_map->elements_kind());
207 object_map = jsgraph()->Constant(receiver_map);
208 if (IsFastHoleyElementsKind(receiver_map->elements_kind())) {
209 Handle<JSObject> initial_array_prototype(
210 native_context()->initial_array_prototype(), isolate());
211 dependencies()->AssumePrototypeMapsStable(
212 receiver_map, initial_array_prototype);
213 }
214 } else {
215 map_index += (Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX -
216 Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX);
217 }
218 }
219 break;
220 case JS_TYPED_ARRAY_TYPE:
221 if (kind == IterationKind::kKeys) {
222 map_index = Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX;
223 } else {
224 DCHECK_GE(receiver_map->elements_kind(), UINT8_ELEMENTS);
225 DCHECK_LE(receiver_map->elements_kind(), UINT8_CLAMPED_ELEMENTS);
226 map_index =
227 (kind == IterationKind::kValues
228 ? Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX
229 : Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX) +
230 (receiver_map->elements_kind() - UINT8_ELEMENTS);
231 }
232 break;
233 default:
234 if (kind == IterationKind::kKeys) {
235 map_index = Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX;
236 } else if (kind == IterationKind::kValues) {
237 map_index = Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX;
238 } else {
239 map_index = Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
240 }
241 break;
242 }
243
244 DCHECK_GE(map_index, Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX);
245 DCHECK_LE(map_index, Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX);
246
247 Handle<Map> map(Map::cast(native_context()->get(map_index)), isolate());
248
249 // allocate new iterator
250 effect = graph()->NewNode(
251 common()->BeginRegion(RegionObservability::kNotObservable), effect);
252 Node* value = effect = graph()->NewNode(
253 simplified()->Allocate(NOT_TENURED),
254 jsgraph()->Constant(JSArrayIterator::kSize), effect, control);
255 effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
256 value, jsgraph()->Constant(map), effect, control);
257 effect = graph()->NewNode(
258 simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
259 jsgraph()->EmptyFixedArrayConstant(), effect, control);
260 effect = graph()->NewNode(
261 simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
262 jsgraph()->EmptyFixedArrayConstant(), effect, control);
263
264 // attach the iterator to this object
265 effect = graph()->NewNode(
266 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
267 value, receiver, effect, control);
268 effect = graph()->NewNode(
269 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex()),
270 value, jsgraph()->ZeroConstant(), effect, control);
271 effect = graph()->NewNode(
272 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObjectMap()),
273 value, object_map, effect, control);
274
275 value = effect = graph()->NewNode(common()->FinishRegion(), value, effect);
276
277 // replace it
278 ReplaceWithValue(node, value, effect, control);
279 return Replace(value);
280 }
281 return NoChange();
282 }
283
284 Reduction JSBuiltinReducer::ReduceFastArrayIteratorNext(
285 Handle<Map> iterator_map, Node* node, IterationKind kind) {
286 Node* iterator = NodeProperties::GetValueInput(node, 1);
287 Node* effect = NodeProperties::GetEffectInput(node);
288 Node* control = NodeProperties::GetControlInput(node);
289 Node* context = NodeProperties::GetContextInput(node);
290
291 if (kind != IterationKind::kKeys && !isolate()->CanInlineArrayIterator()) {
292 // Avoid deopt loops for non-key iteration if the array_iterator_protector
293 // cell has been invalidated.
294 return NoChange();
295 }
296
297 ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
298 iterator_map->instance_type());
299
300 if (IsFastHoleyElementsKind(elements_kind)) {
301 if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
302 return NoChange();
303 } else {
304 Handle<JSObject> initial_array_prototype(
305 native_context()->initial_array_prototype(), isolate());
306 dependencies()->AssumePropertyCell(factory()->array_protector());
307 }
308 }
309
310 Node* array = effect = graph()->NewNode(
311 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
312 iterator, effect, control);
313 Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), array,
314 jsgraph()->UndefinedConstant());
315 Node* branch0 =
316 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
317
318 Node* vdone_false0;
319 Node* vfalse0;
320 Node* efalse0 = effect;
321 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
322 {
323 // iterator.[[IteratedObject]] !== undefined, continue iterating.
324 Node* index = efalse0 = graph()->NewNode(
325 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
326 JS_ARRAY_TYPE, elements_kind)),
327 iterator, efalse0, if_false0);
328
329 Node* length = efalse0 = graph()->NewNode(
330 simplified()->LoadField(AccessBuilder::ForJSArrayLength(elements_kind)),
331 array, efalse0, if_false0);
332 Node* check1 =
333 graph()->NewNode(simplified()->NumberLessThan(), index, length);
334 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
335 check1, if_false0);
336
337 Node* vdone_true1;
338 Node* vtrue1;
339 Node* etrue1 = efalse0;
340 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
341 {
342 // iterator.[[NextIndex]] < array.length, continue iterating
343 vdone_true1 = jsgraph()->FalseConstant();
344 if (kind == IterationKind::kKeys) {
345 vtrue1 = index;
346 } else {
347 // For value/entry iteration, first step is a mapcheck to ensure
348 // inlining is still valid.
349 Node* orig_map = etrue1 =
350 graph()->NewNode(simplified()->LoadField(
351 AccessBuilder::ForJSArrayIteratorObjectMap()),
352 iterator, etrue1, if_true1);
353 etrue1 = graph()->NewNode(simplified()->CheckMaps(1), array, orig_map,
354 etrue1, if_true1);
355 }
356
357 Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
358 jsgraph()->OneConstant());
359 next_index = graph()->NewNode(simplified()->NumberToUint32(), next_index);
360
361 etrue1 = graph()->NewNode(
362 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
363 JS_ARRAY_TYPE, elements_kind)),
364 iterator, next_index, etrue1, if_true1);
365
366 if (kind != IterationKind::kKeys) {
367 Node* elements = etrue1 = graph()->NewNode(
368 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
369 array, etrue1, if_true1);
370 Node* value = etrue1 = graph()->NewNode(
371 simplified()->LoadElement(
372 AccessBuilder::ForFixedArrayElement(elements_kind)),
373 elements, index, etrue1, if_true1);
374
375 // Convert hole to undefined if needed.
376 if (elements_kind == FAST_HOLEY_ELEMENTS ||
377 elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
378 value = graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(),
379 value);
380 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
381 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kAllowReturnHole;
382 // Check if we are allowed to return the hole directly.
383 value = etrue1 = graph()->NewNode(
384 simplified()->CheckFloat64Hole(mode), value, etrue1, if_true1);
385 }
386
387 if (kind == IterationKind::kEntries) {
388 // Allocate elements for key/value pair
389 etrue1 = graph()->NewNode(
390 common()->BeginRegion(RegionObservability::kNotObservable),
391 etrue1);
392 Node* elements = etrue1 = graph()->NewNode(
393 simplified()->Allocate(NOT_TENURED),
394 jsgraph()->Constant(FixedArray::SizeFor(2)), etrue1, if_true1);
395 etrue1 = graph()->NewNode(
396 simplified()->StoreField(AccessBuilder::ForMap()), elements,
397 jsgraph()->Constant(isolate()->factory()->fixed_array_map()),
398 etrue1, if_true1);
399 etrue1 = graph()->NewNode(
400 simplified()->StoreField(AccessBuilder::ForFixedArrayLength()),
401 elements, jsgraph()->Constant(2));
402 etrue1 = graph()->NewNode(
403 simplified()->StoreElement(
404 AccessBuilder::ForFixedArrayElement(FAST_ELEMENTS)),
405 elements, jsgraph()->Constant(0), index, etrue1, if_true1);
406 etrue1 = graph()->NewNode(
407 simplified()->StoreElement(
408 AccessBuilder::ForFixedArrayElement(FAST_ELEMENTS)),
409 elements, jsgraph()->Constant(1), value, etrue1, if_true1);
410 elements = etrue1 =
411 graph()->NewNode(common()->FinishRegion(), elements, etrue1);
412
413 // Allocate JSArray for key/value pair
414 etrue1 = graph()->NewNode(
415 common()->BeginRegion(RegionObservability::kNotObservable),
416 etrue1);
417 Node* entry = etrue1 = graph()->NewNode(
418 simplified()->Allocate(NOT_TENURED),
419 jsgraph()->Constant(JSArray::kSize), etrue1, if_true1);
420 etrue1 = graph()->NewNode(
421 simplified()->StoreField(AccessBuilder::ForMap()), entry,
422 jsgraph()->Constant(
423 handle(native_context()->js_array_fast_elements_map_index())),
424 etrue1, if_true1);
425 etrue1 = graph()->NewNode(
426 simplified()->StoreField(AccessBuilder::ForJSObjectProperties()),
427 entry, jsgraph()->EmptyFixedArrayConstant(), etrue1, if_true1);
428 etrue1 = graph()->NewNode(
429 simplified()->StoreField(AccessBuilder::ForJSObjectElements()),
430 entry, elements, etrue1, if_true1);
431 etrue1 = graph()->NewNode(
432 simplified()->StoreField(
433 AccessBuilder::ForJSArrayLength(elements_kind)),
434 entry, jsgraph()->Constant(2), etrue1, if_true1);
435 entry = etrue1 =
436 graph()->NewNode(common()->FinishRegion(), entry, etrue1);
437 vtrue1 = entry;
438 } else {
439 DCHECK(kind == IterationKind::kValues);
Benedikt Meurer 2016/11/08 08:30:00 Please use DCHECK_EQ here (and add operator<< over
caitp 2016/11/08 17:53:07 will do that for the next one
440 vtrue1 = value;
441 }
442 }
443 }
444
445 Node* vdone_false1;
446 Node* vfalse1;
447 Node* efalse1 = efalse0;
448 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
449 {
450 // iterator.[[NextIndex]] >= array.length, stop iterating.
451 vdone_false1 = jsgraph()->TrueConstant();
452 vfalse1 = jsgraph()->UndefinedConstant();
453 efalse1 = graph()->NewNode(
454 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
455 iterator, vfalse1, efalse1, if_false1);
456 }
457
458 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
459 efalse0 =
460 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
461 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
462 vtrue1, vfalse1, if_false0);
463 vdone_false0 =
464 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
465 vdone_true1, vdone_false1, if_false0);
466 }
467
468 Node* vdone_true0;
469 Node* vtrue0;
470 Node* etrue0 = effect;
471 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
472 {
473 // iterator.[[IteratedObject]] === undefined, the iterator is done.
474 vdone_true0 = jsgraph()->TrueConstant();
475 vtrue0 = jsgraph()->UndefinedConstant();
476 }
477
478 control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
479 effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
480 Node* value =
481 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
482 vfalse0, vtrue0, control);
483 Node* done =
484 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
485 vdone_false0, vdone_true0, control);
486
487 // Create IteratorResult object.
488 value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
489 value, done, context, effect);
490 ReplaceWithValue(node, value, effect, control);
491 return Replace(value);
492 }
493
494 Reduction JSBuiltinReducer::ReduceTypedArrayIteratorNext(
495 Handle<Map> iterator_map, Node* node, IterationKind kind) {
496 Node* iterator = NodeProperties::GetValueInput(node, 1);
497 Node* effect = NodeProperties::GetEffectInput(node);
498 Node* control = NodeProperties::GetControlInput(node);
499 Node* context = NodeProperties::GetContextInput(node);
500
501 ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
502 iterator_map->instance_type());
503
504 Node* array = effect = graph()->NewNode(
505 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
506 iterator, effect, control);
507 Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), array,
508 jsgraph()->UndefinedConstant());
509 Node* branch0 =
510 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
511
512 Node* vdone_false0;
513 Node* vfalse0;
514 Node* efalse0 = effect;
515 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
516 {
517 // iterator.[[IteratedObject]] !== undefined, continue iterating.
518 Node* index = efalse0 = graph()->NewNode(
519 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
520 JS_TYPED_ARRAY_TYPE, elements_kind)),
521 iterator, efalse0, if_false0);
522
523 // typedarray.[[ViewedArrayBuffer]]
524 Node* buffer = efalse0 = graph()->NewNode(
525 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
526 array, efalse0, if_false0);
527
528 Node* check1 = efalse0 = graph()->NewNode(
529 simplified()->ArrayBufferWasNeutered(), buffer, efalse0, if_false0);
530 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
531 check1, if_false0);
532
533 Node* vfalse1;
534 Node* efalse1 = efalse0;
535 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
536 {
537 vfalse1 = efalse1 = graph()->NewNode(
538 simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()),
539 array, efalse1, if_false1);
540 }
541
542 Node* vtrue1;
543 Node* etrue1 = efalse0;
544 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
545 {
546 // TODO(caitp): If IsDetached(buffer) is true, throw a TypeError, per
547 // https://github.com/tc39/ecma262/issues/713
548 vtrue1 = jsgraph()->Constant(0);
549 }
550
551 if_false0 = graph()->NewNode(common()->Merge(2), if_false1, if_true1);
552 efalse0 =
553 graph()->NewNode(common()->EffectPhi(2), efalse1, etrue1, if_false0);
554 Node* length =
555 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
556 vfalse1, vtrue1, if_false0);
557
558 Node* check2 =
559 graph()->NewNode(simplified()->NumberLessThan(), index, length);
560 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
561 check2, if_false0);
562
563 Node* vdone_true2;
564 Node* vtrue2;
565 Node* etrue2 = efalse0;
566 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
567 {
568 // iterator.[[NextIndex]] < array.length, continue iterating
569 vdone_true2 = jsgraph()->FalseConstant();
570 if (kind == IterationKind::kKeys) {
571 vtrue2 = index;
572 }
573
574 Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
575 jsgraph()->OneConstant());
Benedikt Meurer 2016/11/08 08:30:00 Here you also need to do the NumberToUint32 trunca
caitp 2016/11/08 17:53:07 added truncation for both cases
576 etrue2 = graph()->NewNode(
577 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
578 JS_TYPED_ARRAY_TYPE, elements_kind)),
579 iterator, next_index, etrue2, if_true2);
580
581 if (kind != IterationKind::kKeys) {
582 Node* elements = etrue2 = graph()->NewNode(
583 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
584 array, etrue2, if_true2);
585 Node* base_ptr = etrue2 = graph()->NewNode(
586 simplified()->LoadField(
587 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
588 elements, etrue2, if_true2);
589 Node* external_ptr = etrue2 = graph()->NewNode(
590 simplified()->LoadField(
591 AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
592 elements, etrue2, if_true2);
593
594 ExternalArrayType array_type = kExternalInt8Array;
595 switch (elements_kind) {
596 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
597 case TYPE##_ELEMENTS: \
598 array_type = kExternal##Type##Array;
599 TYPED_ARRAYS(TYPED_ARRAY_CASE)
600 default:
601 UNREACHABLE();
602 #undef TYPED_ARRAY_CASE
603 }
604
605 Node* value = etrue2 =
606 graph()->NewNode(simplified()->LoadTypedElement(array_type), buffer,
607 base_ptr, external_ptr, index, etrue2, if_true2);
608
609 if (kind == IterationKind::kEntries) {
610 // Allocate elements for key/value pair
611 etrue2 = graph()->NewNode(
612 common()->BeginRegion(RegionObservability::kNotObservable),
613 etrue2);
614 Node* elements = etrue2 = graph()->NewNode(
615 simplified()->Allocate(NOT_TENURED),
616 jsgraph()->Constant(FixedArray::SizeFor(2)), etrue2, if_true2);
617 etrue2 = graph()->NewNode(
618 simplified()->StoreField(AccessBuilder::ForMap()), elements,
619 jsgraph()->Constant(isolate()->factory()->fixed_array_map()),
620 etrue1, if_true2);
621 etrue2 = graph()->NewNode(
622 simplified()->StoreField(AccessBuilder::ForFixedArrayLength()),
623 elements, jsgraph()->Constant(2));
624 etrue2 = graph()->NewNode(
625 simplified()->StoreElement(
626 AccessBuilder::ForFixedArrayElement(FAST_ELEMENTS)),
627 elements, jsgraph()->Constant(0), index, etrue2, if_true2);
628 etrue2 = graph()->NewNode(
629 simplified()->StoreElement(
630 AccessBuilder::ForFixedArrayElement(FAST_ELEMENTS)),
631 elements, jsgraph()->Constant(1), value, etrue2, if_true2);
632 elements = etrue2 =
633 graph()->NewNode(common()->FinishRegion(), elements, etrue2);
634
635 // Allocate JSArray for key/value pair
636 etrue2 = graph()->NewNode(
637 common()->BeginRegion(RegionObservability::kNotObservable),
638 etrue2);
639 Node* entry = etrue2 = graph()->NewNode(
640 simplified()->Allocate(NOT_TENURED),
641 jsgraph()->Constant(JSArray::kSize), etrue2, if_true2);
642 etrue2 = graph()->NewNode(
643 simplified()->StoreField(AccessBuilder::ForMap()), entry,
644 jsgraph()->Constant(
645 handle(native_context()->js_array_fast_elements_map_index())),
646 etrue2, if_true2);
647 etrue2 = graph()->NewNode(
648 simplified()->StoreField(AccessBuilder::ForJSObjectProperties()),
649 entry, jsgraph()->EmptyFixedArrayConstant(), etrue2, if_true2);
650 etrue2 = graph()->NewNode(
651 simplified()->StoreField(AccessBuilder::ForJSObjectElements()),
652 entry, elements, etrue2, if_true2);
653 etrue2 = graph()->NewNode(
654 simplified()->StoreField(
655 AccessBuilder::ForJSArrayLength(elements_kind)),
656 entry, jsgraph()->Constant(2), etrue2, if_true2);
657 entry = etrue1 =
658 graph()->NewNode(common()->FinishRegion(), entry, etrue2);
659 vtrue2 = entry;
660 } else {
661 DCHECK(kind == IterationKind::kValues);
662 vtrue2 = value;
663 }
664 }
665 }
666
667 Node* vdone_false2;
668 Node* vfalse2;
669 Node* efalse2 = efalse0;
670 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
671 {
672 // iterator.[[NextIndex]] >= array.length, stop iterating.
673 vdone_false2 = jsgraph()->TrueConstant();
674 vfalse2 = jsgraph()->UndefinedConstant();
675 efalse2 = graph()->NewNode(
676 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
677 iterator, vfalse2, efalse2, if_false2);
678 }
679
680 if_false0 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
681 efalse0 =
682 graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, if_false0);
683 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
684 vtrue2, vfalse2, if_false0);
685 vdone_false0 =
686 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
687 vdone_true2, vdone_false2, if_false0);
688 }
689
690 Node* vdone_true0;
691 Node* vtrue0;
692 Node* etrue0 = effect;
693 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
694 {
695 // iterator.[[IteratedObject]] === undefined, the iterator is done.
696 vdone_true0 = jsgraph()->TrueConstant();
697 vtrue0 = jsgraph()->UndefinedConstant();
698 }
699
700 control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
701 effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
702 Node* value =
703 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
704 vfalse0, vtrue0, control);
705 Node* done =
706 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
707 vdone_false0, vdone_true0, control);
708
709 // Create IteratorResult object.
710 value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
711 value, done, context, effect);
712 ReplaceWithValue(node, value, effect, control);
713 return Replace(value);
714 }
715
716 Reduction JSBuiltinReducer::ReduceArrayIteratorNext(Node* node) {
717 Handle<Map> receiver_map;
718 if (GetMapWitness(node).ToHandle(&receiver_map)) {
719 switch (receiver_map->instance_type()) {
720 case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
721 return ReduceTypedArrayIteratorNext(receiver_map, node,
722 IterationKind::kKeys);
723
724 case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
725 return ReduceFastArrayIteratorNext(receiver_map, node,
726 IterationKind::kKeys);
727
728 case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
729 case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
730 case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
731 case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
732 case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
733 case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
734 case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
735 case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
736 case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
737 return ReduceTypedArrayIteratorNext(receiver_map, node,
738 IterationKind::kEntries);
739
740 case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
741 case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
742 case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
743 case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
744 case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
745 case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
746 return ReduceFastArrayIteratorNext(receiver_map, node,
747 IterationKind::kEntries);
748
749 case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
750 case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
751 case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
752 case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
753 case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
754 case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
755 case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
756 case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
757 case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
758 return ReduceTypedArrayIteratorNext(receiver_map, node,
759 IterationKind::kValues);
760
761 case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
762 case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
763 case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
764 case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
765 case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
766 case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
767 return ReduceFastArrayIteratorNext(receiver_map, node,
768 IterationKind::kValues);
769
770 default:
771 // Slow array iterators are not reduced
772 return NoChange();
773 }
774 }
775 return NoChange();
776 }
777
180 // ES6 section 22.1.3.17 Array.prototype.pop ( ) 778 // ES6 section 22.1.3.17 Array.prototype.pop ( )
181 Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) { 779 Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) {
182 Handle<Map> receiver_map; 780 Handle<Map> receiver_map;
183 Node* receiver = NodeProperties::GetValueInput(node, 1); 781 Node* receiver = NodeProperties::GetValueInput(node, 1);
184 Node* effect = NodeProperties::GetEffectInput(node); 782 Node* effect = NodeProperties::GetEffectInput(node);
185 Node* control = NodeProperties::GetControlInput(node); 783 Node* control = NodeProperties::GetControlInput(node);
186 // TODO(turbofan): Extend this to also handle fast (holey) double elements 784 // TODO(turbofan): Extend this to also handle fast (holey) double elements
187 // once we got the hole NaN mess sorted out in TurboFan/V8. 785 // once we got the hole NaN mess sorted out in TurboFan/V8.
188 if (GetMapWitness(node).ToHandle(&receiver_map) && 786 if (GetMapWitness(node).ToHandle(&receiver_map) &&
189 CanInlineArrayResizeOperation(receiver_map) && 787 CanInlineArrayResizeOperation(receiver_map) &&
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 return NoChange(); 1851 return NoChange();
1254 } 1852 }
1255 1853
1256 Reduction JSBuiltinReducer::Reduce(Node* node) { 1854 Reduction JSBuiltinReducer::Reduce(Node* node) {
1257 Reduction reduction = NoChange(); 1855 Reduction reduction = NoChange();
1258 JSCallReduction r(node); 1856 JSCallReduction r(node);
1259 1857
1260 // Dispatch according to the BuiltinFunctionId if present. 1858 // Dispatch according to the BuiltinFunctionId if present.
1261 if (!r.HasBuiltinFunctionId()) return NoChange(); 1859 if (!r.HasBuiltinFunctionId()) return NoChange();
1262 switch (r.GetBuiltinFunctionId()) { 1860 switch (r.GetBuiltinFunctionId()) {
1861 case kArrayEntries:
1862 return ReduceArrayIterator(node, IterationKind::kEntries);
1863 case kArrayKeys:
1864 return ReduceArrayIterator(node, IterationKind::kKeys);
1865 case kArrayValues:
1866 return ReduceArrayIterator(node, IterationKind::kValues);
1867 case kArrayIteratorNext:
1868 return ReduceArrayIteratorNext(node);
1263 case kArrayPop: 1869 case kArrayPop:
1264 return ReduceArrayPop(node); 1870 return ReduceArrayPop(node);
1265 case kArrayPush: 1871 case kArrayPush:
1266 return ReduceArrayPush(node); 1872 return ReduceArrayPush(node);
1267 case kDateGetTime: 1873 case kDateGetTime:
1268 return ReduceDateGetTime(node); 1874 return ReduceDateGetTime(node);
1269 case kGlobalIsFinite: 1875 case kGlobalIsFinite:
1270 reduction = ReduceGlobalIsFinite(node); 1876 reduction = ReduceGlobalIsFinite(node);
1271 break; 1877 break;
1272 case kGlobalIsNaN: 1878 case kGlobalIsNaN:
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
1456 return jsgraph()->simplified(); 2062 return jsgraph()->simplified();
1457 } 2063 }
1458 2064
1459 JSOperatorBuilder* JSBuiltinReducer::javascript() const { 2065 JSOperatorBuilder* JSBuiltinReducer::javascript() const {
1460 return jsgraph()->javascript(); 2066 return jsgraph()->javascript();
1461 } 2067 }
1462 2068
1463 } // namespace compiler 2069 } // namespace compiler
1464 } // namespace internal 2070 } // namespace internal
1465 } // namespace v8 2071 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698