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

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

Issue 2484003002: [builtins] implement JSBuiltinReducer for ArrayIteratorNext() (Closed)
Patch Set: Remove whitespace change that snuck in 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 if (IsFastElementsKind(receiver_map->elements_kind())) {
200 map_index += static_cast<int>(receiver_map->elements_kind());
201 object_map = jsgraph()->Constant(receiver_map);
202 } else {
203 map_index += (Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX -
204 Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX);
205 }
206 }
207 break;
208 case JS_TYPED_ARRAY_TYPE:
209 if (kind == IterationKind::kKeys) {
210 map_index = Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX;
211 } else {
212 DCHECK_GE(receiver_map->elements_kind(), UINT8_ELEMENTS);
213 DCHECK_LE(receiver_map->elements_kind(), UINT8_CLAMPED_ELEMENTS);
214 map_index =
215 (kind == IterationKind::kValues
216 ? Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX
217 : Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX) +
218 (receiver_map->elements_kind() - UINT8_ELEMENTS);
219 }
220 break;
221 default:
222 if (kind == IterationKind::kKeys) {
223 map_index = Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX;
224 } else if (kind == IterationKind::kValues) {
225 map_index = Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX;
226 } else {
227 map_index = Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
228 }
Benedikt Meurer 2016/11/08 05:29:48 Add a break for the default
229 }
230
231 DCHECK_GE(map_index, Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX);
232 DCHECK_LE(map_index, Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX);
233
234 Handle<Map> map(Map::cast(native_context()->get(map_index)), isolate());
235
236 // allocate new iterator
237 effect = graph()->NewNode(
238 common()->BeginRegion(RegionObservability::kNotObservable), effect);
239 Node* value = effect = graph()->NewNode(
240 simplified()->Allocate(NOT_TENURED),
241 jsgraph()->Constant(JSArrayIterator::kSize), effect, control);
242 effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()),
243 value, jsgraph()->Constant(map), effect, control);
244 effect = graph()->NewNode(
245 simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value,
246 jsgraph()->EmptyFixedArrayConstant(), effect, control);
247 effect = graph()->NewNode(
248 simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value,
249 jsgraph()->EmptyFixedArrayConstant(), effect, control);
250
251 // attach the iterator to this object
252 effect = graph()->NewNode(
253 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
254 value, receiver, effect, control);
255 effect = graph()->NewNode(
256 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex()),
257 value, jsgraph()->SmiConstant(0), effect, control);
Benedikt Meurer 2016/11/08 05:29:49 Nit: use jsgraph()->ZeroConstant() here.
258 effect = graph()->NewNode(
259 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObjectMap()),
260 value, object_map, effect, control);
261
262 value = effect = graph()->NewNode(common()->FinishRegion(), value, effect);
263
264 // replace it
265 ReplaceWithValue(node, value, effect, control);
266 return Replace(value);
267 }
268 return NoChange();
269 }
270
271 Reduction JSBuiltinReducer::ReduceFastArrayIteratorNext(
272 Handle<Map> iterator_map, Node* node, IterationKind kind) {
273 Node* iterator = NodeProperties::GetValueInput(node, 1);
274 Node* effect = NodeProperties::GetEffectInput(node);
275 Node* control = NodeProperties::GetControlInput(node);
276 Node* context = NodeProperties::GetContextInput(node);
277
278 if (kind != IterationKind::kKeys && !isolate()->CanInlineArrayIterator()) {
279 // Avoid deopt loops for non-key iteration if the array_iterator_protector
280 // cell has been invalidated.
281 return NoChange();
282 }
283
284 ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
285 iterator_map->instance_type());
286
287 Node* array = effect = graph()->NewNode(
288 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
Benedikt Meurer 2016/11/08 05:29:48 Move this after the condition below, otherwise you
289 iterator, effect, control);
290
291 Handle<Map> array_map;
292 if (IsFastHoleyElementsKind(elements_kind)) {
293 if (!GetMapWitness(array).ToHandle(&array_map)) {
Benedikt Meurer 2016/11/08 05:29:48 This won't work in general, as there's no guarante
caitp 2016/11/08 06:27:59 Okay, I've updated this to set up a generic iterat
294 // Don't inline if there may be elements on the prototype chain.
295 return NoChange();
296 }
297 }
298
299 Node* check0 = effect = graph()->NewNode(
300 javascript()->StrictEqual(CompareOperationHint::kNone), array,
Benedikt Meurer 2016/11/08 05:29:48 Use simplified()->ReferenceEqual() instead of Stri
301 jsgraph()->UndefinedConstant(), context, effect, control);
302 Node* branch0 =
303 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
304
305 Node* vdone_false0;
306 Node* vfalse0;
307 Node* efalse0 = effect;
308 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
309 {
310 // iterator.[[IteratedObject]] !== undefined, continue iterating.
311 Node* index = efalse0 = graph()->NewNode(
312 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
313 JS_ARRAY_TYPE, elements_kind)),
314 iterator, efalse0, if_false0);
315
316 Node* length = efalse0 = graph()->NewNode(
317 simplified()->LoadField(AccessBuilder::ForJSArrayLength(elements_kind)),
318 array, efalse0, if_false0);
319 Node* check1 =
320 graph()->NewNode(simplified()->NumberLessThan(), index, length);
321 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
322 check1, if_false0);
323
324 Node* vdone_true1;
325 Node* vtrue1;
326 Node* etrue1 = efalse0;
327 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
328 {
329 // iterator.[[NextIndex]] < array.length, continue iterating
330 vdone_true1 = jsgraph()->FalseConstant();
331 if (kind == IterationKind::kKeys) {
332 vtrue1 = index;
333 } else {
334 // For value/entry iteration, first step is a mapcheck to ensure
335 // inlining is still valid.
336 Node* orig_map = etrue1 =
337 graph()->NewNode(simplified()->LoadField(
338 AccessBuilder::ForJSArrayIteratorObjectMap()),
339 iterator, effect, control);
Benedikt Meurer 2016/11/08 05:29:49 s/effect/etrue1
340 etrue1 = graph()->NewNode(simplified()->CheckMaps(1), array, orig_map,
341 effect, control);
Benedikt Meurer 2016/11/08 05:29:48 s/effect/etrue1/
342 }
343
344 Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
Benedikt Meurer 2016/11/08 05:29:49 You need to truncate the next_index via NumberToUi
345 jsgraph()->OneConstant());
346 etrue1 = graph()->NewNode(
347 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
348 JS_ARRAY_TYPE, elements_kind)),
349 iterator, next_index, etrue1, if_true1);
350
351 if (kind != IterationKind::kKeys) {
352 Node* elements = etrue1 = graph()->NewNode(
353 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
354 array, etrue1, if_true1);
355 Node* value = etrue1 = graph()->NewNode(
356 simplified()->LoadElement(
357 AccessBuilder::ForFixedArrayElement(elements_kind)),
358 elements, index, etrue1, if_true1);
359
360 // Handle loading from holey backing stores correctly, by either mapping
361 // the hole to undefined if possible, or deoptimizing otherwise.
Benedikt Meurer 2016/11/08 05:29:48 You cannot deoptimize for hole here, as that'll be
362 if (elements_kind == FAST_HOLEY_ELEMENTS ||
363 elements_kind == FAST_HOLEY_SMI_ELEMENTS) {
364 // Check if we are allowed to turn the hole into undefined.
365 DCHECK(!array_map.is_null());
366 if (CanTreatHoleAsUndefined(array_map)) {
367 // Turn the hole into undefined.
368 value = graph()->NewNode(
369 simplified()->ConvertTaggedHoleToUndefined(), value);
370 } else {
371 // Bailout if we see the hole.
372 value = etrue1 = graph()->NewNode(simplified()->CheckTaggedHole(),
373 value, etrue1, if_true1);
374 }
375 } else if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) {
376 // Perform the hole check on the result.
377 DCHECK(!array_map.is_null());
378 CheckFloat64HoleMode mode = CheckFloat64HoleMode::kNeverReturnHole;
379 // Check if we are allowed to return the hole directly.
380 if (CanTreatHoleAsUndefined(array_map)) {
Benedikt Meurer 2016/11/08 05:29:49 Same as above.
381 // Return the signaling NaN hole directly if all uses are
382 // truncating.
383 mode = CheckFloat64HoleMode::kAllowReturnHole;
384 }
385 value = etrue1 = graph()->NewNode(
386 simplified()->CheckFloat64Hole(mode), value, etrue1, if_true1);
387 }
388
389 if (kind == IterationKind::kEntries) {
390 // Allocate elements for key/value pair
391 etrue1 = graph()->NewNode(
392 common()->BeginRegion(RegionObservability::kNotObservable),
393 etrue1);
394 Node* elements = etrue1 = graph()->NewNode(
395 simplified()->Allocate(NOT_TENURED),
396 jsgraph()->Constant(FixedArray::SizeFor(2)), etrue1, if_true1);
397 etrue1 = graph()->NewNode(
398 simplified()->StoreField(AccessBuilder::ForMap()), elements,
399 jsgraph()->Constant(isolate()->factory()->fixed_array_map()),
400 etrue1, if_true1);
401 etrue1 = graph()->NewNode(
402 simplified()->StoreField(AccessBuilder::ForFixedArrayLength()),
403 elements, jsgraph()->Constant(2));
404 etrue1 = graph()->NewNode(
405 simplified()->StoreElement(
406 AccessBuilder::ForFixedArrayElement(FAST_ELEMENTS)),
407 elements, jsgraph()->Constant(0), index, etrue1, if_true1);
408 etrue1 = graph()->NewNode(
409 simplified()->StoreElement(
410 AccessBuilder::ForFixedArrayElement(FAST_ELEMENTS)),
411 elements, jsgraph()->Constant(1), value, etrue1, if_true1);
412 elements = etrue1 =
413 graph()->NewNode(common()->FinishRegion(), elements, etrue1);
414
415 // Allocate JSArray for key/value pair
416 etrue1 = graph()->NewNode(
417 common()->BeginRegion(RegionObservability::kNotObservable),
418 etrue1);
419 Node* entry = etrue1 = graph()->NewNode(
420 simplified()->Allocate(NOT_TENURED),
421 jsgraph()->Constant(JSArray::kSize), etrue1, if_true1);
422 etrue1 = graph()->NewNode(
423 simplified()->StoreField(AccessBuilder::ForMap()), entry,
424 jsgraph()->Constant(
425 handle(native_context()->js_array_fast_elements_map_index())),
426 etrue1, if_true1);
427 etrue1 = graph()->NewNode(
428 simplified()->StoreField(AccessBuilder::ForJSObjectProperties()),
429 entry, jsgraph()->EmptyFixedArrayConstant(), etrue1, if_true1);
430 etrue1 = graph()->NewNode(
431 simplified()->StoreField(AccessBuilder::ForJSObjectElements()),
432 entry, elements, etrue1, if_true1);
433 etrue1 = graph()->NewNode(
434 simplified()->StoreField(
435 AccessBuilder::ForJSArrayLength(elements_kind)),
436 entry, jsgraph()->Constant(2), etrue1, if_true1);
437 entry = etrue1 =
438 graph()->NewNode(common()->FinishRegion(), entry, etrue1);
439 vtrue1 = entry;
440 } else {
441 DCHECK(kind == IterationKind::kValues);
442 vtrue1 = value;
443 }
444 }
445 }
446
447 Node* vdone_false1;
448 Node* vfalse1;
449 Node* efalse1 = efalse0;
450 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
451 {
452 // iterator.[[NextIndex]] >= array.length, stop iterating.
453 vdone_false1 = jsgraph()->TrueConstant();
454 vfalse1 = jsgraph()->UndefinedConstant();
455 efalse1 = graph()->NewNode(
456 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
457 iterator, vfalse1, efalse1, if_false1);
458 }
459
460 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
461 efalse0 =
462 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_false0);
463 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
464 vtrue1, vfalse1, if_false0);
465 vdone_false0 =
466 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
467 vdone_true1, vdone_false1, if_false0);
468 }
469
470 Node* vdone_true0;
471 Node* vtrue0;
472 Node* etrue0 = effect;
473 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
474 {
475 // iterator.[[IteratedObject]] === undefined, the iterator is done.
476 vdone_true0 = jsgraph()->TrueConstant();
477 vtrue0 = jsgraph()->UndefinedConstant();
478 }
479
480 control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
481 effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
482 Node* value =
483 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
484 vfalse0, vtrue0, control);
485 Node* done =
486 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
487 vdone_false0, vdone_true0, control);
488
489 // Create IteratorResult object.
490 value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
491 value, done, context, effect);
492 ReplaceWithValue(node, value, effect, control);
493 return Replace(value);
494 }
495
496 Reduction JSBuiltinReducer::ReduceTypedArrayIteratorNext(
497 Handle<Map> iterator_map, Node* node, IterationKind kind) {
498 Node* iterator = NodeProperties::GetValueInput(node, 1);
499 Node* effect = NodeProperties::GetEffectInput(node);
500 Node* control = NodeProperties::GetControlInput(node);
501 Node* context = NodeProperties::GetContextInput(node);
502
503 ElementsKind elements_kind = JSArrayIterator::ElementsKindForInstanceType(
504 iterator_map->instance_type());
505
506 Node* array = effect = graph()->NewNode(
507 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorObject()),
508 iterator, effect, control);
509 Node* check0 = effect = graph()->NewNode(
510 javascript()->StrictEqual(CompareOperationHint::kNone), array,
511 jsgraph()->UndefinedConstant(), context, effect, control);
512 Node* branch0 =
513 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
514
515 Node* vdone_false0;
516 Node* vfalse0;
517 Node* efalse0 = effect;
518 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
519 {
520 // iterator.[[IteratedObject]] !== undefined, continue iterating.
521 Node* index = efalse0 = graph()->NewNode(
522 simplified()->LoadField(AccessBuilder::ForJSArrayIteratorIndex(
523 JS_TYPED_ARRAY_TYPE, elements_kind)),
524 iterator, efalse0, if_false0);
525
526 // typedarray.[[ViewedArrayBuffer]]
527 Node* buffer = efalse0 = graph()->NewNode(
528 simplified()->LoadField(AccessBuilder::ForJSArrayBufferViewBuffer()),
529 array, efalse0, if_false0);
530
531 Node* check1 = efalse0 = graph()->NewNode(
532 simplified()->ArrayBufferWasNeutered(), buffer, efalse0, if_false0);
533 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
534 check1, if_false0);
535
536 Node* vfalse1;
537 Node* efalse1 = efalse0;
538 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
539 {
540 vfalse1 = efalse1 = graph()->NewNode(
541 simplified()->LoadField(AccessBuilder::ForJSTypedArrayLength()),
542 array, efalse1, if_false1);
543 }
544
545 Node* vtrue1;
546 Node* etrue1 = efalse0;
547 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
548 {
549 // TODO(caitp): If IsDetached(buffer) is true, throw a TypeError, per
550 // https://github.com/tc39/ecma262/issues/713
551 vtrue1 = jsgraph()->Constant(0);
552 }
553
554 if_false0 = graph()->NewNode(common()->Merge(2), if_false1, if_true1);
555 efalse0 =
556 graph()->NewNode(common()->EffectPhi(2), efalse1, etrue1, if_false0);
557 Node* length =
558 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
559 vfalse1, vtrue1, if_false0);
560
561 Node* check2 =
562 graph()->NewNode(simplified()->NumberLessThan(), index, length);
563 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue),
564 check2, if_false0);
565
566 Node* vdone_true2;
567 Node* vtrue2;
568 Node* etrue2 = efalse0;
569 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
570 {
571 // iterator.[[NextIndex]] < array.length, continue iterating
572 vdone_true2 = jsgraph()->FalseConstant();
573 if (kind == IterationKind::kKeys) {
574 vtrue2 = index;
575 }
576
577 Node* next_index = graph()->NewNode(simplified()->NumberAdd(), index,
578 jsgraph()->OneConstant());
579 etrue2 = graph()->NewNode(
580 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorIndex(
581 JS_TYPED_ARRAY_TYPE, elements_kind)),
582 iterator, next_index, etrue2, if_true2);
583
584 if (kind != IterationKind::kKeys) {
585 Node* elements = etrue2 = graph()->NewNode(
586 simplified()->LoadField(AccessBuilder::ForJSObjectElements()),
587 array, etrue2, if_true2);
588 Node* base_ptr = etrue2 = graph()->NewNode(
589 simplified()->LoadField(
590 AccessBuilder::ForFixedTypedArrayBaseBasePointer()),
591 elements, etrue2, if_true2);
592 Node* external_ptr = etrue2 = graph()->NewNode(
593 simplified()->LoadField(
594 AccessBuilder::ForFixedTypedArrayBaseExternalPointer()),
595 elements, etrue2, if_true2);
596
597 ExternalArrayType array_type = kExternalInt8Array;
598 switch (elements_kind) {
599 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
600 case TYPE##_ELEMENTS: \
601 array_type = kExternal##Type##Array;
602 TYPED_ARRAYS(TYPED_ARRAY_CASE)
603 default:
604 UNREACHABLE();
605 #undef TYPED_ARRAY_CASE
606 }
607
608 Node* value = etrue2 =
609 graph()->NewNode(simplified()->LoadTypedElement(array_type), buffer,
610 base_ptr, external_ptr, index, etrue2, if_true2);
611
612 if (kind == IterationKind::kEntries) {
613 // Allocate elements for key/value pair
614 etrue2 = graph()->NewNode(
615 common()->BeginRegion(RegionObservability::kNotObservable),
616 etrue2);
617 Node* elements = etrue2 = graph()->NewNode(
618 simplified()->Allocate(NOT_TENURED),
619 jsgraph()->Constant(FixedArray::SizeFor(2)), etrue2, if_true2);
620 etrue2 = graph()->NewNode(
621 simplified()->StoreField(AccessBuilder::ForMap()), elements,
622 jsgraph()->Constant(isolate()->factory()->fixed_array_map()),
623 etrue1, if_true2);
624 etrue2 = graph()->NewNode(
625 simplified()->StoreField(AccessBuilder::ForFixedArrayLength()),
626 elements, jsgraph()->Constant(2));
627 etrue2 = graph()->NewNode(
628 simplified()->StoreElement(
629 AccessBuilder::ForFixedArrayElement(FAST_ELEMENTS)),
630 elements, jsgraph()->Constant(0), index, etrue2, if_true2);
631 etrue2 = graph()->NewNode(
632 simplified()->StoreElement(
633 AccessBuilder::ForFixedArrayElement(FAST_ELEMENTS)),
634 elements, jsgraph()->Constant(1), value, etrue2, if_true2);
635 elements = etrue2 =
636 graph()->NewNode(common()->FinishRegion(), elements, etrue2);
637
638 // Allocate JSArray for key/value pair
639 etrue2 = graph()->NewNode(
640 common()->BeginRegion(RegionObservability::kNotObservable),
641 etrue2);
642 Node* entry = etrue2 = graph()->NewNode(
643 simplified()->Allocate(NOT_TENURED),
644 jsgraph()->Constant(JSArray::kSize), etrue2, if_true2);
645 etrue2 = graph()->NewNode(
646 simplified()->StoreField(AccessBuilder::ForMap()), entry,
647 jsgraph()->Constant(
648 handle(native_context()->js_array_fast_elements_map_index())),
649 etrue2, if_true2);
650 etrue2 = graph()->NewNode(
651 simplified()->StoreField(AccessBuilder::ForJSObjectProperties()),
652 entry, jsgraph()->EmptyFixedArrayConstant(), etrue2, if_true2);
653 etrue2 = graph()->NewNode(
654 simplified()->StoreField(AccessBuilder::ForJSObjectElements()),
655 entry, elements, etrue2, if_true2);
656 etrue2 = graph()->NewNode(
657 simplified()->StoreField(
658 AccessBuilder::ForJSArrayLength(elements_kind)),
659 entry, jsgraph()->Constant(2), etrue2, if_true2);
660 entry = etrue1 =
661 graph()->NewNode(common()->FinishRegion(), entry, etrue2);
662 vtrue2 = entry;
663 } else {
664 DCHECK(kind == IterationKind::kValues);
665 vtrue2 = value;
666 }
667 }
668 }
669
670 Node* vdone_false2;
671 Node* vfalse2;
672 Node* efalse2 = efalse0;
673 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
674 {
675 // iterator.[[NextIndex]] >= array.length, stop iterating.
676 vdone_false2 = jsgraph()->TrueConstant();
677 vfalse2 = jsgraph()->UndefinedConstant();
678 efalse2 = graph()->NewNode(
679 simplified()->StoreField(AccessBuilder::ForJSArrayIteratorObject()),
680 iterator, vfalse2, efalse2, if_false2);
681 }
682
683 if_false0 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
684 efalse0 =
685 graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, if_false0);
686 vfalse0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
687 vtrue2, vfalse2, if_false0);
688 vdone_false0 =
689 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
690 vdone_true2, vdone_false2, if_false0);
691 }
692
693 Node* vdone_true0;
694 Node* vtrue0;
695 Node* etrue0 = effect;
696 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
697 {
698 // iterator.[[IteratedObject]] === undefined, the iterator is done.
699 vdone_true0 = jsgraph()->TrueConstant();
700 vtrue0 = jsgraph()->UndefinedConstant();
701 }
702
703 control = graph()->NewNode(common()->Merge(2), if_false0, if_true0);
704 effect = graph()->NewNode(common()->EffectPhi(2), efalse0, etrue0, control);
705 Node* value =
706 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
707 vfalse0, vtrue0, control);
708 Node* done =
709 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
710 vdone_false0, vdone_true0, control);
711
712 // Create IteratorResult object.
713 value = effect = graph()->NewNode(javascript()->CreateIterResultObject(),
714 value, done, context, effect);
715 ReplaceWithValue(node, value, effect, control);
716 return Replace(value);
717 }
718
719 Reduction JSBuiltinReducer::ReduceArrayIteratorNext(Node* node) {
720 Handle<Map> receiver_map;
721 if (GetMapWitness(node).ToHandle(&receiver_map)) {
722 switch (receiver_map->instance_type()) {
723 case JS_TYPED_ARRAY_KEY_ITERATOR_TYPE:
724 return ReduceTypedArrayIteratorNext(receiver_map, node,
725 IterationKind::kKeys);
726
727 case JS_FAST_ARRAY_KEY_ITERATOR_TYPE:
728 return ReduceFastArrayIteratorNext(receiver_map, node,
729 IterationKind::kKeys);
730
731 case JS_INT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
732 case JS_UINT8_ARRAY_KEY_VALUE_ITERATOR_TYPE:
733 case JS_INT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
734 case JS_UINT16_ARRAY_KEY_VALUE_ITERATOR_TYPE:
735 case JS_INT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
736 case JS_UINT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
737 case JS_FLOAT32_ARRAY_KEY_VALUE_ITERATOR_TYPE:
738 case JS_FLOAT64_ARRAY_KEY_VALUE_ITERATOR_TYPE:
739 case JS_UINT8_CLAMPED_ARRAY_KEY_VALUE_ITERATOR_TYPE:
740 return ReduceTypedArrayIteratorNext(receiver_map, node,
741 IterationKind::kEntries);
742
743 case JS_FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
744 case JS_FAST_HOLEY_SMI_ARRAY_KEY_VALUE_ITERATOR_TYPE:
745 case JS_FAST_ARRAY_KEY_VALUE_ITERATOR_TYPE:
746 case JS_FAST_HOLEY_ARRAY_KEY_VALUE_ITERATOR_TYPE:
747 case JS_FAST_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
748 case JS_FAST_HOLEY_DOUBLE_ARRAY_KEY_VALUE_ITERATOR_TYPE:
749 return ReduceFastArrayIteratorNext(receiver_map, node,
750 IterationKind::kEntries);
751
752 case JS_INT8_ARRAY_VALUE_ITERATOR_TYPE:
753 case JS_UINT8_ARRAY_VALUE_ITERATOR_TYPE:
754 case JS_INT16_ARRAY_VALUE_ITERATOR_TYPE:
755 case JS_UINT16_ARRAY_VALUE_ITERATOR_TYPE:
756 case JS_INT32_ARRAY_VALUE_ITERATOR_TYPE:
757 case JS_UINT32_ARRAY_VALUE_ITERATOR_TYPE:
758 case JS_FLOAT32_ARRAY_VALUE_ITERATOR_TYPE:
759 case JS_FLOAT64_ARRAY_VALUE_ITERATOR_TYPE:
760 case JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE:
761 return ReduceTypedArrayIteratorNext(receiver_map, node,
762 IterationKind::kValues);
763
764 case JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE:
765 case JS_FAST_HOLEY_SMI_ARRAY_VALUE_ITERATOR_TYPE:
766 case JS_FAST_ARRAY_VALUE_ITERATOR_TYPE:
767 case JS_FAST_HOLEY_ARRAY_VALUE_ITERATOR_TYPE:
768 case JS_FAST_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
769 case JS_FAST_HOLEY_DOUBLE_ARRAY_VALUE_ITERATOR_TYPE:
770 return ReduceFastArrayIteratorNext(receiver_map, node,
771 IterationKind::kValues);
772
773 default:
774 // Slow array iterators are not reduced
775 return NoChange();
776 }
777 }
778 return NoChange();
779 }
780
180 // ES6 section 22.1.3.17 Array.prototype.pop ( ) 781 // ES6 section 22.1.3.17 Array.prototype.pop ( )
181 Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) { 782 Reduction JSBuiltinReducer::ReduceArrayPop(Node* node) {
182 Handle<Map> receiver_map; 783 Handle<Map> receiver_map;
183 Node* receiver = NodeProperties::GetValueInput(node, 1); 784 Node* receiver = NodeProperties::GetValueInput(node, 1);
184 Node* effect = NodeProperties::GetEffectInput(node); 785 Node* effect = NodeProperties::GetEffectInput(node);
185 Node* control = NodeProperties::GetControlInput(node); 786 Node* control = NodeProperties::GetControlInput(node);
186 // TODO(turbofan): Extend this to also handle fast (holey) double elements 787 // TODO(turbofan): Extend this to also handle fast (holey) double elements
187 // once we got the hole NaN mess sorted out in TurboFan/V8. 788 // once we got the hole NaN mess sorted out in TurboFan/V8.
188 if (GetMapWitness(node).ToHandle(&receiver_map) && 789 if (GetMapWitness(node).ToHandle(&receiver_map) &&
189 CanInlineArrayResizeOperation(receiver_map) && 790 CanInlineArrayResizeOperation(receiver_map) &&
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 return NoChange(); 1854 return NoChange();
1254 } 1855 }
1255 1856
1256 Reduction JSBuiltinReducer::Reduce(Node* node) { 1857 Reduction JSBuiltinReducer::Reduce(Node* node) {
1257 Reduction reduction = NoChange(); 1858 Reduction reduction = NoChange();
1258 JSCallReduction r(node); 1859 JSCallReduction r(node);
1259 1860
1260 // Dispatch according to the BuiltinFunctionId if present. 1861 // Dispatch according to the BuiltinFunctionId if present.
1261 if (!r.HasBuiltinFunctionId()) return NoChange(); 1862 if (!r.HasBuiltinFunctionId()) return NoChange();
1262 switch (r.GetBuiltinFunctionId()) { 1863 switch (r.GetBuiltinFunctionId()) {
1864 case kArrayEntries:
1865 return ReduceArrayIterator(node, IterationKind::kEntries);
1866 case kArrayKeys:
1867 return ReduceArrayIterator(node, IterationKind::kKeys);
1868 case kArrayValues:
1869 return ReduceArrayIterator(node, IterationKind::kValues);
1870 case kArrayIteratorNext:
1871 return ReduceArrayIteratorNext(node);
1263 case kArrayPop: 1872 case kArrayPop:
1264 return ReduceArrayPop(node); 1873 return ReduceArrayPop(node);
1265 case kArrayPush: 1874 case kArrayPush:
1266 return ReduceArrayPush(node); 1875 return ReduceArrayPush(node);
1267 case kDateGetTime: 1876 case kDateGetTime:
1268 return ReduceDateGetTime(node); 1877 return ReduceDateGetTime(node);
1269 case kGlobalIsFinite: 1878 case kGlobalIsFinite:
1270 reduction = ReduceGlobalIsFinite(node); 1879 reduction = ReduceGlobalIsFinite(node);
1271 break; 1880 break;
1272 case kGlobalIsNaN: 1881 case kGlobalIsNaN:
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1433 return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), input); 2042 return graph()->NewNode(simplified()->PlainPrimitiveToNumber(), input);
1434 } 2043 }
1435 2044
1436 Node* JSBuiltinReducer::ToUint32(Node* input) { 2045 Node* JSBuiltinReducer::ToUint32(Node* input) {
1437 input = ToNumber(input); 2046 input = ToNumber(input);
1438 Type* input_type = NodeProperties::GetType(input); 2047 Type* input_type = NodeProperties::GetType(input);
1439 if (input_type->Is(Type::Unsigned32())) return input; 2048 if (input_type->Is(Type::Unsigned32())) return input;
1440 return graph()->NewNode(simplified()->NumberToUint32(), input); 2049 return graph()->NewNode(simplified()->NumberToUint32(), input);
1441 } 2050 }
1442 2051
2052 bool JSBuiltinReducer::CanTreatHoleAsUndefined(Handle<Map> receiver_map) {
2053 std::vector<Handle<Map>> receiver_maps = {receiver_map};
2054 return CanTreatHoleAsUndefined(receiver_maps);
2055 }
2056
2057 bool JSBuiltinReducer::CanTreatHoleAsUndefined(
2058 std::vector<Handle<Map>> const& receiver_maps) {
2059 // Check if the array prototype chain is intact.
2060 if (!isolate()->IsFastArrayConstructorPrototypeChainIntact()) return false;
2061
2062 // Make sure both the initial Array and Object prototypes are stable.
2063 Handle<JSObject> initial_array_prototype(
2064 native_context()->initial_array_prototype(), isolate());
2065 Handle<JSObject> initial_object_prototype(
2066 native_context()->initial_object_prototype(), isolate());
2067 if (!initial_array_prototype->map()->is_stable() ||
2068 !initial_object_prototype->map()->is_stable()) {
2069 return false;
2070 }
2071
2072 // Check if all {receiver_maps} either have the initial Array.prototype
2073 // or the initial Object.prototype as their prototype, as those are
2074 // guarded by the array protector cell.
2075 for (Handle<Map> map : receiver_maps) {
2076 if (map->prototype() != *initial_array_prototype &&
2077 map->prototype() != *initial_object_prototype) {
2078 return false;
2079 }
2080 }
2081
2082 // Install code dependencies on the prototype maps.
2083 for (Handle<Map> map : receiver_maps) {
2084 dependencies()->AssumePrototypeMapsStable(map, initial_object_prototype);
2085 }
2086
2087 // Install code dependency on the array protector cell.
2088 dependencies()->AssumePropertyCell(factory()->array_protector());
2089 return true;
2090 }
2091
1443 Graph* JSBuiltinReducer::graph() const { return jsgraph()->graph(); } 2092 Graph* JSBuiltinReducer::graph() const { return jsgraph()->graph(); }
1444 2093
1445 Factory* JSBuiltinReducer::factory() const { return isolate()->factory(); } 2094 Factory* JSBuiltinReducer::factory() const { return isolate()->factory(); }
1446 2095
1447 Isolate* JSBuiltinReducer::isolate() const { return jsgraph()->isolate(); } 2096 Isolate* JSBuiltinReducer::isolate() const { return jsgraph()->isolate(); }
1448 2097
1449 2098
1450 CommonOperatorBuilder* JSBuiltinReducer::common() const { 2099 CommonOperatorBuilder* JSBuiltinReducer::common() const {
1451 return jsgraph()->common(); 2100 return jsgraph()->common();
1452 } 2101 }
1453 2102
1454 2103
1455 SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const { 2104 SimplifiedOperatorBuilder* JSBuiltinReducer::simplified() const {
1456 return jsgraph()->simplified(); 2105 return jsgraph()->simplified();
1457 } 2106 }
1458 2107
1459 JSOperatorBuilder* JSBuiltinReducer::javascript() const { 2108 JSOperatorBuilder* JSBuiltinReducer::javascript() const {
1460 return jsgraph()->javascript(); 2109 return jsgraph()->javascript();
1461 } 2110 }
1462 2111
1463 } // namespace compiler 2112 } // namespace compiler
1464 } // namespace internal 2113 } // namespace internal
1465 } // namespace v8 2114 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698