Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 } | 93 } |
| 94 | 94 |
| 95 ~ArrayContextChecker() { | 95 ~ArrayContextChecker() { |
| 96 checker_.ElseDeopt(); | 96 checker_.ElseDeopt(); |
| 97 checker_.End(); | 97 checker_.End(); |
| 98 } | 98 } |
| 99 private: | 99 private: |
| 100 IfBuilder checker_; | 100 IfBuilder checker_; |
| 101 }; | 101 }; |
| 102 | 102 |
| 103 enum ArgumentClass { | |
| 104 NONE, | |
| 105 SINGLE, | |
| 106 MULTIPLE | |
| 107 }; | |
| 108 | |
| 109 HValue* BuildArrayConstructor(ElementsKind kind, AllocationSiteMode mode, | |
| 110 ArgumentClass argument_class); | |
| 111 HValue* BuildInternalArrayConstructor(ElementsKind kind, | |
| 112 ArgumentClass argument_class); | |
| 113 | |
| 103 private: | 114 private: |
| 115 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); | |
| 116 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, | |
| 117 ElementsKind kind); | |
| 118 | |
| 104 SmartArrayPointer<HParameter*> parameters_; | 119 SmartArrayPointer<HParameter*> parameters_; |
| 105 HValue* arguments_length_; | 120 HValue* arguments_length_; |
| 106 CompilationInfoWithZone info_; | 121 CompilationInfoWithZone info_; |
| 107 CodeStubInterfaceDescriptor* descriptor_; | 122 CodeStubInterfaceDescriptor* descriptor_; |
| 108 HContext* context_; | 123 HContext* context_; |
| 109 }; | 124 }; |
| 110 | 125 |
| 111 | 126 |
| 112 bool CodeStubGraphBuilderBase::BuildGraph() { | 127 bool CodeStubGraphBuilderBase::BuildGraph() { |
| 113 // Update the static counter each time a new code stub is generated. | 128 // Update the static counter each time a new code stub is generated. |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 Representation::Tagged(), | 544 Representation::Tagged(), |
| 530 JSArray::kMapOffset)); | 545 JSArray::kMapOffset)); |
| 531 return js_array; | 546 return js_array; |
| 532 } | 547 } |
| 533 | 548 |
| 534 | 549 |
| 535 Handle<Code> TransitionElementsKindStub::GenerateCode() { | 550 Handle<Code> TransitionElementsKindStub::GenerateCode() { |
| 536 return DoGenerateCode(this); | 551 return DoGenerateCode(this); |
| 537 } | 552 } |
| 538 | 553 |
| 554 HValue* CodeStubGraphBuilderBase::BuildArrayConstructor( | |
| 555 ElementsKind kind, AllocationSiteMode mode, | |
| 556 ArgumentClass argument_class) { | |
| 557 HValue* constructor = GetParameter(ArrayConstructorStubBase::kConstructor); | |
| 558 HValue* property_cell = GetParameter(ArrayConstructorStubBase::kPropertyCell); | |
| 559 HInstruction* array_function = BuildGetArrayFunction(context()); | |
| 560 ArrayContextChecker(this, constructor, array_function); | |
| 561 JSArrayBuilder array_builder(this, kind, property_cell, mode); | |
| 539 | 562 |
| 540 template <> | 563 if (argument_class == NONE) { |
|
Michael Starzinger
2013/05/23 09:16:49
Can we model that as a switch without a default ca
mvstanton
2013/05/23 14:46:05
Cool, didn't think about that good trick. Done.
| |
| 541 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() { | 564 return array_builder.AllocateEmptyArray(); |
| 542 // ----------- S t a t e ------------- | 565 } else if (argument_class == SINGLE) { |
| 543 // -- Parameter 1 : type info cell | 566 return BuildArraySingleArgumentConstructor(&array_builder); |
| 544 // -- Parameter 0 : constructor | 567 } |
| 545 // ----------------------------------- | 568 |
| 546 HInstruction* array_function = BuildGetArrayFunction(context()); | 569 ASSERT(argument_class == MULTIPLE); |
| 547 ArrayContextChecker(this, | 570 return BuildArrayNArgumentsConstructor(&array_builder, kind); |
| 548 GetParameter(ArrayConstructorStubBase::kConstructor), | |
| 549 array_function); | |
| 550 // Get the right map | |
| 551 // Should be a constant | |
| 552 JSArrayBuilder array_builder( | |
| 553 this, | |
| 554 casted_stub()->elements_kind(), | |
| 555 GetParameter(ArrayConstructorStubBase::kPropertyCell), | |
| 556 casted_stub()->mode()); | |
| 557 return array_builder.AllocateEmptyArray(); | |
| 558 } | 571 } |
| 559 | 572 |
| 560 | 573 |
| 561 Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() { | 574 HValue* CodeStubGraphBuilderBase::BuildInternalArrayConstructor( |
| 562 return DoGenerateCode(this); | 575 ElementsKind kind, ArgumentClass argument_class) { |
| 576 HValue* constructor = GetParameter( | |
| 577 InternalArrayConstructorStubBase::kConstructor); | |
| 578 JSArrayBuilder array_builder(this, kind, constructor); | |
| 579 | |
| 580 if (argument_class == NONE) { | |
|
Michael Starzinger
2013/05/23 09:16:49
Likewise.
mvstanton
2013/05/23 14:46:05
Done.
| |
| 581 return array_builder.AllocateEmptyArray(); | |
| 582 } else if (argument_class == SINGLE) { | |
| 583 return BuildArraySingleArgumentConstructor(&array_builder); | |
| 584 } | |
| 585 | |
| 586 ASSERT(argument_class == MULTIPLE); | |
| 587 return BuildArrayNArgumentsConstructor(&array_builder, kind); | |
| 563 } | 588 } |
| 564 | 589 |
| 565 | 590 |
| 566 template <> | 591 HValue* CodeStubGraphBuilderBase::BuildArraySingleArgumentConstructor( |
| 567 HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>:: | 592 JSArrayBuilder* array_builder) { |
| 568 BuildCodeStub() { | |
| 569 HInstruction* array_function = BuildGetArrayFunction(context()); | |
| 570 ArrayContextChecker(this, | |
| 571 GetParameter(ArrayConstructorStubBase::kConstructor), | |
| 572 array_function); | |
| 573 // Smi check and range check on the input arg. | 593 // Smi check and range check on the input arg. |
| 574 HValue* constant_one = graph()->GetConstant1(); | 594 HValue* constant_one = graph()->GetConstant1(); |
| 575 HValue* constant_zero = graph()->GetConstant0(); | 595 HValue* constant_zero = graph()->GetConstant0(); |
| 576 | 596 |
| 577 HInstruction* elements = AddInstruction( | 597 HInstruction* elements = AddInstruction( |
| 578 new(zone()) HArgumentsElements(false)); | 598 new(zone()) HArgumentsElements(false)); |
| 579 HInstruction* argument = AddInstruction( | 599 HInstruction* argument = AddInstruction( |
| 580 new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero)); | 600 new(zone()) HAccessArgumentsAt(elements, constant_one, constant_zero)); |
| 581 | 601 |
| 582 HConstant* max_alloc_length = | 602 HConstant* max_alloc_length = |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 599 Push(initial_capacity_node); // capacity | 619 Push(initial_capacity_node); // capacity |
| 600 Push(constant_zero); // length | 620 Push(constant_zero); // length |
| 601 if_builder.Else(); | 621 if_builder.Else(); |
| 602 Push(checked_arg); // capacity | 622 Push(checked_arg); // capacity |
| 603 Push(checked_arg); // length | 623 Push(checked_arg); // length |
| 604 if_builder.End(); | 624 if_builder.End(); |
| 605 | 625 |
| 606 // Figure out total size | 626 // Figure out total size |
| 607 HValue* length = Pop(); | 627 HValue* length = Pop(); |
| 608 HValue* capacity = Pop(); | 628 HValue* capacity = Pop(); |
| 609 | 629 return array_builder->AllocateArray(capacity, length, true); |
| 610 JSArrayBuilder array_builder( | |
| 611 this, | |
| 612 casted_stub()->elements_kind(), | |
| 613 GetParameter(ArrayConstructorStubBase::kPropertyCell), | |
| 614 casted_stub()->mode()); | |
| 615 return array_builder.AllocateArray(capacity, length, true); | |
| 616 } | 630 } |
| 617 | 631 |
| 618 | 632 |
| 619 Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() { | 633 HValue* CodeStubGraphBuilderBase::BuildArrayNArgumentsConstructor( |
| 620 return DoGenerateCode(this); | 634 JSArrayBuilder* array_builder, ElementsKind kind) { |
| 621 } | |
| 622 | |
| 623 | |
| 624 template <> | |
| 625 HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() { | |
| 626 HInstruction* array_function = BuildGetArrayFunction(context()); | |
| 627 ArrayContextChecker(this, | |
| 628 GetParameter(ArrayConstructorStubBase::kConstructor), | |
| 629 array_function); | |
| 630 ElementsKind kind = casted_stub()->elements_kind(); | |
| 631 HValue* length = GetArgumentsLength(); | |
| 632 | |
| 633 JSArrayBuilder array_builder( | |
| 634 this, | |
| 635 kind, | |
| 636 GetParameter(ArrayConstructorStubBase::kPropertyCell), | |
| 637 casted_stub()->mode()); | |
| 638 | |
| 639 // We need to fill with the hole if it's a smi array in the multi-argument | 635 // We need to fill with the hole if it's a smi array in the multi-argument |
| 640 // case because we might have to bail out while copying arguments into | 636 // case because we might have to bail out while copying arguments into |
| 641 // the array because they aren't compatible with a smi array. | 637 // the array because they aren't compatible with a smi array. |
| 642 // If it's a double array, no problem, and if it's fast then no | 638 // If it's a double array, no problem, and if it's fast then no |
| 643 // problem either because doubles are boxed. | 639 // problem either because doubles are boxed. |
| 640 HValue* length = GetArgumentsLength(); | |
| 644 bool fill_with_hole = IsFastSmiElementsKind(kind); | 641 bool fill_with_hole = IsFastSmiElementsKind(kind); |
| 645 HValue* new_object = array_builder.AllocateArray(length, | 642 HValue* new_object = array_builder->AllocateArray(length, |
| 646 length, | 643 length, |
| 647 fill_with_hole); | 644 fill_with_hole); |
| 648 HValue* elements = array_builder.GetElementsLocation(); | 645 HValue* elements = array_builder->GetElementsLocation(); |
| 649 ASSERT(elements != NULL); | 646 ASSERT(elements != NULL); |
| 650 | 647 |
| 651 // Now populate the elements correctly. | 648 // Now populate the elements correctly. |
| 652 LoopBuilder builder(this, | 649 LoopBuilder builder(this, |
| 653 context(), | 650 context(), |
| 654 LoopBuilder::kPostIncrement); | 651 LoopBuilder::kPostIncrement); |
| 655 HValue* start = graph()->GetConstant0(); | 652 HValue* start = graph()->GetConstant0(); |
| 656 HValue* key = builder.BeginBody(start, length, Token::LT); | 653 HValue* key = builder.BeginBody(start, length, Token::LT); |
| 657 HInstruction* argument_elements = AddInstruction( | 654 HInstruction* argument_elements = AddInstruction( |
| 658 new(zone()) HArgumentsElements(false)); | 655 new(zone()) HArgumentsElements(false)); |
| 659 HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt( | 656 HInstruction* argument = AddInstruction(new(zone()) HAccessArgumentsAt( |
| 660 argument_elements, length, key)); | 657 argument_elements, length, key)); |
| 661 | 658 |
| 662 // Checks to prevent incompatible stores | 659 // Checks to prevent incompatible stores |
| 663 if (IsFastSmiElementsKind(kind)) { | 660 if (IsFastSmiElementsKind(kind)) { |
| 664 AddInstruction(new(zone()) HCheckSmi(argument)); | 661 AddInstruction(new(zone()) HCheckSmi(argument)); |
| 665 } | 662 } |
| 666 | 663 |
| 667 AddInstruction(new(zone()) HStoreKeyed(elements, key, argument, kind)); | 664 AddInstruction(new(zone()) HStoreKeyed(elements, key, argument, kind)); |
| 668 builder.EndBody(); | 665 builder.EndBody(); |
| 669 return new_object; | 666 return new_object; |
| 670 } | 667 } |
| 671 | 668 |
| 672 | 669 |
| 670 template <> | |
| 671 HValue* CodeStubGraphBuilder<ArrayNoArgumentConstructorStub>::BuildCodeStub() { | |
| 672 ElementsKind kind = casted_stub()->elements_kind(); | |
| 673 AllocationSiteMode mode = casted_stub()->mode(); | |
| 674 return BuildArrayConstructor(kind, mode, NONE); | |
| 675 } | |
| 676 | |
| 677 | |
| 678 Handle<Code> ArrayNoArgumentConstructorStub::GenerateCode() { | |
| 679 return DoGenerateCode(this); | |
| 680 } | |
| 681 | |
| 682 | |
| 683 template <> | |
| 684 HValue* CodeStubGraphBuilder<ArraySingleArgumentConstructorStub>:: | |
| 685 BuildCodeStub() { | |
| 686 ElementsKind kind = casted_stub()->elements_kind(); | |
| 687 AllocationSiteMode mode = casted_stub()->mode(); | |
| 688 return BuildArrayConstructor(kind, mode, SINGLE); | |
| 689 } | |
| 690 | |
| 691 | |
| 692 Handle<Code> ArraySingleArgumentConstructorStub::GenerateCode() { | |
| 693 return DoGenerateCode(this); | |
| 694 } | |
| 695 | |
| 696 | |
| 697 template <> | |
| 698 HValue* CodeStubGraphBuilder<ArrayNArgumentsConstructorStub>::BuildCodeStub() { | |
| 699 ElementsKind kind = casted_stub()->elements_kind(); | |
| 700 AllocationSiteMode mode = casted_stub()->mode(); | |
| 701 return BuildArrayConstructor(kind, mode, MULTIPLE); | |
| 702 } | |
| 703 | |
| 704 | |
| 673 Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() { | 705 Handle<Code> ArrayNArgumentsConstructorStub::GenerateCode() { |
| 674 return DoGenerateCode(this); | 706 return DoGenerateCode(this); |
| 675 } | 707 } |
| 676 | 708 |
| 677 | 709 |
| 678 template <> | 710 template <> |
| 711 HValue* CodeStubGraphBuilder<InternalArrayNoArgumentConstructorStub>:: | |
| 712 BuildCodeStub() { | |
| 713 ElementsKind kind = casted_stub()->elements_kind(); | |
| 714 return BuildInternalArrayConstructor(kind, NONE); | |
| 715 } | |
| 716 | |
| 717 | |
| 718 Handle<Code> InternalArrayNoArgumentConstructorStub::GenerateCode() { | |
| 719 return DoGenerateCode(this); | |
| 720 } | |
| 721 | |
| 722 | |
| 723 template <> | |
| 724 HValue* CodeStubGraphBuilder<InternalArraySingleArgumentConstructorStub>:: | |
| 725 BuildCodeStub() { | |
| 726 ElementsKind kind = casted_stub()->elements_kind(); | |
| 727 return BuildInternalArrayConstructor(kind, SINGLE); | |
| 728 } | |
| 729 | |
| 730 | |
| 731 Handle<Code> InternalArraySingleArgumentConstructorStub::GenerateCode() { | |
| 732 return DoGenerateCode(this); | |
| 733 } | |
| 734 | |
| 735 | |
| 736 template <> | |
| 737 HValue* CodeStubGraphBuilder<InternalArrayNArgumentsConstructorStub>:: | |
| 738 BuildCodeStub() { | |
| 739 ElementsKind kind = casted_stub()->elements_kind(); | |
| 740 return BuildInternalArrayConstructor(kind, MULTIPLE); | |
| 741 } | |
| 742 | |
| 743 | |
| 744 Handle<Code> InternalArrayNArgumentsConstructorStub::GenerateCode() { | |
| 745 return DoGenerateCode(this); | |
| 746 } | |
| 747 | |
| 748 | |
| 749 template <> | |
| 679 HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeUninitializedStub() { | 750 HValue* CodeStubGraphBuilder<CompareNilICStub>::BuildCodeUninitializedStub() { |
| 680 CompareNilICStub* stub = casted_stub(); | 751 CompareNilICStub* stub = casted_stub(); |
| 681 HIfContinuation continuation; | 752 HIfContinuation continuation; |
| 682 Handle<Map> sentinel_map(graph()->isolate()->heap()->meta_map()); | 753 Handle<Map> sentinel_map(graph()->isolate()->heap()->meta_map()); |
| 683 BuildCompareNil(GetParameter(0), stub->GetKind(), | 754 BuildCompareNil(GetParameter(0), stub->GetKind(), |
| 684 stub->GetTypes(), sentinel_map, | 755 stub->GetTypes(), sentinel_map, |
| 685 RelocInfo::kNoPosition, &continuation); | 756 RelocInfo::kNoPosition, &continuation); |
| 686 IfBuilder if_nil(this, &continuation); | 757 IfBuilder if_nil(this, &continuation); |
| 687 if_nil.Then(); | 758 if_nil.Then(); |
| 688 if (continuation.IsFalseReachable()) { | 759 if (continuation.IsFalseReachable()) { |
| 689 if_nil.Else(); | 760 if_nil.Else(); |
| 690 if_nil.Return(graph()->GetConstantSmi0()); | 761 if_nil.Return(graph()->GetConstantSmi0()); |
| 691 } | 762 } |
| 692 if_nil.End(); | 763 if_nil.End(); |
| 693 return continuation.IsTrueReachable() | 764 return continuation.IsTrueReachable() |
| 694 ? graph()->GetConstantSmi1() | 765 ? graph()->GetConstantSmi1() |
| 695 : graph()->GetConstantUndefined(); | 766 : graph()->GetConstantUndefined(); |
| 696 } | 767 } |
| 697 | 768 |
| 698 | 769 |
| 699 Handle<Code> CompareNilICStub::GenerateCode() { | 770 Handle<Code> CompareNilICStub::GenerateCode() { |
| 700 return DoGenerateCode(this); | 771 return DoGenerateCode(this); |
| 701 } | 772 } |
| 702 | 773 |
| 703 } } // namespace v8::internal | 774 } } // namespace v8::internal |
| OLD | NEW |