Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/builtins/builtins.h" | 5 #include "src/builtins/builtins.h" |
| 6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
| 7 | 7 |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| (...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 } | 574 } |
| 575 | 575 |
| 576 a->Bind(&out); | 576 a->Bind(&out); |
| 577 { | 577 { |
| 578 Node* result = | 578 Node* result = |
| 579 a->SubString(context, string, var_start.value(), var_end.value()); | 579 a->SubString(context, string, var_start.value(), var_end.value()); |
| 580 a->Return(result); | 580 a->Return(result); |
| 581 } | 581 } |
| 582 } | 582 } |
| 583 | 583 |
| 584 // ES6 section B.2.3.1 String.prototype.substr ( start, length ) | |
| 585 void Builtins::Generate_StringPrototypeSubstr(CodeStubAssembler* a) { | |
| 586 typedef CodeStubAssembler::Label Label; | |
| 587 typedef compiler::Node Node; | |
| 588 typedef CodeStubAssembler::Variable Variable; | |
| 589 | |
| 590 Label out(a), handle_length(a); | |
| 591 | |
| 592 Variable var_start(a, MachineRepresentation::kTagged); | |
| 593 Variable var_length(a, MachineRepresentation::kTagged); | |
| 594 | |
| 595 Node* const receiver = a->Parameter(0); | |
| 596 Node* const start = a->Parameter(1); | |
| 597 Node* const length = a->Parameter(2); | |
| 598 Node* const context = a->Parameter(5); | |
| 599 | |
| 600 // Check that {receiver} is coercible to Object and convert it to a String. | |
| 601 Node* const string = | |
| 602 a->ToThisString(context, receiver, "String.prototype.substr"); | |
| 603 | |
| 604 Node* const string_length = a->LoadStringLength(string); | |
| 605 | |
| 606 // Conversions and bounds-checks for {start}. | |
| 607 { | |
| 608 Node* const start_int = | |
| 609 a->ToInteger(context, start, CodeStubAssembler::kTruncateMinusZero); | |
| 610 | |
| 611 Label if_issmi(a), if_isheapnumber(a, Label::kDeferred); | |
| 612 a->Branch(a->WordIsSmi(start_int), &if_issmi, &if_isheapnumber); | |
| 613 | |
| 614 a->Bind(&if_issmi); | |
| 615 { | |
| 616 Node* const zero = a->SmiConstant(Smi::FromInt(0)); | |
| 617 Node* const length_plus_start = a->SmiAdd(string_length, start_int); | |
| 618 var_start.Bind(a->Select(a->SmiLessThan(start_int, zero), | |
| 619 a->SmiMax(length_plus_start, zero), start_int)); | |
| 620 a->Goto(&handle_length); | |
| 621 } | |
| 622 | |
| 623 a->Bind(&if_isheapnumber); | |
| 624 { | |
| 625 Node* result = a->CallRuntime(Runtime::kThrowIllegalOperation, context); | |
|
Igor Sheludko
2016/09/27 12:15:06
String.prototype.substr should not throw. I guess
jgruber
2016/09/29 07:48:49
Thanks, good catch! Modified this to set var_start
| |
| 626 a->DebugBreak(); // Unreachable. | |
| 627 a->Return(result); | |
| 628 } | |
| 629 } | |
| 630 | |
| 631 // Conversions and bounds-checks for {length}. | |
| 632 a->Bind(&handle_length); | |
| 633 { | |
| 634 // Default to {string_length} if {length} is undefined. | |
| 635 { | |
| 636 Node* const length_int = | |
| 637 a->ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero); | |
| 638 var_length.Bind(a->Select(a->WordEqual(length, a->UndefinedConstant()), | |
| 639 string_length, length_int)); | |
| 640 } | |
| 641 | |
| 642 Label if_issmi(a), if_isheapnumber(a, Label::kDeferred); | |
| 643 a->Branch(a->WordIsSmi(var_length.value()), &if_issmi, &if_isheapnumber); | |
| 644 | |
| 645 // Set {length} to min(max({length}, 0), {string_length} - {start} | |
| 646 a->Bind(&if_issmi); | |
| 647 { | |
| 648 Node* const zero = a->SmiConstant(Smi::FromInt(0)); | |
| 649 Node* const positive_length = a->SmiMax(var_length.value(), zero); | |
| 650 | |
| 651 Node* const minimal_length = a->SmiSub(string_length, var_start.value()); | |
| 652 var_length.Bind(a->SmiMin(positive_length, minimal_length)); | |
| 653 | |
| 654 a->GotoUnless(a->SmiLessThanOrEqual(var_length.value(), zero), &out); | |
| 655 a->Return(a->EmptyStringConstant()); | |
| 656 } | |
| 657 | |
| 658 a->Bind(&if_isheapnumber); | |
| 659 { | |
| 660 // If {length} is a heap number, it is definitely out of bounds. There are | |
| 661 // two cases according to the spec: if it is negative, "" is returned; if | |
| 662 // it is positive, then length is set to {string_length} - {start}. | |
| 663 | |
| 664 a->Assert(a->WordEqual(a->LoadMap(var_length.value()), | |
| 665 a->HeapNumberMapConstant())); | |
| 666 | |
| 667 Label if_isnegative(a), if_ispositive(a); | |
| 668 Node* const float_zero = a->Float64Constant(0.); | |
| 669 Node* const length_float = a->LoadHeapNumberValue(var_length.value()); | |
| 670 a->Branch(a->Float64LessThan(length_float, float_zero), &if_isnegative, | |
| 671 &if_ispositive); | |
| 672 | |
| 673 a->Bind(&if_isnegative); | |
| 674 a->Return(a->EmptyStringConstant()); | |
| 675 | |
| 676 a->Bind(&if_ispositive); | |
| 677 { | |
| 678 var_length.Bind(a->SmiSub(string_length, var_start.value())); | |
| 679 a->Goto(&out); | |
| 680 } | |
| 681 } | |
| 682 } | |
| 683 | |
| 684 a->Bind(&out); | |
| 685 { | |
| 686 Node* const end = a->SmiAdd(var_start.value(), var_length.value()); | |
| 687 Node* const result = a->SubString(context, string, var_start.value(), end); | |
| 688 a->Return(result); | |
| 689 } | |
| 690 } | |
| 691 | |
| 584 // ES6 section 21.1.3.25 String.prototype.toString () | 692 // ES6 section 21.1.3.25 String.prototype.toString () |
| 585 void Builtins::Generate_StringPrototypeToString(CodeStubAssembler* assembler) { | 693 void Builtins::Generate_StringPrototypeToString(CodeStubAssembler* assembler) { |
| 586 typedef compiler::Node Node; | 694 typedef compiler::Node Node; |
| 587 | 695 |
| 588 Node* receiver = assembler->Parameter(0); | 696 Node* receiver = assembler->Parameter(0); |
| 589 Node* context = assembler->Parameter(3); | 697 Node* context = assembler->Parameter(3); |
| 590 | 698 |
| 591 Node* result = assembler->ToThisValue( | 699 Node* result = assembler->ToThisValue( |
| 592 context, receiver, PrimitiveType::kString, "String.prototype.toString"); | 700 context, receiver, PrimitiveType::kString, "String.prototype.toString"); |
| 593 assembler->Return(result); | 701 assembler->Return(result); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 675 } | 783 } |
| 676 | 784 |
| 677 iterator->set_string(isolate->heap()->empty_string()); | 785 iterator->set_string(isolate->heap()->empty_string()); |
| 678 | 786 |
| 679 return *isolate->factory()->NewJSIteratorResult( | 787 return *isolate->factory()->NewJSIteratorResult( |
| 680 isolate->factory()->undefined_value(), true); | 788 isolate->factory()->undefined_value(), true); |
| 681 } | 789 } |
| 682 | 790 |
| 683 } // namespace internal | 791 } // namespace internal |
| 684 } // namespace v8 | 792 } // namespace v8 |
| OLD | NEW |