OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/bailout-reason.h" | 7 #include "src/bailout-reason.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/field-index.h" | 9 #include "src/field-index.h" |
10 #include "src/hydrogen.h" | 10 #include "src/hydrogen.h" |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 template <> | 316 template <> |
317 HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() { | 317 HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() { |
318 Factory* factory = isolate()->factory(); | 318 Factory* factory = isolate()->factory(); |
319 HValue* undefined = graph()->GetConstantUndefined(); | 319 HValue* undefined = graph()->GetConstantUndefined(); |
320 AllocationSiteMode alloc_site_mode = casted_stub()->allocation_site_mode(); | 320 AllocationSiteMode alloc_site_mode = casted_stub()->allocation_site_mode(); |
321 | 321 |
322 // This stub is very performance sensitive, the generated code must be tuned | 322 // This stub is very performance sensitive, the generated code must be tuned |
323 // so that it doesn't build and eager frame. | 323 // so that it doesn't build and eager frame. |
324 info()->MarkMustNotHaveEagerFrame(); | 324 info()->MarkMustNotHaveEagerFrame(); |
325 | 325 |
326 HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0), | 326 HInstruction* allocation_site = |
327 GetParameter(1), | 327 Add<HLoadKeyed>(GetParameter(0), GetParameter(1), nullptr, FAST_ELEMENTS); |
328 static_cast<HValue*>(NULL), | |
329 FAST_ELEMENTS); | |
330 IfBuilder checker(this); | 328 IfBuilder checker(this); |
331 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, | 329 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, |
332 undefined); | 330 undefined); |
333 checker.Then(); | 331 checker.Then(); |
334 | 332 |
335 HObjectAccess access = HObjectAccess::ForAllocationSiteOffset( | 333 HObjectAccess access = HObjectAccess::ForAllocationSiteOffset( |
336 AllocationSite::kTransitionInfoOffset); | 334 AllocationSite::kTransitionInfoOffset); |
337 HInstruction* boilerplate = Add<HLoadNamedField>( | 335 HInstruction* boilerplate = |
338 allocation_site, static_cast<HValue*>(NULL), access); | 336 Add<HLoadNamedField>(allocation_site, nullptr, access); |
339 HValue* elements = AddLoadElements(boilerplate); | 337 HValue* elements = AddLoadElements(boilerplate); |
340 HValue* capacity = AddLoadFixedArrayLength(elements); | 338 HValue* capacity = AddLoadFixedArrayLength(elements); |
341 IfBuilder zero_capacity(this); | 339 IfBuilder zero_capacity(this); |
342 zero_capacity.If<HCompareNumericAndBranch>(capacity, graph()->GetConstant0(), | 340 zero_capacity.If<HCompareNumericAndBranch>(capacity, graph()->GetConstant0(), |
343 Token::EQ); | 341 Token::EQ); |
344 zero_capacity.Then(); | 342 zero_capacity.Then(); |
345 Push(BuildCloneShallowArrayEmpty(boilerplate, | 343 Push(BuildCloneShallowArrayEmpty(boilerplate, |
346 allocation_site, | 344 allocation_site, |
347 alloc_site_mode)); | 345 alloc_site_mode)); |
348 zero_capacity.Else(); | 346 zero_capacity.Else(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 | 378 |
381 Handle<Code> FastCloneShallowArrayStub::GenerateCode() { | 379 Handle<Code> FastCloneShallowArrayStub::GenerateCode() { |
382 return DoGenerateCode(this); | 380 return DoGenerateCode(this); |
383 } | 381 } |
384 | 382 |
385 | 383 |
386 template <> | 384 template <> |
387 HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() { | 385 HValue* CodeStubGraphBuilder<FastCloneShallowObjectStub>::BuildCodeStub() { |
388 HValue* undefined = graph()->GetConstantUndefined(); | 386 HValue* undefined = graph()->GetConstantUndefined(); |
389 | 387 |
390 HInstruction* allocation_site = Add<HLoadKeyed>(GetParameter(0), | 388 HInstruction* allocation_site = |
391 GetParameter(1), | 389 Add<HLoadKeyed>(GetParameter(0), GetParameter(1), nullptr, FAST_ELEMENTS); |
392 static_cast<HValue*>(NULL), | |
393 FAST_ELEMENTS); | |
394 | 390 |
395 IfBuilder checker(this); | 391 IfBuilder checker(this); |
396 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, | 392 checker.IfNot<HCompareObjectEqAndBranch, HValue*>(allocation_site, |
397 undefined); | 393 undefined); |
398 checker.And(); | 394 checker.And(); |
399 | 395 |
400 HObjectAccess access = HObjectAccess::ForAllocationSiteOffset( | 396 HObjectAccess access = HObjectAccess::ForAllocationSiteOffset( |
401 AllocationSite::kTransitionInfoOffset); | 397 AllocationSite::kTransitionInfoOffset); |
402 HInstruction* boilerplate = Add<HLoadNamedField>( | 398 HInstruction* boilerplate = |
403 allocation_site, static_cast<HValue*>(NULL), access); | 399 Add<HLoadNamedField>(allocation_site, nullptr, access); |
404 | 400 |
405 int length = casted_stub()->length(); | 401 int length = casted_stub()->length(); |
406 if (length == 0) { | 402 if (length == 0) { |
407 // Empty objects have some slack added to them. | 403 // Empty objects have some slack added to them. |
408 length = JSObject::kInitialGlobalObjectUnusedPropertiesCount; | 404 length = JSObject::kInitialGlobalObjectUnusedPropertiesCount; |
409 } | 405 } |
410 int size = JSObject::kHeaderSize + length * kPointerSize; | 406 int size = JSObject::kHeaderSize + length * kPointerSize; |
411 int object_size = size; | 407 int object_size = size; |
412 if (FLAG_allocation_site_pretenuring) { | 408 if (FLAG_allocation_site_pretenuring) { |
413 size += AllocationMemento::kSize; | 409 size += AllocationMemento::kSize; |
414 } | 410 } |
415 | 411 |
416 HValue* boilerplate_map = Add<HLoadNamedField>( | 412 HValue* boilerplate_map = |
417 boilerplate, static_cast<HValue*>(NULL), | 413 Add<HLoadNamedField>(boilerplate, nullptr, HObjectAccess::ForMap()); |
418 HObjectAccess::ForMap()); | |
419 HValue* boilerplate_size = Add<HLoadNamedField>( | 414 HValue* boilerplate_size = Add<HLoadNamedField>( |
420 boilerplate_map, static_cast<HValue*>(NULL), | 415 boilerplate_map, nullptr, HObjectAccess::ForMapInstanceSize()); |
421 HObjectAccess::ForMapInstanceSize()); | |
422 HValue* size_in_words = Add<HConstant>(object_size >> kPointerSizeLog2); | 416 HValue* size_in_words = Add<HConstant>(object_size >> kPointerSizeLog2); |
423 checker.If<HCompareNumericAndBranch>(boilerplate_size, | 417 checker.If<HCompareNumericAndBranch>(boilerplate_size, |
424 size_in_words, Token::EQ); | 418 size_in_words, Token::EQ); |
425 checker.Then(); | 419 checker.Then(); |
426 | 420 |
427 HValue* size_in_bytes = Add<HConstant>(size); | 421 HValue* size_in_bytes = Add<HConstant>(size); |
428 | 422 |
429 HInstruction* object = Add<HAllocate>(size_in_bytes, HType::JSObject(), | 423 HInstruction* object = Add<HAllocate>(size_in_bytes, HType::JSObject(), |
430 NOT_TENURED, JS_OBJECT_TYPE); | 424 NOT_TENURED, JS_OBJECT_TYPE); |
431 | 425 |
432 for (int i = 0; i < object_size; i += kPointerSize) { | 426 for (int i = 0; i < object_size; i += kPointerSize) { |
433 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(i); | 427 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(i); |
434 Add<HStoreNamedField>( | 428 Add<HStoreNamedField>(object, access, |
435 object, access, Add<HLoadNamedField>( | 429 Add<HLoadNamedField>(boilerplate, nullptr, access)); |
436 boilerplate, static_cast<HValue*>(NULL), access)); | |
437 } | 430 } |
438 | 431 |
439 DCHECK(FLAG_allocation_site_pretenuring || (size == object_size)); | 432 DCHECK(FLAG_allocation_site_pretenuring || (size == object_size)); |
440 if (FLAG_allocation_site_pretenuring) { | 433 if (FLAG_allocation_site_pretenuring) { |
441 BuildCreateAllocationMemento( | 434 BuildCreateAllocationMemento( |
442 object, Add<HConstant>(object_size), allocation_site); | 435 object, Add<HConstant>(object_size), allocation_site); |
443 } | 436 } |
444 | 437 |
445 environment()->Push(object); | 438 environment()->Push(object); |
446 checker.ElseDeopt("Uninitialized boilerplate in fast clone"); | 439 checker.ElseDeopt("Uninitialized boilerplate in fast clone"); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 Add<HConstant>(isolate()->factory()->empty_fixed_array()); | 488 Add<HConstant>(isolate()->factory()->empty_fixed_array()); |
496 Add<HStoreNamedField>( | 489 Add<HStoreNamedField>( |
497 object, | 490 object, |
498 HObjectAccess::ForAllocationSiteOffset( | 491 HObjectAccess::ForAllocationSiteOffset( |
499 AllocationSite::kDependentCodeOffset), | 492 AllocationSite::kDependentCodeOffset), |
500 empty_fixed_array); | 493 empty_fixed_array); |
501 | 494 |
502 // Link the object to the allocation site list | 495 // Link the object to the allocation site list |
503 HValue* site_list = Add<HConstant>( | 496 HValue* site_list = Add<HConstant>( |
504 ExternalReference::allocation_sites_list_address(isolate())); | 497 ExternalReference::allocation_sites_list_address(isolate())); |
505 HValue* site = Add<HLoadNamedField>( | 498 HValue* site = Add<HLoadNamedField>(site_list, nullptr, |
506 site_list, static_cast<HValue*>(NULL), | 499 HObjectAccess::ForAllocationSiteList()); |
507 HObjectAccess::ForAllocationSiteList()); | |
508 // TODO(mvstanton): This is a store to a weak pointer, which we may want to | 500 // TODO(mvstanton): This is a store to a weak pointer, which we may want to |
509 // mark as such in order to skip the write barrier, once we have a unified | 501 // mark as such in order to skip the write barrier, once we have a unified |
510 // system for weakness. For now we decided to keep it like this because having | 502 // system for weakness. For now we decided to keep it like this because having |
511 // an initial write barrier backed store makes this pointer strong until the | 503 // an initial write barrier backed store makes this pointer strong until the |
512 // next GC, and allocation sites are designed to survive several GCs anyway. | 504 // next GC, and allocation sites are designed to survive several GCs anyway. |
513 Add<HStoreNamedField>( | 505 Add<HStoreNamedField>( |
514 object, | 506 object, |
515 HObjectAccess::ForAllocationSiteOffset(AllocationSite::kWeakNextOffset), | 507 HObjectAccess::ForAllocationSiteOffset(AllocationSite::kWeakNextOffset), |
516 site); | 508 site); |
517 Add<HStoreNamedField>(site_list, HObjectAccess::ForAllocationSiteList(), | 509 Add<HStoreNamedField>(site_list, HObjectAccess::ForAllocationSiteList(), |
(...skipping 11 matching lines...) Expand all Loading... |
529 return DoGenerateCode(this); | 521 return DoGenerateCode(this); |
530 } | 522 } |
531 | 523 |
532 | 524 |
533 template <> | 525 template <> |
534 HValue* CodeStubGraphBuilder<LoadScriptContextFieldStub>::BuildCodeStub() { | 526 HValue* CodeStubGraphBuilder<LoadScriptContextFieldStub>::BuildCodeStub() { |
535 int context_index = casted_stub()->context_index(); | 527 int context_index = casted_stub()->context_index(); |
536 int slot_index = casted_stub()->slot_index(); | 528 int slot_index = casted_stub()->slot_index(); |
537 | 529 |
538 HValue* script_context = BuildGetScriptContext(context_index); | 530 HValue* script_context = BuildGetScriptContext(context_index); |
539 return Add<HLoadNamedField>(script_context, static_cast<HValue*>(NULL), | 531 return Add<HLoadNamedField>(script_context, nullptr, |
540 HObjectAccess::ForContextSlot(slot_index)); | 532 HObjectAccess::ForContextSlot(slot_index)); |
541 } | 533 } |
542 | 534 |
543 | 535 |
544 Handle<Code> LoadScriptContextFieldStub::GenerateCode() { | 536 Handle<Code> LoadScriptContextFieldStub::GenerateCode() { |
545 return DoGenerateCode(this); | 537 return DoGenerateCode(this); |
546 } | 538 } |
547 | 539 |
548 | 540 |
549 template <> | 541 template <> |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 ? Representation::Double() | 578 ? Representation::Double() |
587 : Representation::Tagged(); | 579 : Representation::Tagged(); |
588 int offset = index.offset(); | 580 int offset = index.offset(); |
589 HObjectAccess access = index.is_inobject() | 581 HObjectAccess access = index.is_inobject() |
590 ? HObjectAccess::ForObservableJSObjectOffset(offset, representation) | 582 ? HObjectAccess::ForObservableJSObjectOffset(offset, representation) |
591 : HObjectAccess::ForBackingStoreOffset(offset, representation); | 583 : HObjectAccess::ForBackingStoreOffset(offset, representation); |
592 if (index.is_double() && | 584 if (index.is_double() && |
593 (!FLAG_unbox_double_fields || !index.is_inobject())) { | 585 (!FLAG_unbox_double_fields || !index.is_inobject())) { |
594 // Load the heap number. | 586 // Load the heap number. |
595 object = Add<HLoadNamedField>( | 587 object = Add<HLoadNamedField>( |
596 object, static_cast<HValue*>(NULL), | 588 object, nullptr, access.WithRepresentation(Representation::Tagged())); |
597 access.WithRepresentation(Representation::Tagged())); | |
598 // Load the double value from it. | 589 // Load the double value from it. |
599 access = HObjectAccess::ForHeapNumberValue(); | 590 access = HObjectAccess::ForHeapNumberValue(); |
600 } | 591 } |
601 return Add<HLoadNamedField>(object, static_cast<HValue*>(NULL), access); | 592 return Add<HLoadNamedField>(object, nullptr, access); |
602 } | 593 } |
603 | 594 |
604 | 595 |
605 template<> | 596 template<> |
606 HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() { | 597 HValue* CodeStubGraphBuilder<LoadFieldStub>::BuildCodeStub() { |
607 return BuildLoadNamedField(GetParameter(0), casted_stub()->index()); | 598 return BuildLoadNamedField(GetParameter(0), casted_stub()->index()); |
608 } | 599 } |
609 | 600 |
610 | 601 |
611 Handle<Code> LoadFieldStub::GenerateCode() { | 602 Handle<Code> LoadFieldStub::GenerateCode() { |
612 return DoGenerateCode(this); | 603 return DoGenerateCode(this); |
613 } | 604 } |
614 | 605 |
615 | 606 |
616 template <> | 607 template <> |
617 HValue* CodeStubGraphBuilder<LoadConstantStub>::BuildCodeStub() { | 608 HValue* CodeStubGraphBuilder<LoadConstantStub>::BuildCodeStub() { |
618 HValue* map = AddLoadMap(GetParameter(0), NULL); | 609 HValue* map = AddLoadMap(GetParameter(0), NULL); |
619 HObjectAccess descriptors_access = HObjectAccess::ForObservableJSObjectOffset( | 610 HObjectAccess descriptors_access = HObjectAccess::ForObservableJSObjectOffset( |
620 Map::kDescriptorsOffset, Representation::Tagged()); | 611 Map::kDescriptorsOffset, Representation::Tagged()); |
621 HValue* descriptors = | 612 HValue* descriptors = Add<HLoadNamedField>(map, nullptr, descriptors_access); |
622 Add<HLoadNamedField>(map, static_cast<HValue*>(NULL), descriptors_access); | |
623 HObjectAccess value_access = HObjectAccess::ForObservableJSObjectOffset( | 613 HObjectAccess value_access = HObjectAccess::ForObservableJSObjectOffset( |
624 DescriptorArray::GetValueOffset(casted_stub()->constant_index())); | 614 DescriptorArray::GetValueOffset(casted_stub()->constant_index())); |
625 return Add<HLoadNamedField>(descriptors, static_cast<HValue*>(NULL), | 615 return Add<HLoadNamedField>(descriptors, nullptr, value_access); |
626 value_access); | |
627 } | 616 } |
628 | 617 |
629 | 618 |
630 Handle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); } | 619 Handle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); } |
631 | 620 |
632 | 621 |
633 HValue* CodeStubGraphBuilderBase::UnmappedCase(HValue* elements, HValue* key) { | 622 HValue* CodeStubGraphBuilderBase::UnmappedCase(HValue* elements, HValue* key) { |
634 HValue* result; | 623 HValue* result; |
635 HInstruction* backing_store = Add<HLoadKeyed>( | 624 HInstruction* backing_store = |
636 elements, graph()->GetConstant1(), static_cast<HValue*>(NULL), | 625 Add<HLoadKeyed>(elements, graph()->GetConstant1(), nullptr, FAST_ELEMENTS, |
637 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | 626 ALLOW_RETURN_HOLE); |
638 Add<HCheckMaps>(backing_store, isolate()->factory()->fixed_array_map()); | 627 Add<HCheckMaps>(backing_store, isolate()->factory()->fixed_array_map()); |
639 HValue* backing_store_length = | 628 HValue* backing_store_length = Add<HLoadNamedField>( |
640 Add<HLoadNamedField>(backing_store, static_cast<HValue*>(NULL), | 629 backing_store, nullptr, HObjectAccess::ForFixedArrayLength()); |
641 HObjectAccess::ForFixedArrayLength()); | |
642 IfBuilder in_unmapped_range(this); | 630 IfBuilder in_unmapped_range(this); |
643 in_unmapped_range.If<HCompareNumericAndBranch>(key, backing_store_length, | 631 in_unmapped_range.If<HCompareNumericAndBranch>(key, backing_store_length, |
644 Token::LT); | 632 Token::LT); |
645 in_unmapped_range.Then(); | 633 in_unmapped_range.Then(); |
646 { | 634 { |
647 result = Add<HLoadKeyed>(backing_store, key, static_cast<HValue*>(NULL), | 635 result = Add<HLoadKeyed>(backing_store, key, nullptr, FAST_HOLEY_ELEMENTS, |
648 FAST_HOLEY_ELEMENTS, NEVER_RETURN_HOLE); | 636 NEVER_RETURN_HOLE); |
649 } | 637 } |
650 in_unmapped_range.ElseDeopt("Outside of range"); | 638 in_unmapped_range.ElseDeopt("Outside of range"); |
651 in_unmapped_range.End(); | 639 in_unmapped_range.End(); |
652 return result; | 640 return result; |
653 } | 641 } |
654 | 642 |
655 | 643 |
656 template <> | 644 template <> |
657 HValue* CodeStubGraphBuilder<KeyedLoadSloppyArgumentsStub>::BuildCodeStub() { | 645 HValue* CodeStubGraphBuilder<KeyedLoadSloppyArgumentsStub>::BuildCodeStub() { |
658 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); | 646 HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex); |
(...skipping 26 matching lines...) Expand all Loading... |
685 // context[t]. | 673 // context[t]. |
686 | 674 |
687 key = AddUncasted<HForceRepresentation>(key, Representation::Smi()); | 675 key = AddUncasted<HForceRepresentation>(key, Representation::Smi()); |
688 IfBuilder positive_smi(this); | 676 IfBuilder positive_smi(this); |
689 positive_smi.If<HCompareNumericAndBranch>(key, graph()->GetConstant0(), | 677 positive_smi.If<HCompareNumericAndBranch>(key, graph()->GetConstant0(), |
690 Token::LT); | 678 Token::LT); |
691 positive_smi.ThenDeopt("key is negative"); | 679 positive_smi.ThenDeopt("key is negative"); |
692 positive_smi.End(); | 680 positive_smi.End(); |
693 | 681 |
694 HValue* constant_two = Add<HConstant>(2); | 682 HValue* constant_two = Add<HConstant>(2); |
695 HValue* elements = AddLoadElements(receiver, static_cast<HValue*>(NULL)); | 683 HValue* elements = AddLoadElements(receiver, nullptr); |
696 HValue* elements_length = | 684 HValue* elements_length = Add<HLoadNamedField>( |
697 Add<HLoadNamedField>(elements, static_cast<HValue*>(NULL), | 685 elements, nullptr, HObjectAccess::ForFixedArrayLength()); |
698 HObjectAccess::ForFixedArrayLength()); | |
699 HValue* adjusted_length = AddUncasted<HSub>(elements_length, constant_two); | 686 HValue* adjusted_length = AddUncasted<HSub>(elements_length, constant_two); |
700 IfBuilder in_range(this); | 687 IfBuilder in_range(this); |
701 in_range.If<HCompareNumericAndBranch>(key, adjusted_length, Token::LT); | 688 in_range.If<HCompareNumericAndBranch>(key, adjusted_length, Token::LT); |
702 in_range.Then(); | 689 in_range.Then(); |
703 { | 690 { |
704 HValue* index = AddUncasted<HAdd>(key, constant_two); | 691 HValue* index = AddUncasted<HAdd>(key, constant_two); |
705 HInstruction* mapped_index = | 692 HInstruction* mapped_index = Add<HLoadKeyed>( |
706 Add<HLoadKeyed>(elements, index, static_cast<HValue*>(NULL), | 693 elements, index, nullptr, FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE); |
707 FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE); | |
708 | 694 |
709 IfBuilder is_valid(this); | 695 IfBuilder is_valid(this); |
710 is_valid.IfNot<HCompareObjectEqAndBranch>(mapped_index, | 696 is_valid.IfNot<HCompareObjectEqAndBranch>(mapped_index, |
711 graph()->GetConstantHole()); | 697 graph()->GetConstantHole()); |
712 is_valid.Then(); | 698 is_valid.Then(); |
713 { | 699 { |
714 // TODO(mvstanton): I'd like to assert from this point, that if the | 700 // TODO(mvstanton): I'd like to assert from this point, that if the |
715 // mapped_index is not the hole that it is indeed, a smi. An unnecessary | 701 // mapped_index is not the hole that it is indeed, a smi. An unnecessary |
716 // smi check is being emitted. | 702 // smi check is being emitted. |
717 HValue* the_context = | 703 HValue* the_context = Add<HLoadKeyed>(elements, graph()->GetConstant0(), |
718 Add<HLoadKeyed>(elements, graph()->GetConstant0(), | 704 nullptr, FAST_ELEMENTS); |
719 static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
720 DCHECK(Context::kHeaderSize == FixedArray::kHeaderSize); | 705 DCHECK(Context::kHeaderSize == FixedArray::kHeaderSize); |
721 HValue* result = | 706 HValue* result = Add<HLoadKeyed>(the_context, mapped_index, nullptr, |
722 Add<HLoadKeyed>(the_context, mapped_index, static_cast<HValue*>(NULL), | 707 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
723 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | |
724 environment()->Push(result); | 708 environment()->Push(result); |
725 } | 709 } |
726 is_valid.Else(); | 710 is_valid.Else(); |
727 { | 711 { |
728 HValue* result = UnmappedCase(elements, key); | 712 HValue* result = UnmappedCase(elements, key); |
729 environment()->Push(result); | 713 environment()->Push(result); |
730 } | 714 } |
731 is_valid.End(); | 715 is_valid.End(); |
732 } | 716 } |
733 in_range.Else(); | 717 in_range.Else(); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
771 MUTABLE_HEAP_NUMBER_TYPE); | 755 MUTABLE_HEAP_NUMBER_TYPE); |
772 AddStoreMapConstant(heap_number, | 756 AddStoreMapConstant(heap_number, |
773 isolate()->factory()->mutable_heap_number_map()); | 757 isolate()->factory()->mutable_heap_number_map()); |
774 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(), | 758 Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(), |
775 value); | 759 value); |
776 // Store the new mutable heap number into the object. | 760 // Store the new mutable heap number into the object. |
777 access = heap_number_access; | 761 access = heap_number_access; |
778 value = heap_number; | 762 value = heap_number; |
779 } else { | 763 } else { |
780 // Load the heap number. | 764 // Load the heap number. |
781 object = Add<HLoadNamedField>(object, static_cast<HValue*>(NULL), | 765 object = Add<HLoadNamedField>(object, nullptr, heap_number_access); |
782 heap_number_access); | |
783 // Store the double value into it. | 766 // Store the double value into it. |
784 access = HObjectAccess::ForHeapNumberValue(); | 767 access = HObjectAccess::ForHeapNumberValue(); |
785 } | 768 } |
786 } | 769 } |
787 } else if (representation.IsHeapObject()) { | 770 } else if (representation.IsHeapObject()) { |
788 BuildCheckHeapObject(value); | 771 BuildCheckHeapObject(value); |
789 } | 772 } |
790 | 773 |
791 Add<HStoreNamedField>(object, access, value, INITIALIZING_STORE); | 774 Add<HStoreNamedField>(object, access, value, INITIALIZING_STORE); |
792 } | 775 } |
793 | 776 |
794 | 777 |
795 template <> | 778 template <> |
796 HValue* CodeStubGraphBuilder<StoreFieldStub>::BuildCodeStub() { | 779 HValue* CodeStubGraphBuilder<StoreFieldStub>::BuildCodeStub() { |
797 BuildStoreNamedField(GetParameter(0), GetParameter(2), casted_stub()->index(), | 780 BuildStoreNamedField(GetParameter(0), GetParameter(2), casted_stub()->index(), |
798 casted_stub()->representation(), false); | 781 casted_stub()->representation(), false); |
799 return GetParameter(2); | 782 return GetParameter(2); |
800 } | 783 } |
801 | 784 |
802 | 785 |
803 Handle<Code> StoreFieldStub::GenerateCode() { return DoGenerateCode(this); } | 786 Handle<Code> StoreFieldStub::GenerateCode() { return DoGenerateCode(this); } |
804 | 787 |
805 | 788 |
806 template <> | 789 template <> |
807 HValue* CodeStubGraphBuilder<StoreTransitionStub>::BuildCodeStub() { | 790 HValue* CodeStubGraphBuilder<StoreTransitionStub>::BuildCodeStub() { |
808 HValue* object = GetParameter(StoreTransitionDescriptor::kReceiverIndex); | 791 HValue* object = GetParameter(StoreTransitionDescriptor::kReceiverIndex); |
809 | 792 |
810 switch (casted_stub()->store_mode()) { | 793 switch (casted_stub()->store_mode()) { |
811 case StoreTransitionStub::ExtendStorageAndStoreMapAndValue: { | 794 case StoreTransitionStub::ExtendStorageAndStoreMapAndValue: { |
812 HValue* properties = | 795 HValue* properties = Add<HLoadNamedField>( |
813 Add<HLoadNamedField>(object, static_cast<HValue*>(NULL), | 796 object, nullptr, HObjectAccess::ForPropertiesPointer()); |
814 HObjectAccess::ForPropertiesPointer()); | |
815 HValue* length = AddLoadFixedArrayLength(properties); | 797 HValue* length = AddLoadFixedArrayLength(properties); |
816 HValue* delta = | 798 HValue* delta = |
817 Add<HConstant>(static_cast<int32_t>(JSObject::kFieldsAdded)); | 799 Add<HConstant>(static_cast<int32_t>(JSObject::kFieldsAdded)); |
818 HValue* new_capacity = AddUncasted<HAdd>(length, delta); | 800 HValue* new_capacity = AddUncasted<HAdd>(length, delta); |
819 | 801 |
820 // Grow properties array. | 802 // Grow properties array. |
821 ElementsKind kind = FAST_ELEMENTS; | 803 ElementsKind kind = FAST_ELEMENTS; |
822 Add<HBoundsCheck>(new_capacity, | 804 Add<HBoundsCheck>(new_capacity, |
823 Add<HConstant>((Page::kMaxRegularHeapObjectSize - | 805 Add<HConstant>((Page::kMaxRegularHeapObjectSize - |
824 FixedArray::kHeaderSize) >> | 806 FixedArray::kHeaderSize) >> |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1338 // Check that the map of the global has not changed: use a placeholder map | 1320 // Check that the map of the global has not changed: use a placeholder map |
1339 // that will be replaced later with the global object's map. | 1321 // that will be replaced later with the global object's map. |
1340 Handle<Map> placeholder_map = isolate()->factory()->meta_map(); | 1322 Handle<Map> placeholder_map = isolate()->factory()->meta_map(); |
1341 HValue* global = Add<HConstant>( | 1323 HValue* global = Add<HConstant>( |
1342 StoreGlobalStub::global_placeholder(isolate())); | 1324 StoreGlobalStub::global_placeholder(isolate())); |
1343 Add<HCheckMaps>(global, placeholder_map); | 1325 Add<HCheckMaps>(global, placeholder_map); |
1344 } | 1326 } |
1345 | 1327 |
1346 HValue* cell = Add<HConstant>(placeholder_cell); | 1328 HValue* cell = Add<HConstant>(placeholder_cell); |
1347 HObjectAccess access(HObjectAccess::ForCellPayload(isolate())); | 1329 HObjectAccess access(HObjectAccess::ForCellPayload(isolate())); |
1348 HValue* cell_contents = Add<HLoadNamedField>( | 1330 HValue* cell_contents = Add<HLoadNamedField>(cell, nullptr, access); |
1349 cell, static_cast<HValue*>(NULL), access); | |
1350 | 1331 |
1351 if (stub->is_constant()) { | 1332 if (stub->is_constant()) { |
1352 IfBuilder builder(this); | 1333 IfBuilder builder(this); |
1353 builder.If<HCompareObjectEqAndBranch>(cell_contents, value); | 1334 builder.If<HCompareObjectEqAndBranch>(cell_contents, value); |
1354 builder.Then(); | 1335 builder.Then(); |
1355 builder.ElseDeopt("Unexpected cell contents in constant global store"); | 1336 builder.ElseDeopt("Unexpected cell contents in constant global store"); |
1356 builder.End(); | 1337 builder.End(); |
1357 } else { | 1338 } else { |
1358 // Load the payload of the global parameter cell. A hole indicates that the | 1339 // Load the payload of the global parameter cell. A hole indicates that the |
1359 // property has been deleted and that the store must be handled by the | 1340 // property has been deleted and that the store must be handled by the |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1437 | 1418 |
1438 // TODO(fschneider): Idea: store proper code pointers in the optimized code | 1419 // TODO(fschneider): Idea: store proper code pointers in the optimized code |
1439 // map and either unmangle them on marking or do nothing as the whole map is | 1420 // map and either unmangle them on marking or do nothing as the whole map is |
1440 // discarded on major GC anyway. | 1421 // discarded on major GC anyway. |
1441 Add<HStoreCodeEntry>(js_function, code_object); | 1422 Add<HStoreCodeEntry>(js_function, code_object); |
1442 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), | 1423 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), |
1443 literals); | 1424 literals); |
1444 | 1425 |
1445 // Now link a function into a list of optimized functions. | 1426 // Now link a function into a list of optimized functions. |
1446 HValue* optimized_functions_list = Add<HLoadNamedField>( | 1427 HValue* optimized_functions_list = Add<HLoadNamedField>( |
1447 native_context, static_cast<HValue*>(NULL), | 1428 native_context, nullptr, |
1448 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST)); | 1429 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST)); |
1449 Add<HStoreNamedField>(js_function, | 1430 Add<HStoreNamedField>(js_function, |
1450 HObjectAccess::ForNextFunctionLinkPointer(), | 1431 HObjectAccess::ForNextFunctionLinkPointer(), |
1451 optimized_functions_list); | 1432 optimized_functions_list); |
1452 | 1433 |
1453 // This store is the only one that should have a write barrier. | 1434 // This store is the only one that should have a write barrier. |
1454 Add<HStoreNamedField>(native_context, | 1435 Add<HStoreNamedField>(native_context, |
1455 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST), | 1436 HObjectAccess::ForContextSlot(Context::OPTIMIZED_FUNCTIONS_LIST), |
1456 js_function); | 1437 js_function); |
1457 | 1438 |
1458 // The builder continues in the "then" after this function. | 1439 // The builder continues in the "then" after this function. |
1459 } | 1440 } |
1460 | 1441 |
1461 | 1442 |
1462 void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function, | 1443 void CodeStubGraphBuilderBase::BuildInstallCode(HValue* js_function, |
1463 HValue* shared_info) { | 1444 HValue* shared_info) { |
1464 Add<HStoreNamedField>(js_function, | 1445 Add<HStoreNamedField>(js_function, |
1465 HObjectAccess::ForNextFunctionLinkPointer(), | 1446 HObjectAccess::ForNextFunctionLinkPointer(), |
1466 graph()->GetConstantUndefined()); | 1447 graph()->GetConstantUndefined()); |
1467 HValue* code_object = Add<HLoadNamedField>( | 1448 HValue* code_object = Add<HLoadNamedField>(shared_info, nullptr, |
1468 shared_info, static_cast<HValue*>(NULL), HObjectAccess::ForCodeOffset()); | 1449 HObjectAccess::ForCodeOffset()); |
1469 Add<HStoreCodeEntry>(js_function, code_object); | 1450 Add<HStoreCodeEntry>(js_function, code_object); |
1470 } | 1451 } |
1471 | 1452 |
1472 | 1453 |
1473 HInstruction* CodeStubGraphBuilderBase::LoadFromOptimizedCodeMap( | 1454 HInstruction* CodeStubGraphBuilderBase::LoadFromOptimizedCodeMap( |
1474 HValue* optimized_map, | 1455 HValue* optimized_map, |
1475 HValue* iterator, | 1456 HValue* iterator, |
1476 int field_offset) { | 1457 int field_offset) { |
1477 // By making sure to express these loads in the form [<hvalue> + constant] | 1458 // By making sure to express these loads in the form [<hvalue> + constant] |
1478 // the keyed load can be hoisted. | 1459 // the keyed load can be hoisted. |
1479 DCHECK(field_offset >= 0 && field_offset < SharedFunctionInfo::kEntryLength); | 1460 DCHECK(field_offset >= 0 && field_offset < SharedFunctionInfo::kEntryLength); |
1480 HValue* field_slot = iterator; | 1461 HValue* field_slot = iterator; |
1481 if (field_offset > 0) { | 1462 if (field_offset > 0) { |
1482 HValue* field_offset_value = Add<HConstant>(field_offset); | 1463 HValue* field_offset_value = Add<HConstant>(field_offset); |
1483 field_slot = AddUncasted<HAdd>(iterator, field_offset_value); | 1464 field_slot = AddUncasted<HAdd>(iterator, field_offset_value); |
1484 } | 1465 } |
1485 HInstruction* field_entry = Add<HLoadKeyed>(optimized_map, field_slot, | 1466 HInstruction* field_entry = |
1486 static_cast<HValue*>(NULL), FAST_ELEMENTS); | 1467 Add<HLoadKeyed>(optimized_map, field_slot, nullptr, FAST_ELEMENTS); |
1487 return field_entry; | 1468 return field_entry; |
1488 } | 1469 } |
1489 | 1470 |
1490 | 1471 |
1491 void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( | 1472 void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap( |
1492 HValue* js_function, | 1473 HValue* js_function, |
1493 HValue* shared_info, | 1474 HValue* shared_info, |
1494 HValue* native_context) { | 1475 HValue* native_context) { |
1495 Counters* counters = isolate()->counters(); | 1476 Counters* counters = isolate()->counters(); |
1496 IfBuilder is_optimized(this); | 1477 IfBuilder is_optimized(this); |
1497 HInstruction* optimized_map = Add<HLoadNamedField>( | 1478 HInstruction* optimized_map = Add<HLoadNamedField>( |
1498 shared_info, static_cast<HValue*>(NULL), | 1479 shared_info, nullptr, HObjectAccess::ForOptimizedCodeMap()); |
1499 HObjectAccess::ForOptimizedCodeMap()); | |
1500 HValue* null_constant = Add<HConstant>(0); | 1480 HValue* null_constant = Add<HConstant>(0); |
1501 is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant); | 1481 is_optimized.If<HCompareObjectEqAndBranch>(optimized_map, null_constant); |
1502 is_optimized.Then(); | 1482 is_optimized.Then(); |
1503 { | 1483 { |
1504 BuildInstallCode(js_function, shared_info); | 1484 BuildInstallCode(js_function, shared_info); |
1505 } | 1485 } |
1506 is_optimized.Else(); | 1486 is_optimized.Else(); |
1507 { | 1487 { |
1508 AddIncrementCounter(counters->fast_new_closure_try_optimized()); | 1488 AddIncrementCounter(counters->fast_new_closure_try_optimized()); |
1509 // optimized_map points to fixed array of 3-element entries | 1489 // optimized_map points to fixed array of 3-element entries |
(...skipping 12 matching lines...) Expand all Loading... |
1522 // for(i = map.length() - SharedFunctionInfo::kEntryLength; | 1502 // for(i = map.length() - SharedFunctionInfo::kEntryLength; |
1523 // i > SharedFunctionInfo::kEntriesStart; | 1503 // i > SharedFunctionInfo::kEntriesStart; |
1524 // i -= SharedFunctionInfo::kEntryLength) { .. } | 1504 // i -= SharedFunctionInfo::kEntryLength) { .. } |
1525 HValue* shared_function_entry_length = | 1505 HValue* shared_function_entry_length = |
1526 Add<HConstant>(SharedFunctionInfo::kEntryLength); | 1506 Add<HConstant>(SharedFunctionInfo::kEntryLength); |
1527 LoopBuilder loop_builder(this, | 1507 LoopBuilder loop_builder(this, |
1528 context(), | 1508 context(), |
1529 LoopBuilder::kPostDecrement, | 1509 LoopBuilder::kPostDecrement, |
1530 shared_function_entry_length); | 1510 shared_function_entry_length); |
1531 HValue* array_length = Add<HLoadNamedField>( | 1511 HValue* array_length = Add<HLoadNamedField>( |
1532 optimized_map, static_cast<HValue*>(NULL), | 1512 optimized_map, nullptr, HObjectAccess::ForFixedArrayLength()); |
1533 HObjectAccess::ForFixedArrayLength()); | |
1534 HValue* start_pos = AddUncasted<HSub>(array_length, | 1513 HValue* start_pos = AddUncasted<HSub>(array_length, |
1535 shared_function_entry_length); | 1514 shared_function_entry_length); |
1536 HValue* slot_iterator = loop_builder.BeginBody(start_pos, | 1515 HValue* slot_iterator = loop_builder.BeginBody(start_pos, |
1537 first_entry_index, | 1516 first_entry_index, |
1538 Token::GT); | 1517 Token::GT); |
1539 { | 1518 { |
1540 IfBuilder done_check(this); | 1519 IfBuilder done_check(this); |
1541 BuildCheckAndInstallOptimizedCode(js_function, native_context, | 1520 BuildCheckAndInstallOptimizedCode(js_function, native_context, |
1542 &done_check, | 1521 &done_check, |
1543 optimized_map, | 1522 optimized_map, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1576 HValue* size = Add<HConstant>(JSFunction::kSize); | 1555 HValue* size = Add<HConstant>(JSFunction::kSize); |
1577 HInstruction* js_function = | 1556 HInstruction* js_function = |
1578 Add<HAllocate>(size, HType::JSObject(), NOT_TENURED, JS_FUNCTION_TYPE); | 1557 Add<HAllocate>(size, HType::JSObject(), NOT_TENURED, JS_FUNCTION_TYPE); |
1579 | 1558 |
1580 int map_index = Context::FunctionMapIndex(casted_stub()->strict_mode(), | 1559 int map_index = Context::FunctionMapIndex(casted_stub()->strict_mode(), |
1581 casted_stub()->kind()); | 1560 casted_stub()->kind()); |
1582 | 1561 |
1583 // Compute the function map in the current native context and set that | 1562 // Compute the function map in the current native context and set that |
1584 // as the map of the allocated object. | 1563 // as the map of the allocated object. |
1585 HInstruction* native_context = BuildGetNativeContext(); | 1564 HInstruction* native_context = BuildGetNativeContext(); |
1586 HInstruction* map_slot_value = | 1565 HInstruction* map_slot_value = Add<HLoadNamedField>( |
1587 Add<HLoadNamedField>(native_context, static_cast<HValue*>(NULL), | 1566 native_context, nullptr, HObjectAccess::ForContextSlot(map_index)); |
1588 HObjectAccess::ForContextSlot(map_index)); | |
1589 Add<HStoreNamedField>(js_function, HObjectAccess::ForMap(), map_slot_value); | 1567 Add<HStoreNamedField>(js_function, HObjectAccess::ForMap(), map_slot_value); |
1590 | 1568 |
1591 // Initialize the rest of the function. | 1569 // Initialize the rest of the function. |
1592 Add<HStoreNamedField>(js_function, HObjectAccess::ForPropertiesPointer(), | 1570 Add<HStoreNamedField>(js_function, HObjectAccess::ForPropertiesPointer(), |
1593 empty_fixed_array); | 1571 empty_fixed_array); |
1594 Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(), | 1572 Add<HStoreNamedField>(js_function, HObjectAccess::ForElementsPointer(), |
1595 empty_fixed_array); | 1573 empty_fixed_array); |
1596 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), | 1574 Add<HStoreNamedField>(js_function, HObjectAccess::ForLiteralsPointer(), |
1597 empty_fixed_array); | 1575 empty_fixed_array); |
1598 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), | 1576 Add<HStoreNamedField>(js_function, HObjectAccess::ForPrototypeOrInitialMap(), |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1645 function); | 1623 function); |
1646 Add<HStoreNamedField>(function_context, | 1624 Add<HStoreNamedField>(function_context, |
1647 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX), | 1625 HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX), |
1648 context()); | 1626 context()); |
1649 Add<HStoreNamedField>(function_context, | 1627 Add<HStoreNamedField>(function_context, |
1650 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX), | 1628 HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX), |
1651 graph()->GetConstant0()); | 1629 graph()->GetConstant0()); |
1652 | 1630 |
1653 // Copy the global object from the previous context. | 1631 // Copy the global object from the previous context. |
1654 HValue* global_object = Add<HLoadNamedField>( | 1632 HValue* global_object = Add<HLoadNamedField>( |
1655 context(), static_cast<HValue*>(NULL), | 1633 context(), nullptr, |
1656 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); | 1634 HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX)); |
1657 Add<HStoreNamedField>(function_context, | 1635 Add<HStoreNamedField>(function_context, |
1658 HObjectAccess::ForContextSlot( | 1636 HObjectAccess::ForContextSlot( |
1659 Context::GLOBAL_OBJECT_INDEX), | 1637 Context::GLOBAL_OBJECT_INDEX), |
1660 global_object); | 1638 global_object); |
1661 | 1639 |
1662 // Initialize the rest of the slots to undefined. | 1640 // Initialize the rest of the slots to undefined. |
1663 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; ++i) { | 1641 for (int i = Context::MIN_CONTEXT_SLOTS; i < length; ++i) { |
1664 Add<HStoreNamedField>(function_context, | 1642 Add<HStoreNamedField>(function_context, |
1665 HObjectAccess::ForContextSlot(i), | 1643 HObjectAccess::ForContextSlot(i), |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1810 IfBuilder index_name_split(this, &index_name_split_continuation); | 1788 IfBuilder index_name_split(this, &index_name_split_continuation); |
1811 index_name_split.Then(); | 1789 index_name_split.Then(); |
1812 { | 1790 { |
1813 // Key is an index (number) | 1791 // Key is an index (number) |
1814 key = Pop(); | 1792 key = Pop(); |
1815 | 1793 |
1816 int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) | | 1794 int bit_field_mask = (1 << Map::kIsAccessCheckNeeded) | |
1817 (1 << Map::kHasIndexedInterceptor); | 1795 (1 << Map::kHasIndexedInterceptor); |
1818 BuildJSObjectCheck(receiver, bit_field_mask); | 1796 BuildJSObjectCheck(receiver, bit_field_mask); |
1819 | 1797 |
1820 HValue* map = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL), | 1798 HValue* map = |
1821 HObjectAccess::ForMap()); | 1799 Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap()); |
1822 | 1800 |
1823 HValue* instance_type = | 1801 HValue* instance_type = |
1824 Add<HLoadNamedField>(map, static_cast<HValue*>(NULL), | 1802 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType()); |
1825 HObjectAccess::ForMapInstanceType()); | |
1826 | 1803 |
1827 HValue* bit_field2 = Add<HLoadNamedField>(map, | 1804 HValue* bit_field2 = |
1828 static_cast<HValue*>(NULL), | 1805 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2()); |
1829 HObjectAccess::ForMapBitField2()); | |
1830 | 1806 |
1831 IfBuilder kind_if(this); | 1807 IfBuilder kind_if(this); |
1832 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | 1808 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
1833 FAST_HOLEY_ELEMENTS); | 1809 FAST_HOLEY_ELEMENTS); |
1834 | 1810 |
1835 kind_if.Else(); | 1811 kind_if.Else(); |
1836 { | 1812 { |
1837 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, | 1813 BuildFastElementLoad(&kind_if, receiver, key, instance_type, bit_field2, |
1838 FAST_HOLEY_DOUBLE_ELEMENTS); | 1814 FAST_HOLEY_DOUBLE_ELEMENTS); |
1839 } | 1815 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1909 | 1885 |
1910 HIfContinuation continuation; | 1886 HIfContinuation continuation; |
1911 BuildTestForDictionaryProperties(receiver, &continuation); | 1887 BuildTestForDictionaryProperties(receiver, &continuation); |
1912 IfBuilder if_dict_properties(this, &continuation); | 1888 IfBuilder if_dict_properties(this, &continuation); |
1913 if_dict_properties.Then(); | 1889 if_dict_properties.Then(); |
1914 { | 1890 { |
1915 // Key is string, properties are dictionary mode | 1891 // Key is string, properties are dictionary mode |
1916 BuildNonGlobalObjectCheck(receiver); | 1892 BuildNonGlobalObjectCheck(receiver); |
1917 | 1893 |
1918 HValue* properties = Add<HLoadNamedField>( | 1894 HValue* properties = Add<HLoadNamedField>( |
1919 receiver, static_cast<HValue*>(NULL), | 1895 receiver, nullptr, HObjectAccess::ForPropertiesPointer()); |
1920 HObjectAccess::ForPropertiesPointer()); | |
1921 | 1896 |
1922 HValue* hash = | 1897 HValue* hash = |
1923 Add<HLoadNamedField>(key, static_cast<HValue*>(NULL), | 1898 Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForNameHashField()); |
1924 HObjectAccess::ForNameHashField()); | |
1925 | 1899 |
1926 hash = AddUncasted<HShr>(hash, Add<HConstant>(Name::kHashShift)); | 1900 hash = AddUncasted<HShr>(hash, Add<HConstant>(Name::kHashShift)); |
1927 | 1901 |
1928 HValue* value = BuildUncheckedDictionaryElementLoad(receiver, | 1902 HValue* value = BuildUncheckedDictionaryElementLoad(receiver, |
1929 properties, | 1903 properties, |
1930 key, | 1904 key, |
1931 hash); | 1905 hash); |
1932 Push(value); | 1906 Push(value); |
1933 } | 1907 } |
1934 if_dict_properties.Else(); | 1908 if_dict_properties.Else(); |
1935 { | 1909 { |
1936 // Key is string, properties are fast mode | 1910 // Key is string, properties are fast mode |
1937 HValue* hash = BuildKeyedLookupCacheHash(receiver, key); | 1911 HValue* hash = BuildKeyedLookupCacheHash(receiver, key); |
1938 | 1912 |
1939 ExternalReference cache_keys_ref = | 1913 ExternalReference cache_keys_ref = |
1940 ExternalReference::keyed_lookup_cache_keys(isolate()); | 1914 ExternalReference::keyed_lookup_cache_keys(isolate()); |
1941 HValue* cache_keys = Add<HConstant>(cache_keys_ref); | 1915 HValue* cache_keys = Add<HConstant>(cache_keys_ref); |
1942 | 1916 |
1943 HValue* map = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL), | 1917 HValue* map = |
1944 HObjectAccess::ForMap()); | 1918 Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap()); |
1945 HValue* base_index = AddUncasted<HMul>(hash, Add<HConstant>(2)); | 1919 HValue* base_index = AddUncasted<HMul>(hash, Add<HConstant>(2)); |
1946 base_index->ClearFlag(HValue::kCanOverflow); | 1920 base_index->ClearFlag(HValue::kCanOverflow); |
1947 | 1921 |
1948 HIfContinuation inline_or_runtime_continuation( | 1922 HIfContinuation inline_or_runtime_continuation( |
1949 graph()->CreateBasicBlock(), graph()->CreateBasicBlock()); | 1923 graph()->CreateBasicBlock(), graph()->CreateBasicBlock()); |
1950 { | 1924 { |
1951 IfBuilder lookup_ifs[KeyedLookupCache::kEntriesPerBucket]; | 1925 IfBuilder lookup_ifs[KeyedLookupCache::kEntriesPerBucket]; |
1952 for (int probe = 0; probe < KeyedLookupCache::kEntriesPerBucket; | 1926 for (int probe = 0; probe < KeyedLookupCache::kEntriesPerBucket; |
1953 ++probe) { | 1927 ++probe) { |
1954 IfBuilder* lookup_if = &lookup_ifs[probe]; | 1928 IfBuilder* lookup_if = &lookup_ifs[probe]; |
1955 lookup_if->Initialize(this); | 1929 lookup_if->Initialize(this); |
1956 int probe_base = probe * KeyedLookupCache::kEntryLength; | 1930 int probe_base = probe * KeyedLookupCache::kEntryLength; |
1957 HValue* map_index = AddUncasted<HAdd>( | 1931 HValue* map_index = AddUncasted<HAdd>( |
1958 base_index, | 1932 base_index, |
1959 Add<HConstant>(probe_base + KeyedLookupCache::kMapIndex)); | 1933 Add<HConstant>(probe_base + KeyedLookupCache::kMapIndex)); |
1960 map_index->ClearFlag(HValue::kCanOverflow); | 1934 map_index->ClearFlag(HValue::kCanOverflow); |
1961 HValue* key_index = AddUncasted<HAdd>( | 1935 HValue* key_index = AddUncasted<HAdd>( |
1962 base_index, | 1936 base_index, |
1963 Add<HConstant>(probe_base + KeyedLookupCache::kKeyIndex)); | 1937 Add<HConstant>(probe_base + KeyedLookupCache::kKeyIndex)); |
1964 key_index->ClearFlag(HValue::kCanOverflow); | 1938 key_index->ClearFlag(HValue::kCanOverflow); |
1965 HValue* map_to_check = | 1939 HValue* map_to_check = |
1966 Add<HLoadKeyed>(cache_keys, map_index, static_cast<HValue*>(NULL), | 1940 Add<HLoadKeyed>(cache_keys, map_index, nullptr, FAST_ELEMENTS, |
1967 FAST_ELEMENTS, NEVER_RETURN_HOLE, 0); | 1941 NEVER_RETURN_HOLE, 0); |
1968 lookup_if->If<HCompareObjectEqAndBranch>(map_to_check, map); | 1942 lookup_if->If<HCompareObjectEqAndBranch>(map_to_check, map); |
1969 lookup_if->And(); | 1943 lookup_if->And(); |
1970 HValue* key_to_check = | 1944 HValue* key_to_check = |
1971 Add<HLoadKeyed>(cache_keys, key_index, static_cast<HValue*>(NULL), | 1945 Add<HLoadKeyed>(cache_keys, key_index, nullptr, FAST_ELEMENTS, |
1972 FAST_ELEMENTS, NEVER_RETURN_HOLE, 0); | 1946 NEVER_RETURN_HOLE, 0); |
1973 lookup_if->If<HCompareObjectEqAndBranch>(key_to_check, key); | 1947 lookup_if->If<HCompareObjectEqAndBranch>(key_to_check, key); |
1974 lookup_if->Then(); | 1948 lookup_if->Then(); |
1975 { | 1949 { |
1976 ExternalReference cache_field_offsets_ref = | 1950 ExternalReference cache_field_offsets_ref = |
1977 ExternalReference::keyed_lookup_cache_field_offsets(isolate()); | 1951 ExternalReference::keyed_lookup_cache_field_offsets(isolate()); |
1978 HValue* cache_field_offsets = | 1952 HValue* cache_field_offsets = |
1979 Add<HConstant>(cache_field_offsets_ref); | 1953 Add<HConstant>(cache_field_offsets_ref); |
1980 HValue* index = AddUncasted<HAdd>(hash, Add<HConstant>(probe)); | 1954 HValue* index = AddUncasted<HAdd>(hash, Add<HConstant>(probe)); |
1981 index->ClearFlag(HValue::kCanOverflow); | 1955 index->ClearFlag(HValue::kCanOverflow); |
1982 HValue* property_index = Add<HLoadKeyed>( | 1956 HValue* property_index = |
1983 cache_field_offsets, index, static_cast<HValue*>(NULL), | 1957 Add<HLoadKeyed>(cache_field_offsets, index, nullptr, |
1984 EXTERNAL_INT32_ELEMENTS, NEVER_RETURN_HOLE, 0); | 1958 EXTERNAL_INT32_ELEMENTS, NEVER_RETURN_HOLE, 0); |
1985 Push(property_index); | 1959 Push(property_index); |
1986 } | 1960 } |
1987 lookup_if->Else(); | 1961 lookup_if->Else(); |
1988 } | 1962 } |
1989 for (int i = 0; i < KeyedLookupCache::kEntriesPerBucket; ++i) { | 1963 for (int i = 0; i < KeyedLookupCache::kEntriesPerBucket; ++i) { |
1990 lookup_ifs[i].JoinContinuation(&inline_or_runtime_continuation); | 1964 lookup_ifs[i].JoinContinuation(&inline_or_runtime_continuation); |
1991 } | 1965 } |
1992 } | 1966 } |
1993 | 1967 |
1994 IfBuilder inline_or_runtime(this, &inline_or_runtime_continuation); | 1968 IfBuilder inline_or_runtime(this, &inline_or_runtime_continuation); |
(...skipping 25 matching lines...) Expand all Loading... |
2020 } | 1994 } |
2021 | 1995 |
2022 | 1996 |
2023 void CodeStubGraphBuilderBase::TailCallHandler(HValue* receiver, HValue* name, | 1997 void CodeStubGraphBuilderBase::TailCallHandler(HValue* receiver, HValue* name, |
2024 HValue* array, HValue* map_index, | 1998 HValue* array, HValue* map_index, |
2025 HValue* slot, HValue* vector) { | 1999 HValue* slot, HValue* vector) { |
2026 // The handler is at array[map_index + 1]. Compute this with a custom offset | 2000 // The handler is at array[map_index + 1]. Compute this with a custom offset |
2027 // to HLoadKeyed. | 2001 // to HLoadKeyed. |
2028 int offset = | 2002 int offset = |
2029 GetDefaultHeaderSizeForElementsKind(FAST_ELEMENTS) + kPointerSize; | 2003 GetDefaultHeaderSizeForElementsKind(FAST_ELEMENTS) + kPointerSize; |
2030 HValue* handler_code = | 2004 HValue* handler_code = Add<HLoadKeyed>( |
2031 Add<HLoadKeyed>(array, map_index, static_cast<HValue*>(NULL), | 2005 array, map_index, nullptr, FAST_ELEMENTS, NEVER_RETURN_HOLE, offset); |
2032 FAST_ELEMENTS, NEVER_RETURN_HOLE, offset); | |
2033 TailCallHandler(receiver, name, slot, vector, handler_code); | 2006 TailCallHandler(receiver, name, slot, vector, handler_code); |
2034 } | 2007 } |
2035 | 2008 |
2036 | 2009 |
2037 void CodeStubGraphBuilderBase::TailCallHandler(HValue* receiver, HValue* name, | 2010 void CodeStubGraphBuilderBase::TailCallHandler(HValue* receiver, HValue* name, |
2038 HValue* slot, HValue* vector, | 2011 HValue* slot, HValue* vector, |
2039 HValue* handler_code) { | 2012 HValue* handler_code) { |
2040 VectorLoadICDescriptor descriptor(isolate()); | 2013 VectorLoadICDescriptor descriptor(isolate()); |
2041 HValue* op_vals[] = {context(), receiver, name, slot, vector}; | 2014 HValue* op_vals[] = {context(), receiver, name, slot, vector}; |
2042 Add<HCallWithDescriptor>(handler_code, 0, descriptor, | 2015 Add<HCallWithDescriptor>(handler_code, 0, descriptor, |
(...skipping 17 matching lines...) Expand all Loading... |
2060 HValue* name, HValue* slot, | 2033 HValue* name, HValue* slot, |
2061 HValue* vector, | 2034 HValue* vector, |
2062 bool keyed_load) { | 2035 bool keyed_load) { |
2063 IfBuilder if_receiver_heap_object(this); | 2036 IfBuilder if_receiver_heap_object(this); |
2064 if_receiver_heap_object.IfNot<HIsSmiAndBranch>(receiver); | 2037 if_receiver_heap_object.IfNot<HIsSmiAndBranch>(receiver); |
2065 if_receiver_heap_object.Then(); | 2038 if_receiver_heap_object.Then(); |
2066 { | 2039 { |
2067 HConstant* constant_two = Add<HConstant>(2); | 2040 HConstant* constant_two = Add<HConstant>(2); |
2068 HConstant* constant_three = Add<HConstant>(3); | 2041 HConstant* constant_three = Add<HConstant>(3); |
2069 | 2042 |
2070 HValue* receiver_map = AddLoadMap(receiver, static_cast<HValue*>(NULL)); | 2043 HValue* receiver_map = AddLoadMap(receiver, nullptr); |
2071 HValue* start = | 2044 HValue* start = |
2072 keyed_load ? graph()->GetConstant1() : graph()->GetConstant0(); | 2045 keyed_load ? graph()->GetConstant1() : graph()->GetConstant0(); |
2073 HValue* array_map = | 2046 HValue* array_map = Add<HLoadKeyed>(array, start, nullptr, FAST_ELEMENTS, |
2074 Add<HLoadKeyed>(array, start, static_cast<HValue*>(NULL), FAST_ELEMENTS, | 2047 ALLOW_RETURN_HOLE); |
2075 ALLOW_RETURN_HOLE); | |
2076 IfBuilder if_correct_map(this); | 2048 IfBuilder if_correct_map(this); |
2077 if_correct_map.If<HCompareObjectEqAndBranch>(receiver_map, array_map); | 2049 if_correct_map.If<HCompareObjectEqAndBranch>(receiver_map, array_map); |
2078 if_correct_map.Then(); | 2050 if_correct_map.Then(); |
2079 { TailCallHandler(receiver, name, array, start, slot, vector); } | 2051 { TailCallHandler(receiver, name, array, start, slot, vector); } |
2080 if_correct_map.Else(); | 2052 if_correct_map.Else(); |
2081 { | 2053 { |
2082 // If our array has more elements, the ic is polymorphic. Look for the | 2054 // If our array has more elements, the ic is polymorphic. Look for the |
2083 // receiver map in the rest of the array. | 2055 // receiver map in the rest of the array. |
2084 HValue* length = | 2056 HValue* length = AddLoadFixedArrayLength(array, nullptr); |
2085 AddLoadFixedArrayLength(array, static_cast<HValue*>(NULL)); | |
2086 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement, | 2057 LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement, |
2087 constant_two); | 2058 constant_two); |
2088 start = keyed_load ? constant_three : constant_two; | 2059 start = keyed_load ? constant_three : constant_two; |
2089 HValue* key = builder.BeginBody(start, length, Token::LT); | 2060 HValue* key = builder.BeginBody(start, length, Token::LT); |
2090 { | 2061 { |
2091 HValue* array_map = | 2062 HValue* array_map = Add<HLoadKeyed>(array, key, nullptr, FAST_ELEMENTS, |
2092 Add<HLoadKeyed>(array, key, static_cast<HValue*>(NULL), | 2063 ALLOW_RETURN_HOLE); |
2093 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | |
2094 IfBuilder if_correct_poly_map(this); | 2064 IfBuilder if_correct_poly_map(this); |
2095 if_correct_poly_map.If<HCompareObjectEqAndBranch>(receiver_map, | 2065 if_correct_poly_map.If<HCompareObjectEqAndBranch>(receiver_map, |
2096 array_map); | 2066 array_map); |
2097 if_correct_poly_map.Then(); | 2067 if_correct_poly_map.Then(); |
2098 { TailCallHandler(receiver, name, array, key, slot, vector); } | 2068 { TailCallHandler(receiver, name, array, key, slot, vector); } |
2099 } | 2069 } |
2100 builder.EndBody(); | 2070 builder.EndBody(); |
2101 } | 2071 } |
2102 if_correct_map.End(); | 2072 if_correct_map.End(); |
2103 } | 2073 } |
2104 } | 2074 } |
2105 | 2075 |
2106 | 2076 |
2107 template <> | 2077 template <> |
2108 HValue* CodeStubGraphBuilder<VectorLoadStub>::BuildCodeStub() { | 2078 HValue* CodeStubGraphBuilder<VectorLoadStub>::BuildCodeStub() { |
2109 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | 2079 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); |
2110 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); | 2080 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); |
2111 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); | 2081 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); |
2112 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); | 2082 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); |
2113 | 2083 |
2114 // If the feedback is an array, then the IC is in the monomorphic or | 2084 // If the feedback is an array, then the IC is in the monomorphic or |
2115 // polymorphic state. | 2085 // polymorphic state. |
2116 HValue* feedback = Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), | 2086 HValue* feedback = |
2117 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | 2087 Add<HLoadKeyed>(vector, slot, nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
2118 IfBuilder array_checker(this); | 2088 IfBuilder array_checker(this); |
2119 array_checker.If<HCompareMap>(feedback, | 2089 array_checker.If<HCompareMap>(feedback, |
2120 isolate()->factory()->fixed_array_map()); | 2090 isolate()->factory()->fixed_array_map()); |
2121 array_checker.Then(); | 2091 array_checker.Then(); |
2122 { HandleArrayCases(feedback, receiver, name, slot, vector, false); } | 2092 { HandleArrayCases(feedback, receiver, name, slot, vector, false); } |
2123 array_checker.Else(); | 2093 array_checker.Else(); |
2124 { | 2094 { |
2125 // Is the IC megamorphic? | 2095 // Is the IC megamorphic? |
2126 IfBuilder mega_checker(this); | 2096 IfBuilder mega_checker(this); |
2127 HConstant* megamorphic_symbol = | 2097 HConstant* megamorphic_symbol = |
(...skipping 21 matching lines...) Expand all Loading... |
2149 template <> | 2119 template <> |
2150 HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() { | 2120 HValue* CodeStubGraphBuilder<VectorKeyedLoadStub>::BuildCodeStub() { |
2151 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); | 2121 HValue* receiver = GetParameter(VectorLoadICDescriptor::kReceiverIndex); |
2152 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); | 2122 HValue* name = GetParameter(VectorLoadICDescriptor::kNameIndex); |
2153 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); | 2123 HValue* slot = GetParameter(VectorLoadICDescriptor::kSlotIndex); |
2154 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); | 2124 HValue* vector = GetParameter(VectorLoadICDescriptor::kVectorIndex); |
2155 HConstant* zero = graph()->GetConstant0(); | 2125 HConstant* zero = graph()->GetConstant0(); |
2156 | 2126 |
2157 // If the feedback is an array, then the IC is in the monomorphic or | 2127 // If the feedback is an array, then the IC is in the monomorphic or |
2158 // polymorphic state. | 2128 // polymorphic state. |
2159 HValue* feedback = Add<HLoadKeyed>(vector, slot, static_cast<HValue*>(NULL), | 2129 HValue* feedback = |
2160 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | 2130 Add<HLoadKeyed>(vector, slot, nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
2161 IfBuilder array_checker(this); | 2131 IfBuilder array_checker(this); |
2162 array_checker.If<HCompareMap>(feedback, | 2132 array_checker.If<HCompareMap>(feedback, |
2163 isolate()->factory()->fixed_array_map()); | 2133 isolate()->factory()->fixed_array_map()); |
2164 array_checker.Then(); | 2134 array_checker.Then(); |
2165 { | 2135 { |
2166 // If feedback[0] is 0, then the IC has element handlers and name should be | 2136 // If feedback[0] is 0, then the IC has element handlers and name should be |
2167 // a smi. If feedback[0] is a string, verify that it matches name. | 2137 // a smi. If feedback[0] is a string, verify that it matches name. |
2168 HValue* recorded_name = | 2138 HValue* recorded_name = Add<HLoadKeyed>(feedback, zero, nullptr, |
2169 Add<HLoadKeyed>(feedback, zero, static_cast<HValue*>(NULL), | 2139 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
2170 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | |
2171 | 2140 |
2172 IfBuilder recorded_name_is_zero(this); | 2141 IfBuilder recorded_name_is_zero(this); |
2173 recorded_name_is_zero.If<HCompareObjectEqAndBranch>(recorded_name, zero); | 2142 recorded_name_is_zero.If<HCompareObjectEqAndBranch>(recorded_name, zero); |
2174 recorded_name_is_zero.Then(); | 2143 recorded_name_is_zero.Then(); |
2175 { Add<HCheckSmi>(name); } | 2144 { Add<HCheckSmi>(name); } |
2176 recorded_name_is_zero.Else(); | 2145 recorded_name_is_zero.Else(); |
2177 { | 2146 { |
2178 IfBuilder strings_match(this); | 2147 IfBuilder strings_match(this); |
2179 strings_match.IfNot<HCompareObjectEqAndBranch>(name, recorded_name); | 2148 strings_match.IfNot<HCompareObjectEqAndBranch>(name, recorded_name); |
2180 strings_match.Then(); | 2149 strings_match.Then(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2231 // megamorphic case is handled as part of the default stub. | 2200 // megamorphic case is handled as part of the default stub. |
2232 DCHECK(!FLAG_vector_ics); | 2201 DCHECK(!FLAG_vector_ics); |
2233 | 2202 |
2234 // Probe the stub cache. | 2203 // Probe the stub cache. |
2235 Add<HTailCallThroughMegamorphicCache>(receiver, name); | 2204 Add<HTailCallThroughMegamorphicCache>(receiver, name); |
2236 | 2205 |
2237 // We never continue. | 2206 // We never continue. |
2238 return graph()->GetConstant0(); | 2207 return graph()->GetConstant0(); |
2239 } | 2208 } |
2240 } } // namespace v8::internal | 2209 } } // namespace v8::internal |
OLD | NEW |