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

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

Issue 2484003002: [builtins] implement JSBuiltinReducer for ArrayIteratorNext() (Closed)
Patch Set: add (some) test coverage, and fix some bugs found by it 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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 } 168 }
169 return receiver_map->instance_type() == JS_ARRAY_TYPE && 169 return receiver_map->instance_type() == JS_ARRAY_TYPE &&
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 bool CanInlineJSArrayIteration(Handle<Map> receiver_map) {
179 Isolate* const isolate = receiver_map->GetIsolate();
180 // Ensure that the [[Prototype]] is actually an exotic Array
181 if (!receiver_map->prototype()->IsJSArray()) return false;
182
183 // Don't inline JSArrays with slow elements of any kind
184 if (!IsFastElementsKind(receiver_map->elements_kind())) return false;
185
186 // If the receiver map has packed elements, no need to check the prototype.
187 // This requires a MapCheck where this is used.
188 if (!IsFastHoleyElementsKind(receiver_map->elements_kind())) return true;
189
190 Handle<JSArray> receiver_prototype(JSArray::cast(receiver_map->prototype()),
191 isolate);
192 // Ensure all prototypes of the {receiver} are stable.
193 for (PrototypeIterator it(isolate, receiver_prototype, kStartAtReceiver);
194 !it.IsAtEnd(); it.Advance()) {
195 Handle<JSReceiver> current = PrototypeIterator::GetCurrent<JSReceiver>(it);
196 if (!current->map()->is_stable()) return false;
197 }
198
199 // For holey Arrays, ensure that the array_protector cell is valid (must be
200 // a CompilationDependency), and the JSArray prototype has not been altered.
201 return receiver_map->instance_type() == JS_ARRAY_TYPE &&
202 (!receiver_map->is_dictionary_map() || receiver_map->is_stable()) &&
203 isolate->IsFastArrayConstructorPrototypeChainIntact() &&
204 isolate->IsAnyInitialArrayPrototype(receiver_prototype);
205 }
206
178 } // namespace 207 } // namespace
179 208
209 Reduction JSBuiltinReducer::ReduceArrayIterator(Node* node,
210 IterationKind kind) {
211 Handle<Map> receiver_map;
212 if (GetMapWitness(node).ToHandle(&receiver_map)) {
213 return ReduceArrayIterator(receiver_map, node, kind,
214 ArrayIteratorKind::kArray);
215 }
216 return NoChange();
217 }
218
219 Reduction JSBuiltinReducer::ReduceTypedArrayIterator(Node* node,
220 IterationKind kind) {
221 Handle<Map> receiver_map;
222 if (GetMapWitness(node).ToHandle(&receiver_map) &&
223 receiver_map->instance_type() == JS_TYPED_ARRAY_TYPE) {
224 return ReduceArrayIterator(receiver_map, node, kind,
225 ArrayIteratorKind::kTypedArray);
226 }
227 return NoChange();
228 }
229
230 Reduction JSBuiltinReducer::ReduceArrayIterator(Handle<Map> receiver_map,
231 Node* node, IterationKind kind,
232 ArrayIteratorKind iter_kind) {
233 Node* receiver = NodeProperties::GetValueInput(node, 1);
234 Node* effect = NodeProperties::GetEffectInput(node);
235 Node* control = NodeProperties::GetControlInput(node);
236
237 if (iter_kind == ArrayIteratorKind::kTypedArray) {
238 // For JSTypedArray iterator methods, deopt if the buffer is neutered. This
239 // is potentially a deopt loop, but should be extremely unlikely.
240 DCHECK_EQ(JS_TYPED_ARRAY_TYPE, receiver_map->instance_type());
241 Node* buffer = effect = graph()->NewNode(
242 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
243 receiver, effect, control);
244
245 Node* check = effect = graph()->NewNode(
246 simplified()->ArrayBufferWasNeutered(), buffer, effect, control);
247 check = graph()->NewNode(simplified()->BooleanNot(), check);
248 effect = graph()->NewNode(simplified()->CheckIf(), check, effect, control);
249 }
250
251 int map_index = -1;
252 Node* object_map = jsgraph()->UndefinedConstant();
253 switch (receiver_map->instance_type()) {
254 case JS_ARRAY_TYPE:
255 if (kind == IterationKind::kKeys) {
256 map_index = Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX;
257 } else {
258 map_index = kind == IterationKind::kValues
259 ? Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX
260 : Context::FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
261
262 if (CanInlineJSArrayIteration(receiver_map)) {
263 // Use `generic` elements for holey arrays if there may be elements
264 // on the prototype chain.
265 map_index += static_cast<int>(receiver_map->elements_kind());
266 object_map = jsgraph()->Constant(receiver_map);
267 if (IsFastHoleyElementsKind(receiver_map->elements_kind())) {
268 Handle<JSObject> initial_array_prototype(
269 native_context()->initial_array_prototype(), isolate());
270 dependencies()->AssumePrototypeMapsStable(receiver_map,
271 initial_array_prototype);
272 }
273 } else {
274 map_index += (Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX -
275 Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX);
276 }
277 }
278 break;
279 case JS_TYPED_ARRAY_TYPE:
280 if (kind == IterationKind::kKeys) {
281 map_index = Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX;
282 } else {
283 DCHECK_GE(receiver_map->elements_kind(), UINT8_ELEMENTS);
284 DCHECK_LE(receiver_map->elements_kind(), UINT8_CLAMPED_ELEMENTS);
285 map_index = (kind == IterationKind::kValues
286 ? Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX
287 : Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX) +
288 (receiver_map->elements_kind() - UINT8_ELEMENTS);
289 }
290 break;
291 default:
292 if (kind == IterationKind::kKeys) {
293 map_index = Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX;
294 } else if (kind == IterationKind::kValues) {
295 map_index = Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX;
296 } else {
297 map_index = Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
298 }
299 break;
300 }
301
302 DCHECK_GE(map_index, Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX);
303 DCHECK_LE(map_index, Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX);
304
305 Handle<Map> map(Map::cast(native_context()->get(map_index)), isolate());
306
307 // allocate new iterator
308 effect = graph()->NewNode(
309 common()->BeginRegion(RegionObservability::kNotObservable), effect);
310 Node* value = effect = graph()->NewNode(
311 simplified()->Allocate(NOT_TENURED),
312 jsgraph()->Constant(JSArrayIterator::kSize), effect, control);
313 effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
314 value, jsgraph()->Constant(map), effect, control);
315 effect = graph()->NewNode(
316 simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
317 jsgraph()->EmptyFixedArrayConstant(), effect, control);
318 effect = graph()->NewNode(
319 simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
320 jsgraph()->EmptyFixedArrayConstant(), effect, control);
321
322 // attach the iterator to this object
323 effect = graph()->NewNode(
324 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
325 value, receiver, effect, control);
326 effect = graph()->NewNode(
327 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex()), value,
328 jsgraph()->ZeroConstant(), effect, control);
329 effect = graph()->NewNode(
330 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObjectMap()),
331 value, object_map, effect, control);
332
333 value = effect = graph()->NewNode(common()->FinishRegion(), value, effect);
334
335 // replace it
336 ReplaceWithValue(node, value, effect, control);
337 return Replace(value);
338 }
339
340 Reduction JSBuiltinReducer::ReduceFastArrayIteratorNext(
341 Handle<Map> iterator_map, Node* node, IterationKind kind) {
342 Node* iterator = NodeProperties::GetValueInput(node, 1);
343 Node* effect = NodeProperties::GetEffectInput(node);
344 Node* control = NodeProperties::GetControlInput(node);
345 Node* context = NodeProperties::GetContextInput(node);
346
347 if (kind != IterationKind::kKeys && !isolate()->CanInlineArrayIterator()) {
348 // Avoid deopt loops for non-key iteration if the array_iterator_protector
349 // cell has been invalidated.
350 return NoChange();
351 }
352
353 ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
354 iterator_map->instance_type());
355
356 if (IsFastHoleyElementsKind(elements_kind)) {
357 if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
358 return NoChange();
359 } else {
360 Handle<JSObject> initial_array_prototype(
361 native_context()->initial_array_prototype(), isolate());
362 dependencies()->AssumePropertyCell(factory()->array_protector());
363 }
364 }
365
366 Node* array = effect = graph()->NewNode(
367 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
368 iterator, effect, control);
369 Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), array,
370 jsgraph()->UndefinedConstant());
371 Node* branch0 =
372 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
373
374 Node* vdone_false0;
375 Node* vfalse0;
376 Node* efalse0 = effect;
377 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
378 {
379 // iterator.[[IteratedObject]] !== undefined, continue iterating.
380 Node* index = efalse0 = graph()->NewNode(
381 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
382 JS_ARRAY_TYPE, elements_kind)),
383 iterator, efalse0, if_false0);
384
385 Node* length = efalse0 = graph()->NewNode(
386 simplified()->LoadField(AccessBuilder::ForJSArrayLength(elements_kind)),
387 array, efalse0, if_false0);
388 Node* check1 =
389 graph()->NewNode(simplified()->NumberLessThan(), index, length);
390 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
391 check1, if_false0);
392
393 Node* vdone_true1;
394 Node* vtrue1;
395 Node* etrue1 = efalse0;
396 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
397 {
398 // iterator.[[NextIndex]] < array.length, continue iterating
399 vdone_true1 = jsgraph()->FalseConstant();
400 if (kind == IterationKind::kKeys) {
401 vtrue1 = index;
402 } else {
403 // For value/entry iteration, first step is a mapcheck to ensure
404 // inlining is still valid.
405 Node* orig_map = etrue1 =
406 graph()->NewNode(simplified()->LoadField(
407 AccessBuilder::ForJSArrayIteratorObjectMap()),
408 iterator, etrue1, if_true1);
409 etrue1 = graph()->NewNode(simplified()->CheckMaps(1), array, orig_map,
410 etrue1, if_true1);
411 }
412
413 if (kind != IterationKind::kKeys) {
414 Node* elements = etrue1 = graph()->NewNode(
415 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
416 array, etrue1, if_true1);
417 Node* value = etrue1 = graph()->NewNode(
418 simplified()->LoadElement(
419 AccessBuilder::ForFixedArrayElement(elements_kind)),
420 elements, index, etrue1, if_true1);
421
422 // Convert hole to undefined if needed.
423 if (elements_kind == FAST_HOLEY_ELEMENTS ||
424 elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
425 value = graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(),
426 value);
427 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
428 // TODO(bmeurer): avoid deopt if not all uses of value are truncated.
429 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kAllowReturnHole;
430 value = etrue1 = graph()->NewNode(
431 simplified()->CheckFloat64Hole(mode), value, etrue1, if_true1);
432 }
433
434 if (kind == IterationKind::kEntries) {
435 // Allocate elements for key/value pair
436 vtrue1 = etrue1 = graph()->NewNode(
437 javascript()->CreateKeyValueArray(), index, value, etrue1);
438 } else {
439 DCHECK_EQ(kind, IterationKind::kValues);
440 vtrue1 = value;
441 }
442 }
443
444 Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
445 jsgraph()->OneConstant());
446 next_index = graph()->NewNode(simplified()->NumberToUint32(), next_index);
447
448 etrue1 = graph()->NewNode(
449 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
450 JS_ARRAY_TYPE, elements_kind)),
451 iterator, next_index, etrue1, if_true1);
452 }
453
454 Node* vdone_false1;
455 Node* vfalse1;
456 Node* efalse1 = efalse0;
457 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
458 {
459 // iterator.[[NextIndex]] >= array.length, stop iterating.
460 vdone_false1 = jsgraph()->TrueConstant();
461 vfalse1 = jsgraph()->UndefinedConstant();
462 efalse1 = graph()->NewNode(
463 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
464 iterator, vfalse1, efalse1, if_false1);
465 }
466
467 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
468 efalse0 =
469 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
470 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
471 vtrue1, vfalse1, if_false0);
472 vdone_false0 =
473 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
474 vdone_true1, vdone_false1, if_false0);
475 }
476
477 Node* vdone_true0;
478 Node* vtrue0;
479 Node* etrue0 = effect;
480 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
481 {
482 // iterator.[[IteratedObject]] === undefined, the iterator is done.
483 vdone_true0 = jsgraph()->TrueConstant();
484 vtrue0 = jsgraph()->UndefinedConstant();
485 }
486
487 control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
488 effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
489 Node* value =
490 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
491 vfalse0, vtrue0, control);
492 Node* done =
493 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
494 vdone_false0, vdone_true0, control);
495
496 // Create IteratorResult object.
497 value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
498 value, done, context, effect);
499 ReplaceWithValue(node, value, effect, control);
500 return Replace(value);
501 }
502
503 Reduction JSBuiltinReducer::ReduceTypedArrayIteratorNext(
504 Handle<Map> iterator_map, Node* node, IterationKind kind) {
505 Node* iterator = NodeProperties::GetValueInput(node, 1);
506 Node* effect = NodeProperties::GetEffectInput(node);
507 Node* control = NodeProperties::GetControlInput(node);
508 Node* context = NodeProperties::GetContextInput(node);
509
510 ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
511 iterator_map->instance_type());
512
513 Node* array = effect = graph()->NewNode(
514 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
515 iterator, effect, control);
516 Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), array,
517 jsgraph()->UndefinedConstant());
518 Node* branch0 =
519 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
520
521 Node* vdone_false0;
522 Node* vfalse0;
523 Node* efalse0 = effect;
524 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
525 {
526 // iterator.[[IteratedObject]] !== undefined, continue iterating.
527 Node* index = efalse0 = graph()->NewNode(
528 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
529 JS_TYPED_ARRAY_TYPE, elements_kind)),
530 iterator, efalse0, if_false0);
531
532 // typedarray.[[ViewedArrayBuffer]]
533 Node* buffer = efalse0 = graph()->NewNode(
534 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
535 array, efalse0, if_false0);
536
537 Node* check1 = efalse0 = graph()->NewNode(
538 simplified()->ArrayBufferWasNeutered(), buffer, efalse0, if_false0);
539 check1 = graph()->NewNode(simplified()->BooleanNot(), check1);
540 efalse0 =
541 graph()->NewNode(simplified()->CheckIf(), check1, efalse0, if_false0);
542
543 Node* length = efalse0 = graph()->NewNode(
544 simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()), array,
545 efalse0, if_false0);
546
547 Node* check2 =
548 graph()->NewNode(simplified()->NumberLessThan(), index, length);
549 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
550 check2, if_false0);
551
552 Node* vdone_true2;
553 Node* vtrue2;
554 Node* etrue2 = efalse0;
555 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
556 {
557 // iterator.[[NextIndex]] < array.length, continue iterating
558 vdone_true2 = jsgraph()->FalseConstant();
559 if (kind == IterationKind::kKeys) {
560 vtrue2 = index;
561 }
562
563 Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
564 jsgraph()->OneConstant());
565 next_index = graph()->NewNode(simplified()->NumberToUint32(), next_index);
566
567 etrue2 = graph()->NewNode(
568 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
569 JS_TYPED_ARRAY_TYPE, elements_kind)),
570 iterator, next_index, etrue2, if_true2);
571
572 if (kind != IterationKind::kKeys) {
573 Node* elements = etrue2 = graph()->NewNode(
574 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
575 array, etrue2, if_true2);
576 Node* base_ptr = etrue2 = graph()->NewNode(
577 simplified()->LoadField(
578 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
579 elements, etrue2, if_true2);
580 Node* external_ptr = etrue2 = graph()->NewNode(
581 simplified()->LoadField(
582 AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
583 elements, etrue2, if_true2);
584
585 ExternalArrayType array_type = kExternalInt8Array;
586 switch (elements_kind) {
587 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
588 case TYPE##_ELEMENTS: \
589 array_type = kExternal##Type##Array; \
590 break;
591 TYPED_ARRAYS(TYPED_ARRAY_CASE)
592 default:
593 UNREACHABLE();
594 #undef TYPED_ARRAY_CASE
595 }
596
597 Node* value = etrue2 =
598 graph()->NewNode(simplified()->LoadTypedElement(array_type), buffer,
599 base_ptr, external_ptr, index, etrue2, if_true2);
600
601 if (kind == IterationKind::kEntries) {
602 // Allocate elements for key/value pair
603 vtrue2 = etrue2 = graph()->NewNode(
604 javascript()->CreateKeyValueArray(), index, value, etrue2);
605 } else {
606 DCHECK(kind == IterationKind::kValues);
607 vtrue2 = value;
608 }
609 }
610 }
611
612 Node* vdone_false2;
613 Node* vfalse2;
614 Node* efalse2 = efalse0;
615 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
616 {
617 // iterator.[[NextIndex]] >= array.length, stop iterating.
618 vdone_false2 = jsgraph()->TrueConstant();
619 vfalse2 = jsgraph()->UndefinedConstant();
620 efalse2 = graph()->NewNode(
621 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
622 iterator, vfalse2, efalse2, if_false2);
623 }
624
625 if_false0 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
626 efalse0 =
627 graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, if_false0);
628 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
629 vtrue2, vfalse2, if_false0);
630 vdone_false0 =
631 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
632 vdone_true2, vdone_false2, if_false0);
633 }
634
635 Node* vdone_true0;
636 Node* vtrue0;
637 Node* etrue0 = effect;
638 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
639 {
640 // iterator.[[IteratedObject]] === undefined, the iterator is done.
641 vdone_true0 = jsgraph()->TrueConstant();
642 vtrue0 = jsgraph()->UndefinedConstant();
643 }
644
645 control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
646 effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
647 Node* value =
648 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
649 vfalse0, vtrue0, control);
650 Node* done =
651 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
652 vdone_false0, vdone_true0, control);
653
654 // Create IteratorResult object.
655 value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
656 value, done, context, effect);
657 ReplaceWithValue(node, value, effect, control);
658 return Replace(value);
659 }
660
661 Reduction JSBuiltinReducer::ReduceArrayIteratorNext(Node* node) {
662 Handle<Map> receiver_map;
663 if (GetMapWitness(node).ToHandle(&receiver_map)) {
664 switch (receiver_map->instance_type()) {
665 case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
666 return ReduceTypedArrayIteratorNext(receiver_map, node,
667 IterationKind::kKeys);
668
669 case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
670 return ReduceFastArrayIteratorNext(receiver_map, node,
671 IterationKind::kKeys);
672
673 case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
674 case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
675 case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
676 case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
677 case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
678 case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
679 case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
680 case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
681 case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
682 return ReduceTypedArrayIteratorNext(receiver_map, node,
683 IterationKind::kEntries);
684
685 case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
686 case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
687 case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
688 case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
689 case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
690 case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
691 return ReduceFastArrayIteratorNext(receiver_map, node,
692 IterationKind::kEntries);
693
694 case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
695 case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
696 case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
697 case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
698 case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
699 case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
700 case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
701 case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
702 case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
703 return ReduceTypedArrayIteratorNext(receiver_map, node,
704 IterationKind::kValues);
705
706 case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
707 case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
708 case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
709 case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
710 case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
711 case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
712 return ReduceFastArrayIteratorNext(receiver_map, node,
713 IterationKind::kValues);
714
715 default:
716 // Slow array iterators are not reduced
717 return NoChange();
718 }
719 }
720 return NoChange();
721 }
722
180 // ES6 section 22.1.3.17 Array.prototype.pop ( ) 723 // ES6 section 22.1.3.17 Array.prototype.pop ( )
181 Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) { 724 Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) {
182 Handle<Map> receiver_map; 725 Handle<Map> receiver_map;
183 Node* receiver = NodeProperties::GetValueInput(node, 1); 726 Node* receiver = NodeProperties::GetValueInput(node, 1);
184 Node* effect = NodeProperties::GetEffectInput(node); 727 Node* effect = NodeProperties::GetEffectInput(node);
185 Node* control = NodeProperties::GetControlInput(node); 728 Node* control = NodeProperties::GetControlInput(node);
186 // TODO(turbofan): Extend this to also handle fast (holey) double elements 729 // TODO(turbofan): Extend this to also handle fast (holey) double elements
187 // once we got the hole NaN mess sorted out in TurboFan/V8. 730 // once we got the hole NaN mess sorted out in TurboFan/V8.
188 if (GetMapWitness(node).ToHandle(&receiver_map) && 731 if (GetMapWitness(node).ToHandle(&receiver_map) &&
189 CanInlineArrayResizeOperation(receiver_map) && 732 CanInlineArrayResizeOperation(receiver_map) &&
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 return NoChange(); 1796 return NoChange();
1254 } 1797 }
1255 1798
1256 Reduction JSBuiltinReducer::Reduce(Node* node) { 1799 Reduction JSBuiltinReducer::Reduce(Node* node) {
1257 Reduction reduction = NoChange(); 1800 Reduction reduction = NoChange();
1258 JSCallReduction r(node); 1801 JSCallReduction r(node);
1259 1802
1260 // Dispatch according to the BuiltinFunctionId if present. 1803 // Dispatch according to the BuiltinFunctionId if present.
1261 if (!r.HasBuiltinFunctionId()) return NoChange(); 1804 if (!r.HasBuiltinFunctionId()) return NoChange();
1262 switch (r.GetBuiltinFunctionId()) { 1805 switch (r.GetBuiltinFunctionId()) {
1806 case kArrayEntries:
1807 return ReduceArrayIterator(node, IterationKind::kEntries);
1808 case kArrayKeys:
1809 return ReduceArrayIterator(node, IterationKind::kKeys);
1810 case kArrayValues:
1811 return ReduceArrayIterator(node, IterationKind::kValues);
1812 case kArrayIteratorNext:
1813 return ReduceArrayIteratorNext(node);
1263 case kArrayPop: 1814 case kArrayPop:
1264 return ReduceArrayPop(node); 1815 return ReduceArrayPop(node);
1265 case kArrayPush: 1816 case kArrayPush:
1266 return ReduceArrayPush(node); 1817 return ReduceArrayPush(node);
1267 case kDateGetTime: 1818 case kDateGetTime:
1268 return ReduceDateGetTime(node); 1819 return ReduceDateGetTime(node);
1269 case kGlobalIsFinite: 1820 case kGlobalIsFinite:
1270 reduction = ReduceGlobalIsFinite(node); 1821 reduction = ReduceGlobalIsFinite(node);
1271 break; 1822 break;
1272 case kGlobalIsNaN: 1823 case kGlobalIsNaN:
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1409 return ReduceArrayBufferViewAccessor( 1960 return ReduceArrayBufferViewAccessor(
1410 node, JS_TYPED_ARRAY_TYPE, 1961 node, JS_TYPED_ARRAY_TYPE,
1411 AccessBuilder::ForJSArrayBufferViewByteLength()); 1962 AccessBuilder::ForJSArrayBufferViewByteLength());
1412 case kTypedArrayByteOffset: 1963 case kTypedArrayByteOffset:
1413 return ReduceArrayBufferViewAccessor( 1964 return ReduceArrayBufferViewAccessor(
1414 node, JS_TYPED_ARRAY_TYPE, 1965 node, JS_TYPED_ARRAY_TYPE,
1415 AccessBuilder::ForJSArrayBufferViewByteOffset()); 1966 AccessBuilder::ForJSArrayBufferViewByteOffset());
1416 case kTypedArrayLength: 1967 case kTypedArrayLength:
1417 return ReduceArrayBufferViewAccessor( 1968 return ReduceArrayBufferViewAccessor(
1418 node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength()); 1969 node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength());
1970 case kTypedArrayEntries:
1971 return ReduceTypedArrayIterator(node, IterationKind::kEntries);
1972 case kTypedArrayKeys:
1973 return ReduceTypedArrayIterator(node, IterationKind::kKeys);
1974 case kTypedArrayValues:
1975 return ReduceTypedArrayIterator(node, IterationKind::kValues);
1419 default: 1976 default:
1420 break; 1977 break;
1421 } 1978 }
1422 1979
1423 // Replace builtin call assuming replacement nodes are pure values that don't 1980 // Replace builtin call assuming replacement nodes are pure values that don't
1424 // produce an effect. Replaces {node} with {reduction} and relaxes effects. 1981 // produce an effect. Replaces {node} with {reduction} and relaxes effects.
1425 if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement()); 1982 if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement());
1426 1983
1427 return reduction; 1984 return reduction;
1428 } 1985 }
(...skipping 27 matching lines...) Expand all
1456 return jsgraph()->simplified(); 2013 return jsgraph()->simplified();
1457 } 2014 }
1458 2015
1459 JSOperatorBuilder* JSBuiltinReducer::javascript() const { 2016 JSOperatorBuilder* JSBuiltinReducer::javascript() const {
1460 return jsgraph()->javascript(); 2017 return jsgraph()->javascript();
1461 } 2018 }
1462 2019
1463 } // namespace compiler 2020 } // namespace compiler
1464 } // namespace internal 2021 } // namespace internal
1465 } // namespace v8 2022 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698