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

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

Issue 2484003002: [builtins] implement JSBuiltinReducer for ArrayIteratorNext() (Closed)
Patch Set: fix tests when ignition is used 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
« no previous file with comments | « src/compiler/js-builtin-reducer.h ('k') | src/compiler/js-create-lowering.h » ('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 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 &&
348 !isolate()->IsFastArrayIterationIntact()) {
349 // Avoid deopt loops for non-key iteration if the
350 // fast_array_iteration_protector cell has been invalidated.
351 return NoChange();
352 }
353
354 ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
355 iterator_map->instance_type());
356
357 if (IsFastHoleyElementsKind(elements_kind)) {
358 if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
359 return NoChange();
360 } else {
361 Handle<JSObject> initial_array_prototype(
362 native_context()->initial_array_prototype(), isolate());
363 dependencies()->AssumePropertyCell(factory()->array_protector());
364 }
365 }
366
367 Node* array = effect = graph()->NewNode(
368 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
369 iterator, effect, control);
370 Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), array,
371 jsgraph()->UndefinedConstant());
372 Node* branch0 =
373 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
374
375 Node* vdone_false0;
376 Node* vfalse0;
377 Node* efalse0 = effect;
378 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
379 {
380 // iterator.[[IteratedObject]] !== undefined, continue iterating.
381 Node* index = efalse0 = graph()->NewNode(
382 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
383 JS_ARRAY_TYPE, elements_kind)),
384 iterator, efalse0, if_false0);
385
386 Node* length = efalse0 = graph()->NewNode(
387 simplified()->LoadField(AccessBuilder::ForJSArrayLength(elements_kind)),
388 array, efalse0, if_false0);
389 Node* check1 =
390 graph()->NewNode(simplified()->NumberLessThan(), index, length);
391 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
392 check1, if_false0);
393
394 Node* vdone_true1;
395 Node* vtrue1;
396 Node* etrue1 = efalse0;
397 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
398 {
399 // iterator.[[NextIndex]] < array.length, continue iterating
400 vdone_true1 = jsgraph()->FalseConstant();
401 if (kind == IterationKind::kKeys) {
402 vtrue1 = index;
403 } else {
404 // For value/entry iteration, first step is a mapcheck to ensure
405 // inlining is still valid.
406 Node* orig_map = etrue1 =
407 graph()->NewNode(simplified()->LoadField(
408 AccessBuilder::ForJSArrayIteratorObjectMap()),
409 iterator, etrue1, if_true1);
410 etrue1 = graph()->NewNode(simplified()->CheckMaps(1), array, orig_map,
411 etrue1, if_true1);
412 }
413
414 if (kind != IterationKind::kKeys) {
415 Node* elements = etrue1 = graph()->NewNode(
416 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
417 array, etrue1, if_true1);
418 Node* value = etrue1 = graph()->NewNode(
419 simplified()->LoadElement(
420 AccessBuilder::ForFixedArrayElement(elements_kind)),
421 elements, index, etrue1, if_true1);
422
423 // Convert hole to undefined if needed.
424 if (elements_kind == FAST_HOLEY_ELEMENTS ||
425 elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
426 value = graph()->NewNode(simplified()->ConvertTaggedHoleToUndefined(),
427 value);
428 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
429 // TODO(bmeurer): avoid deopt if not all uses of value are truncated.
430 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kAllowReturnHole;
431 value = etrue1 = graph()->NewNode(
432 simplified()->CheckFloat64Hole(mode), value, etrue1, if_true1);
433 }
434
435 if (kind == IterationKind::kEntries) {
436 // Allocate elements for key/value pair
437 vtrue1 = etrue1 = graph()->NewNode(
438 javascript()->CreateKeyValueArray(), index, value, etrue1);
439 } else {
440 DCHECK_EQ(kind, IterationKind::kValues);
441 vtrue1 = value;
442 }
443 }
444
445 Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
446 jsgraph()->OneConstant());
447 next_index = graph()->NewNode(simplified()->NumberToUint32(), next_index);
448
449 etrue1 = graph()->NewNode(
450 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
451 JS_ARRAY_TYPE, elements_kind)),
452 iterator, next_index, etrue1, if_true1);
453 }
454
455 Node* vdone_false1;
456 Node* vfalse1;
457 Node* efalse1 = efalse0;
458 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
459 {
460 // iterator.[[NextIndex]] >= array.length, stop iterating.
461 vdone_false1 = jsgraph()->TrueConstant();
462 vfalse1 = jsgraph()->UndefinedConstant();
463 efalse1 = graph()->NewNode(
464 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
465 iterator, vfalse1, efalse1, if_false1);
466 }
467
468 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
469 efalse0 =
470 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
471 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
472 vtrue1, vfalse1, if_false0);
473 vdone_false0 =
474 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
475 vdone_true1, vdone_false1, if_false0);
476 }
477
478 Node* vdone_true0;
479 Node* vtrue0;
480 Node* etrue0 = effect;
481 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
482 {
483 // iterator.[[IteratedObject]] === undefined, the iterator is done.
484 vdone_true0 = jsgraph()->TrueConstant();
485 vtrue0 = jsgraph()->UndefinedConstant();
486 }
487
488 control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
489 effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
490 Node* value =
491 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
492 vfalse0, vtrue0, control);
493 Node* done =
494 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
495 vdone_false0, vdone_true0, control);
496
497 // Create IteratorResult object.
498 value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
499 value, done, context, effect);
500 ReplaceWithValue(node, value, effect, control);
501 return Replace(value);
502 }
503
504 Reduction JSBuiltinReducer::ReduceTypedArrayIteratorNext(
505 Handle<Map> iterator_map, Node* node, IterationKind kind) {
506 Node* iterator = NodeProperties::GetValueInput(node, 1);
507 Node* effect = NodeProperties::GetEffectInput(node);
508 Node* control = NodeProperties::GetControlInput(node);
509 Node* context = NodeProperties::GetContextInput(node);
510
511 ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
512 iterator_map->instance_type());
513
514 Node* array = effect = graph()->NewNode(
515 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
516 iterator, effect, control);
517 Node* check0 = graph()->NewNode(simplified()->ReferenceEqual(), array,
518 jsgraph()->UndefinedConstant());
519 Node* branch0 =
520 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
521
522 Node* vdone_false0;
523 Node* vfalse0;
524 Node* efalse0 = effect;
525 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
526 {
527 // iterator.[[IteratedObject]] !== undefined, continue iterating.
528 Node* index = efalse0 = graph()->NewNode(
529 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
530 JS_TYPED_ARRAY_TYPE, elements_kind)),
531 iterator, efalse0, if_false0);
532
533 // typedarray.[[ViewedArrayBuffer]]
534 Node* buffer = efalse0 = graph()->NewNode(
535 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
536 array, efalse0, if_false0);
537
538 Node* check1 = efalse0 = graph()->NewNode(
539 simplified()->ArrayBufferWasNeutered(), buffer, efalse0, if_false0);
540 check1 = graph()->NewNode(simplified()->BooleanNot(), check1);
541 efalse0 =
542 graph()->NewNode(simplified()->CheckIf(), check1, efalse0, if_false0);
543
544 Node* length = efalse0 = graph()->NewNode(
545 simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()), array,
546 efalse0, if_false0);
547
548 Node* check2 =
549 graph()->NewNode(simplified()->NumberLessThan(), index, length);
550 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
551 check2, if_false0);
552
553 Node* vdone_true2;
554 Node* vtrue2;
555 Node* etrue2 = efalse0;
556 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
557 {
558 // iterator.[[NextIndex]] < array.length, continue iterating
559 vdone_true2 = jsgraph()->FalseConstant();
560 if (kind == IterationKind::kKeys) {
561 vtrue2 = index;
562 }
563
564 Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
565 jsgraph()->OneConstant());
566 next_index = graph()->NewNode(simplified()->NumberToUint32(), next_index);
567
568 etrue2 = graph()->NewNode(
569 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
570 JS_TYPED_ARRAY_TYPE, elements_kind)),
571 iterator, next_index, etrue2, if_true2);
572
573 if (kind != IterationKind::kKeys) {
574 Node* elements = etrue2 = graph()->NewNode(
575 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
576 array, etrue2, if_true2);
577 Node* base_ptr = etrue2 = graph()->NewNode(
578 simplified()->LoadField(
579 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
580 elements, etrue2, if_true2);
581 Node* external_ptr = etrue2 = graph()->NewNode(
582 simplified()->LoadField(
583 AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
584 elements, etrue2, if_true2);
585
586 ExternalArrayType array_type = kExternalInt8Array;
587 switch (elements_kind) {
588 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
589 case TYPE##_ELEMENTS: \
590 array_type = kExternal##Type##Array; \
591 break;
592 TYPED_ARRAYS(TYPED_ARRAY_CASE)
593 default:
594 UNREACHABLE();
595 #undef TYPED_ARRAY_CASE
596 }
597
598 Node* value = etrue2 =
599 graph()->NewNode(simplified()->LoadTypedElement(array_type), buffer,
600 base_ptr, external_ptr, index, etrue2, if_true2);
601
602 if (kind == IterationKind::kEntries) {
603 // Allocate elements for key/value pair
604 vtrue2 = etrue2 = graph()->NewNode(
605 javascript()->CreateKeyValueArray(), index, value, etrue2);
606 } else {
607 DCHECK(kind == IterationKind::kValues);
608 vtrue2 = value;
609 }
610 }
611 }
612
613 Node* vdone_false2;
614 Node* vfalse2;
615 Node* efalse2 = efalse0;
616 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
617 {
618 // iterator.[[NextIndex]] >= array.length, stop iterating.
619 vdone_false2 = jsgraph()->TrueConstant();
620 vfalse2 = jsgraph()->UndefinedConstant();
621 efalse2 = graph()->NewNode(
622 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
623 iterator, vfalse2, efalse2, if_false2);
624 }
625
626 if_false0 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
627 efalse0 =
628 graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, if_false0);
629 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
630 vtrue2, vfalse2, if_false0);
631 vdone_false0 =
632 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
633 vdone_true2, vdone_false2, if_false0);
634 }
635
636 Node* vdone_true0;
637 Node* vtrue0;
638 Node* etrue0 = effect;
639 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
640 {
641 // iterator.[[IteratedObject]] === undefined, the iterator is done.
642 vdone_true0 = jsgraph()->TrueConstant();
643 vtrue0 = jsgraph()->UndefinedConstant();
644 }
645
646 control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
647 effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
648 Node* value =
649 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
650 vfalse0, vtrue0, control);
651 Node* done =
652 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
653 vdone_false0, vdone_true0, control);
654
655 // Create IteratorResult object.
656 value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
657 value, done, context, effect);
658 ReplaceWithValue(node, value, effect, control);
659 return Replace(value);
660 }
661
662 Reduction JSBuiltinReducer::ReduceArrayIteratorNext(Node* node) {
663 Handle<Map> receiver_map;
664 if (GetMapWitness(node).ToHandle(&receiver_map)) {
665 switch (receiver_map->instance_type()) {
666 case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
667 return ReduceTypedArrayIteratorNext(receiver_map, node,
668 IterationKind::kKeys);
669
670 case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
671 return ReduceFastArrayIteratorNext(receiver_map, node,
672 IterationKind::kKeys);
673
674 case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
675 case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
676 case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
677 case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
678 case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
679 case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
680 case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
681 case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
682 case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
683 return ReduceTypedArrayIteratorNext(receiver_map, node,
684 IterationKind::kEntries);
685
686 case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
687 case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
688 case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
689 case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
690 case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
691 case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
692 return ReduceFastArrayIteratorNext(receiver_map, node,
693 IterationKind::kEntries);
694
695 case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
696 case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
697 case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
698 case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
699 case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
700 case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
701 case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
702 case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
703 case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
704 return ReduceTypedArrayIteratorNext(receiver_map, node,
705 IterationKind::kValues);
706
707 case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
708 case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
709 case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
710 case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
711 case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
712 case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
713 return ReduceFastArrayIteratorNext(receiver_map, node,
714 IterationKind::kValues);
715
716 default:
717 // Slow array iterators are not reduced
718 return NoChange();
719 }
720 }
721 return NoChange();
722 }
723
180 // ES6 section 22.1.3.17 Array.prototype.pop ( ) 724 // ES6 section 22.1.3.17 Array.prototype.pop ( )
181 Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) { 725 Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) {
182 Handle<Map> receiver_map; 726 Handle<Map> receiver_map;
183 Node* receiver = NodeProperties::GetValueInput(node, 1); 727 Node* receiver = NodeProperties::GetValueInput(node, 1);
184 Node* effect = NodeProperties::GetEffectInput(node); 728 Node* effect = NodeProperties::GetEffectInput(node);
185 Node* control = NodeProperties::GetControlInput(node); 729 Node* control = NodeProperties::GetControlInput(node);
186 // TODO(turbofan): Extend this to also handle fast (holey) double elements 730 // TODO(turbofan): Extend this to also handle fast (holey) double elements
187 // once we got the hole NaN mess sorted out in TurboFan/V8. 731 // once we got the hole NaN mess sorted out in TurboFan/V8.
188 if (GetMapWitness(node).ToHandle(&receiver_map) && 732 if (GetMapWitness(node).ToHandle(&receiver_map) &&
189 CanInlineArrayResizeOperation(receiver_map) && 733 CanInlineArrayResizeOperation(receiver_map) &&
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 return NoChange(); 1797 return NoChange();
1254 } 1798 }
1255 1799
1256 Reduction JSBuiltinReducer::Reduce(Node* node) { 1800 Reduction JSBuiltinReducer::Reduce(Node* node) {
1257 Reduction reduction = NoChange(); 1801 Reduction reduction = NoChange();
1258 JSCallReduction r(node); 1802 JSCallReduction r(node);
1259 1803
1260 // Dispatch according to the BuiltinFunctionId if present. 1804 // Dispatch according to the BuiltinFunctionId if present.
1261 if (!r.HasBuiltinFunctionId()) return NoChange(); 1805 if (!r.HasBuiltinFunctionId()) return NoChange();
1262 switch (r.GetBuiltinFunctionId()) { 1806 switch (r.GetBuiltinFunctionId()) {
1807 case kArrayEntries:
1808 return ReduceArrayIterator(node, IterationKind::kEntries);
1809 case kArrayKeys:
1810 return ReduceArrayIterator(node, IterationKind::kKeys);
1811 case kArrayValues:
1812 return ReduceArrayIterator(node, IterationKind::kValues);
1813 case kArrayIteratorNext:
1814 return ReduceArrayIteratorNext(node);
1263 case kArrayPop: 1815 case kArrayPop:
1264 return ReduceArrayPop(node); 1816 return ReduceArrayPop(node);
1265 case kArrayPush: 1817 case kArrayPush:
1266 return ReduceArrayPush(node); 1818 return ReduceArrayPush(node);
1267 case kDateGetTime: 1819 case kDateGetTime:
1268 return ReduceDateGetTime(node); 1820 return ReduceDateGetTime(node);
1269 case kGlobalIsFinite: 1821 case kGlobalIsFinite:
1270 reduction = ReduceGlobalIsFinite(node); 1822 reduction = ReduceGlobalIsFinite(node);
1271 break; 1823 break;
1272 case kGlobalIsNaN: 1824 case kGlobalIsNaN:
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
1409 return ReduceArrayBufferViewAccessor( 1961 return ReduceArrayBufferViewAccessor(
1410 node, JS_TYPED_ARRAY_TYPE, 1962 node, JS_TYPED_ARRAY_TYPE,
1411 AccessBuilder::ForJSArrayBufferViewByteLength()); 1963 AccessBuilder::ForJSArrayBufferViewByteLength());
1412 case kTypedArrayByteOffset: 1964 case kTypedArrayByteOffset:
1413 return ReduceArrayBufferViewAccessor( 1965 return ReduceArrayBufferViewAccessor(
1414 node, JS_TYPED_ARRAY_TYPE, 1966 node, JS_TYPED_ARRAY_TYPE,
1415 AccessBuilder::ForJSArrayBufferViewByteOffset()); 1967 AccessBuilder::ForJSArrayBufferViewByteOffset());
1416 case kTypedArrayLength: 1968 case kTypedArrayLength:
1417 return ReduceArrayBufferViewAccessor( 1969 return ReduceArrayBufferViewAccessor(
1418 node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength()); 1970 node, JS_TYPED_ARRAY_TYPE, AccessBuilder::ForJSTypedArrayLength());
1971 case kTypedArrayEntries:
1972 return ReduceTypedArrayIterator(node, IterationKind::kEntries);
1973 case kTypedArrayKeys:
1974 return ReduceTypedArrayIterator(node, IterationKind::kKeys);
1975 case kTypedArrayValues:
1976 return ReduceTypedArrayIterator(node, IterationKind::kValues);
1419 default: 1977 default:
1420 break; 1978 break;
1421 } 1979 }
1422 1980
1423 // Replace builtin call assuming replacement nodes are pure values that don't 1981 // Replace builtin call assuming replacement nodes are pure values that don't
1424 // produce an effect. Replaces {node} with {reduction} and relaxes effects. 1982 // produce an effect. Replaces {node} with {reduction} and relaxes effects.
1425 if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement()); 1983 if (reduction.Changed()) ReplaceWithValue(node, reduction.replacement());
1426 1984
1427 return reduction; 1985 return reduction;
1428 } 1986 }
(...skipping 27 matching lines...) Expand all
1456 return jsgraph()->simplified(); 2014 return jsgraph()->simplified();
1457 } 2015 }
1458 2016
1459 JSOperatorBuilder* JSBuiltinReducer::javascript() const { 2017 JSOperatorBuilder* JSBuiltinReducer::javascript() const {
1460 return jsgraph()->javascript(); 2018 return jsgraph()->javascript();
1461 } 2019 }
1462 2020
1463 } // namespace compiler 2021 } // namespace compiler
1464 } // namespace internal 2022 } // namespace internal
1465 } // namespace v8 2023 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-builtin-reducer.h ('k') | src/compiler/js-create-lowering.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698