| 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 #include "src/regexp/regexp-utils.h" | 9 #include "src/regexp/regexp-utils.h" |
| 10 | 10 |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 case RelationalComparisonMode::kGreaterThan: | 375 case RelationalComparisonMode::kGreaterThan: |
| 376 case RelationalComparisonMode::kGreaterThanOrEqual: | 376 case RelationalComparisonMode::kGreaterThanOrEqual: |
| 377 assembler->Return(assembler->BooleanConstant(true)); | 377 assembler->Return(assembler->BooleanConstant(true)); |
| 378 break; | 378 break; |
| 379 } | 379 } |
| 380 } | 380 } |
| 381 | 381 |
| 382 } // namespace | 382 } // namespace |
| 383 | 383 |
| 384 // static | 384 // static |
| 385 void Builtins::Generate_StringEqual(CodeStubAssembler* assembler) { | 385 void Builtins::Generate_StringEqual(compiler::CodeAssemblerState* state) { |
| 386 GenerateStringEqual(assembler, ResultMode::kDontNegateResult); | 386 CodeStubAssembler assembler(state); |
| 387 GenerateStringEqual(&assembler, ResultMode::kDontNegateResult); |
| 387 } | 388 } |
| 388 | 389 |
| 389 // static | 390 // static |
| 390 void Builtins::Generate_StringNotEqual(CodeStubAssembler* assembler) { | 391 void Builtins::Generate_StringNotEqual(compiler::CodeAssemblerState* state) { |
| 391 GenerateStringEqual(assembler, ResultMode::kNegateResult); | 392 CodeStubAssembler assembler(state); |
| 393 GenerateStringEqual(&assembler, ResultMode::kNegateResult); |
| 392 } | 394 } |
| 393 | 395 |
| 394 // static | 396 // static |
| 395 void Builtins::Generate_StringLessThan(CodeStubAssembler* assembler) { | 397 void Builtins::Generate_StringLessThan(compiler::CodeAssemblerState* state) { |
| 396 GenerateStringRelationalComparison(assembler, | 398 CodeStubAssembler assembler(state); |
| 399 GenerateStringRelationalComparison(&assembler, |
| 397 RelationalComparisonMode::kLessThan); | 400 RelationalComparisonMode::kLessThan); |
| 398 } | 401 } |
| 399 | 402 |
| 400 // static | 403 // static |
| 401 void Builtins::Generate_StringLessThanOrEqual(CodeStubAssembler* assembler) { | 404 void Builtins::Generate_StringLessThanOrEqual( |
| 405 compiler::CodeAssemblerState* state) { |
| 406 CodeStubAssembler assembler(state); |
| 402 GenerateStringRelationalComparison( | 407 GenerateStringRelationalComparison( |
| 403 assembler, RelationalComparisonMode::kLessThanOrEqual); | 408 &assembler, RelationalComparisonMode::kLessThanOrEqual); |
| 404 } | 409 } |
| 405 | 410 |
| 406 // static | 411 // static |
| 407 void Builtins::Generate_StringGreaterThan(CodeStubAssembler* assembler) { | 412 void Builtins::Generate_StringGreaterThan(compiler::CodeAssemblerState* state) { |
| 408 GenerateStringRelationalComparison(assembler, | 413 CodeStubAssembler assembler(state); |
| 414 GenerateStringRelationalComparison(&assembler, |
| 409 RelationalComparisonMode::kGreaterThan); | 415 RelationalComparisonMode::kGreaterThan); |
| 410 } | 416 } |
| 411 | 417 |
| 412 // static | 418 // static |
| 413 void Builtins::Generate_StringGreaterThanOrEqual(CodeStubAssembler* assembler) { | 419 void Builtins::Generate_StringGreaterThanOrEqual( |
| 420 compiler::CodeAssemblerState* state) { |
| 421 CodeStubAssembler assembler(state); |
| 414 GenerateStringRelationalComparison( | 422 GenerateStringRelationalComparison( |
| 415 assembler, RelationalComparisonMode::kGreaterThanOrEqual); | 423 &assembler, RelationalComparisonMode::kGreaterThanOrEqual); |
| 416 } | 424 } |
| 417 | 425 |
| 418 // ----------------------------------------------------------------------------- | 426 // ----------------------------------------------------------------------------- |
| 419 // ES6 section 21.1 String Objects | 427 // ES6 section 21.1 String Objects |
| 420 | 428 |
| 421 // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits ) | 429 // ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits ) |
| 422 void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) { | 430 void Builtins::Generate_StringFromCharCode( |
| 431 compiler::CodeAssemblerState* state) { |
| 423 typedef CodeStubAssembler::Label Label; | 432 typedef CodeStubAssembler::Label Label; |
| 424 typedef compiler::Node Node; | 433 typedef compiler::Node Node; |
| 425 typedef CodeStubAssembler::Variable Variable; | 434 typedef CodeStubAssembler::Variable Variable; |
| 435 CodeStubAssembler assembler(state); |
| 426 | 436 |
| 427 Node* argc = assembler->ChangeInt32ToIntPtr( | 437 Node* argc = assembler.ChangeInt32ToIntPtr( |
| 428 assembler->Parameter(BuiltinDescriptor::kArgumentsCount)); | 438 assembler.Parameter(BuiltinDescriptor::kArgumentsCount)); |
| 429 Node* context = assembler->Parameter(BuiltinDescriptor::kContext); | 439 Node* context = assembler.Parameter(BuiltinDescriptor::kContext); |
| 430 | 440 |
| 431 CodeStubArguments arguments(assembler, argc); | 441 CodeStubArguments arguments(&assembler, argc); |
| 432 | 442 |
| 433 // Check if we have exactly one argument (plus the implicit receiver), i.e. | 443 // Check if we have exactly one argument (plus the implicit receiver), i.e. |
| 434 // if the parent frame is not an arguments adaptor frame. | 444 // if the parent frame is not an arguments adaptor frame. |
| 435 Label if_oneargument(assembler), if_notoneargument(assembler); | 445 Label if_oneargument(&assembler), if_notoneargument(&assembler); |
| 436 assembler->Branch(assembler->WordEqual(argc, assembler->IntPtrConstant(1)), | 446 assembler.Branch(assembler.WordEqual(argc, assembler.IntPtrConstant(1)), |
| 437 &if_oneargument, &if_notoneargument); | 447 &if_oneargument, &if_notoneargument); |
| 438 | 448 |
| 439 assembler->Bind(&if_oneargument); | 449 assembler.Bind(&if_oneargument); |
| 440 { | 450 { |
| 441 // Single argument case, perform fast single character string cache lookup | 451 // Single argument case, perform fast single character string cache lookup |
| 442 // for one-byte code units, or fall back to creating a single character | 452 // for one-byte code units, or fall back to creating a single character |
| 443 // string on the fly otherwise. | 453 // string on the fly otherwise. |
| 444 Node* code = arguments.AtIndex(0); | 454 Node* code = arguments.AtIndex(0); |
| 445 Node* code32 = assembler->TruncateTaggedToWord32(context, code); | 455 Node* code32 = assembler.TruncateTaggedToWord32(context, code); |
| 446 Node* code16 = assembler->Word32And( | 456 Node* code16 = assembler.Word32And( |
| 447 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit)); | 457 code32, assembler.Int32Constant(String::kMaxUtf16CodeUnit)); |
| 448 Node* result = assembler->StringFromCharCode(code16); | 458 Node* result = assembler.StringFromCharCode(code16); |
| 449 arguments.PopAndReturn(result); | 459 arguments.PopAndReturn(result); |
| 450 } | 460 } |
| 451 | 461 |
| 452 Node* code16 = nullptr; | 462 Node* code16 = nullptr; |
| 453 assembler->Bind(&if_notoneargument); | 463 assembler.Bind(&if_notoneargument); |
| 454 { | 464 { |
| 455 Label two_byte(assembler); | 465 Label two_byte(&assembler); |
| 456 // Assume that the resulting string contains only one-byte characters. | 466 // Assume that the resulting string contains only one-byte characters. |
| 457 Node* one_byte_result = assembler->AllocateSeqOneByteString(context, argc); | 467 Node* one_byte_result = assembler.AllocateSeqOneByteString(context, argc); |
| 458 | 468 |
| 459 Variable max_index(assembler, MachineType::PointerRepresentation()); | 469 Variable max_index(&assembler, MachineType::PointerRepresentation()); |
| 460 max_index.Bind(assembler->IntPtrConstant(0)); | 470 max_index.Bind(assembler.IntPtrConstant(0)); |
| 461 | 471 |
| 462 // Iterate over the incoming arguments, converting them to 8-bit character | 472 // Iterate over the incoming arguments, converting them to 8-bit character |
| 463 // codes. Stop if any of the conversions generates a code that doesn't fit | 473 // codes. Stop if any of the conversions generates a code that doesn't fit |
| 464 // in 8 bits. | 474 // in 8 bits. |
| 465 CodeStubAssembler::VariableList vars({&max_index}, assembler->zone()); | 475 CodeStubAssembler::VariableList vars({&max_index}, assembler.zone()); |
| 466 arguments.ForEach(vars, [context, &two_byte, &max_index, &code16, | 476 arguments.ForEach(vars, [context, &two_byte, &max_index, &code16, |
| 467 one_byte_result](CodeStubAssembler* assembler, | 477 one_byte_result](CodeStubAssembler* assembler, |
| 468 Node* arg) { | 478 Node* arg) { |
| 469 Node* code32 = assembler->TruncateTaggedToWord32(context, arg); | 479 Node* code32 = assembler->TruncateTaggedToWord32(context, arg); |
| 470 code16 = assembler->Word32And( | 480 code16 = assembler->Word32And( |
| 471 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit)); | 481 code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit)); |
| 472 | 482 |
| 473 assembler->GotoIf( | 483 assembler->GotoIf( |
| 474 assembler->Int32GreaterThan( | 484 assembler->Int32GreaterThan( |
| 475 code16, assembler->Int32Constant(String::kMaxOneByteCharCode)), | 485 code16, assembler->Int32Constant(String::kMaxOneByteCharCode)), |
| 476 &two_byte); | 486 &two_byte); |
| 477 | 487 |
| 478 // The {code16} fits into the SeqOneByteString {one_byte_result}. | 488 // The {code16} fits into the SeqOneByteString {one_byte_result}. |
| 479 Node* offset = assembler->ElementOffsetFromIndex( | 489 Node* offset = assembler->ElementOffsetFromIndex( |
| 480 max_index.value(), UINT8_ELEMENTS, | 490 max_index.value(), UINT8_ELEMENTS, |
| 481 CodeStubAssembler::INTPTR_PARAMETERS, | 491 CodeStubAssembler::INTPTR_PARAMETERS, |
| 482 SeqOneByteString::kHeaderSize - kHeapObjectTag); | 492 SeqOneByteString::kHeaderSize - kHeapObjectTag); |
| 483 assembler->StoreNoWriteBarrier(MachineRepresentation::kWord8, | 493 assembler->StoreNoWriteBarrier(MachineRepresentation::kWord8, |
| 484 one_byte_result, offset, code16); | 494 one_byte_result, offset, code16); |
| 485 max_index.Bind(assembler->IntPtrAdd(max_index.value(), | 495 max_index.Bind(assembler->IntPtrAdd(max_index.value(), |
| 486 assembler->IntPtrConstant(1))); | 496 assembler->IntPtrConstant(1))); |
| 487 }); | 497 }); |
| 488 arguments.PopAndReturn(one_byte_result); | 498 arguments.PopAndReturn(one_byte_result); |
| 489 | 499 |
| 490 assembler->Bind(&two_byte); | 500 assembler.Bind(&two_byte); |
| 491 | 501 |
| 492 // At least one of the characters in the string requires a 16-bit | 502 // At least one of the characters in the string requires a 16-bit |
| 493 // representation. Allocate a SeqTwoByteString to hold the resulting | 503 // representation. Allocate a SeqTwoByteString to hold the resulting |
| 494 // string. | 504 // string. |
| 495 Node* two_byte_result = assembler->AllocateSeqTwoByteString(context, argc); | 505 Node* two_byte_result = assembler.AllocateSeqTwoByteString(context, argc); |
| 496 | 506 |
| 497 // Copy the characters that have already been put in the 8-bit string into | 507 // Copy the characters that have already been put in the 8-bit string into |
| 498 // their corresponding positions in the new 16-bit string. | 508 // their corresponding positions in the new 16-bit string. |
| 499 Node* zero = assembler->IntPtrConstant(0); | 509 Node* zero = assembler.IntPtrConstant(0); |
| 500 assembler->CopyStringCharacters( | 510 assembler.CopyStringCharacters(one_byte_result, two_byte_result, zero, zero, |
| 501 one_byte_result, two_byte_result, zero, zero, max_index.value(), | 511 max_index.value(), String::ONE_BYTE_ENCODING, |
| 502 String::ONE_BYTE_ENCODING, String::TWO_BYTE_ENCODING, | 512 String::TWO_BYTE_ENCODING, |
| 503 CodeStubAssembler::INTPTR_PARAMETERS); | 513 CodeStubAssembler::INTPTR_PARAMETERS); |
| 504 | 514 |
| 505 // Write the character that caused the 8-bit to 16-bit fault. | 515 // Write the character that caused the 8-bit to 16-bit fault. |
| 506 Node* max_index_offset = assembler->ElementOffsetFromIndex( | 516 Node* max_index_offset = assembler.ElementOffsetFromIndex( |
| 507 max_index.value(), UINT16_ELEMENTS, | 517 max_index.value(), UINT16_ELEMENTS, |
| 508 CodeStubAssembler::INTPTR_PARAMETERS, | 518 CodeStubAssembler::INTPTR_PARAMETERS, |
| 509 SeqTwoByteString::kHeaderSize - kHeapObjectTag); | 519 SeqTwoByteString::kHeaderSize - kHeapObjectTag); |
| 510 assembler->StoreNoWriteBarrier(MachineRepresentation::kWord16, | 520 assembler.StoreNoWriteBarrier(MachineRepresentation::kWord16, |
| 511 two_byte_result, max_index_offset, code16); | 521 two_byte_result, max_index_offset, code16); |
| 512 max_index.Bind( | 522 max_index.Bind( |
| 513 assembler->IntPtrAdd(max_index.value(), assembler->IntPtrConstant(1))); | 523 assembler.IntPtrAdd(max_index.value(), assembler.IntPtrConstant(1))); |
| 514 | 524 |
| 515 // Resume copying the passed-in arguments from the same place where the | 525 // Resume copying the passed-in arguments from the same place where the |
| 516 // 8-bit copy stopped, but this time copying over all of the characters | 526 // 8-bit copy stopped, but this time copying over all of the characters |
| 517 // using a 16-bit representation. | 527 // using a 16-bit representation. |
| 518 arguments.ForEach( | 528 arguments.ForEach( |
| 519 vars, | 529 vars, |
| 520 [context, two_byte_result, &max_index](CodeStubAssembler* assembler, | 530 [context, two_byte_result, &max_index](CodeStubAssembler* assembler, |
| 521 Node* arg) { | 531 Node* arg) { |
| 522 Node* code32 = assembler->TruncateTaggedToWord32(context, arg); | 532 Node* code32 = assembler->TruncateTaggedToWord32(context, arg); |
| 523 Node* code16 = assembler->Word32And( | 533 Node* code16 = assembler->Word32And( |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 | 635 |
| 626 CopyChars(result->GetChars(), one_byte_buffer.ToConstVector().start(), | 636 CopyChars(result->GetChars(), one_byte_buffer.ToConstVector().start(), |
| 627 one_byte_buffer.length()); | 637 one_byte_buffer.length()); |
| 628 CopyChars(result->GetChars() + one_byte_buffer.length(), | 638 CopyChars(result->GetChars() + one_byte_buffer.length(), |
| 629 two_byte_buffer.ToConstVector().start(), two_byte_buffer.length()); | 639 two_byte_buffer.ToConstVector().start(), two_byte_buffer.length()); |
| 630 | 640 |
| 631 return *result; | 641 return *result; |
| 632 } | 642 } |
| 633 | 643 |
| 634 // ES6 section 21.1.3.1 String.prototype.charAt ( pos ) | 644 // ES6 section 21.1.3.1 String.prototype.charAt ( pos ) |
| 635 void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) { | 645 void Builtins::Generate_StringPrototypeCharAt( |
| 646 compiler::CodeAssemblerState* state) { |
| 636 typedef CodeStubAssembler::Label Label; | 647 typedef CodeStubAssembler::Label Label; |
| 637 typedef compiler::Node Node; | 648 typedef compiler::Node Node; |
| 649 CodeStubAssembler assembler(state); |
| 638 | 650 |
| 639 Node* receiver = assembler->Parameter(0); | 651 Node* receiver = assembler.Parameter(0); |
| 640 Node* position = assembler->Parameter(1); | 652 Node* position = assembler.Parameter(1); |
| 641 Node* context = assembler->Parameter(4); | 653 Node* context = assembler.Parameter(4); |
| 642 | 654 |
| 643 // Check that {receiver} is coercible to Object and convert it to a String. | 655 // Check that {receiver} is coercible to Object and convert it to a String. |
| 644 receiver = | 656 receiver = |
| 645 assembler->ToThisString(context, receiver, "String.prototype.charAt"); | 657 assembler.ToThisString(context, receiver, "String.prototype.charAt"); |
| 646 | 658 |
| 647 // Convert the {position} to a Smi and check that it's in bounds of the | 659 // Convert the {position} to a Smi and check that it's in bounds of the |
| 648 // {receiver}. | 660 // {receiver}. |
| 649 { | 661 { |
| 650 Label return_emptystring(assembler, Label::kDeferred); | 662 Label return_emptystring(&assembler, Label::kDeferred); |
| 651 position = assembler->ToInteger(context, position, | 663 position = assembler.ToInteger(context, position, |
| 652 CodeStubAssembler::kTruncateMinusZero); | 664 CodeStubAssembler::kTruncateMinusZero); |
| 653 assembler->GotoUnless(assembler->TaggedIsSmi(position), | 665 assembler.GotoUnless(assembler.TaggedIsSmi(position), &return_emptystring); |
| 654 &return_emptystring); | |
| 655 | 666 |
| 656 // Determine the actual length of the {receiver} String. | 667 // Determine the actual length of the {receiver} String. |
| 657 Node* receiver_length = | 668 Node* receiver_length = |
| 658 assembler->LoadObjectField(receiver, String::kLengthOffset); | 669 assembler.LoadObjectField(receiver, String::kLengthOffset); |
| 659 | 670 |
| 660 // Return "" if the Smi {position} is outside the bounds of the {receiver}. | 671 // Return "" if the Smi {position} is outside the bounds of the {receiver}. |
| 661 Label if_positioninbounds(assembler); | 672 Label if_positioninbounds(&assembler); |
| 662 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length), | 673 assembler.Branch(assembler.SmiAboveOrEqual(position, receiver_length), |
| 663 &return_emptystring, &if_positioninbounds); | 674 &return_emptystring, &if_positioninbounds); |
| 664 | 675 |
| 665 assembler->Bind(&return_emptystring); | 676 assembler.Bind(&return_emptystring); |
| 666 assembler->Return(assembler->EmptyStringConstant()); | 677 assembler.Return(assembler.EmptyStringConstant()); |
| 667 | 678 |
| 668 assembler->Bind(&if_positioninbounds); | 679 assembler.Bind(&if_positioninbounds); |
| 669 } | 680 } |
| 670 | 681 |
| 671 // Load the character code at the {position} from the {receiver}. | 682 // Load the character code at the {position} from the {receiver}. |
| 672 Node* code = assembler->StringCharCodeAt(receiver, position); | 683 Node* code = assembler.StringCharCodeAt(receiver, position); |
| 673 | 684 |
| 674 // And return the single character string with only that {code}. | 685 // And return the single character string with only that {code}. |
| 675 Node* result = assembler->StringFromCharCode(code); | 686 Node* result = assembler.StringFromCharCode(code); |
| 676 assembler->Return(result); | 687 assembler.Return(result); |
| 677 } | 688 } |
| 678 | 689 |
| 679 // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos ) | 690 // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos ) |
| 680 void Builtins::Generate_StringPrototypeCharCodeAt( | 691 void Builtins::Generate_StringPrototypeCharCodeAt( |
| 681 CodeStubAssembler* assembler) { | 692 compiler::CodeAssemblerState* state) { |
| 682 typedef CodeStubAssembler::Label Label; | 693 typedef CodeStubAssembler::Label Label; |
| 683 typedef compiler::Node Node; | 694 typedef compiler::Node Node; |
| 695 CodeStubAssembler assembler(state); |
| 684 | 696 |
| 685 Node* receiver = assembler->Parameter(0); | 697 Node* receiver = assembler.Parameter(0); |
| 686 Node* position = assembler->Parameter(1); | 698 Node* position = assembler.Parameter(1); |
| 687 Node* context = assembler->Parameter(4); | 699 Node* context = assembler.Parameter(4); |
| 688 | 700 |
| 689 // Check that {receiver} is coercible to Object and convert it to a String. | 701 // Check that {receiver} is coercible to Object and convert it to a String. |
| 690 receiver = | 702 receiver = |
| 691 assembler->ToThisString(context, receiver, "String.prototype.charCodeAt"); | 703 assembler.ToThisString(context, receiver, "String.prototype.charCodeAt"); |
| 692 | 704 |
| 693 // Convert the {position} to a Smi and check that it's in bounds of the | 705 // Convert the {position} to a Smi and check that it's in bounds of the |
| 694 // {receiver}. | 706 // {receiver}. |
| 695 { | 707 { |
| 696 Label return_nan(assembler, Label::kDeferred); | 708 Label return_nan(&assembler, Label::kDeferred); |
| 697 position = assembler->ToInteger(context, position, | 709 position = assembler.ToInteger(context, position, |
| 698 CodeStubAssembler::kTruncateMinusZero); | 710 CodeStubAssembler::kTruncateMinusZero); |
| 699 assembler->GotoUnless(assembler->TaggedIsSmi(position), &return_nan); | 711 assembler.GotoUnless(assembler.TaggedIsSmi(position), &return_nan); |
| 700 | 712 |
| 701 // Determine the actual length of the {receiver} String. | 713 // Determine the actual length of the {receiver} String. |
| 702 Node* receiver_length = | 714 Node* receiver_length = |
| 703 assembler->LoadObjectField(receiver, String::kLengthOffset); | 715 assembler.LoadObjectField(receiver, String::kLengthOffset); |
| 704 | 716 |
| 705 // Return NaN if the Smi {position} is outside the bounds of the {receiver}. | 717 // Return NaN if the Smi {position} is outside the bounds of the {receiver}. |
| 706 Label if_positioninbounds(assembler); | 718 Label if_positioninbounds(&assembler); |
| 707 assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length), | 719 assembler.Branch(assembler.SmiAboveOrEqual(position, receiver_length), |
| 708 &return_nan, &if_positioninbounds); | 720 &return_nan, &if_positioninbounds); |
| 709 | 721 |
| 710 assembler->Bind(&return_nan); | 722 assembler.Bind(&return_nan); |
| 711 assembler->Return(assembler->NaNConstant()); | 723 assembler.Return(assembler.NaNConstant()); |
| 712 | 724 |
| 713 assembler->Bind(&if_positioninbounds); | 725 assembler.Bind(&if_positioninbounds); |
| 714 } | 726 } |
| 715 | 727 |
| 716 // Load the character at the {position} from the {receiver}. | 728 // Load the character at the {position} from the {receiver}. |
| 717 Node* value = assembler->StringCharCodeAt(receiver, position); | 729 Node* value = assembler.StringCharCodeAt(receiver, position); |
| 718 Node* result = assembler->SmiFromWord32(value); | 730 Node* result = assembler.SmiFromWord32(value); |
| 719 assembler->Return(result); | 731 assembler.Return(result); |
| 720 } | 732 } |
| 721 | 733 |
| 722 // ES6 section 21.1.3.6 | 734 // ES6 section 21.1.3.6 |
| 723 // String.prototype.endsWith ( searchString [ , endPosition ] ) | 735 // String.prototype.endsWith ( searchString [ , endPosition ] ) |
| 724 BUILTIN(StringPrototypeEndsWith) { | 736 BUILTIN(StringPrototypeEndsWith) { |
| 725 HandleScope handle_scope(isolate); | 737 HandleScope handle_scope(isolate); |
| 726 TO_THIS_STRING(str, "String.prototype.endsWith"); | 738 TO_THIS_STRING(str, "String.prototype.endsWith"); |
| 727 | 739 |
| 728 // Check if the search string is a regExp and fail if it is. | 740 // Check if the search string is a regExp and fail if it is. |
| 729 Handle<Object> search = args.atOrUndefined(isolate, 1); | 741 Handle<Object> search = args.atOrUndefined(isolate, 1); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 isolate->factory()->NewStringFromStaticChars("NFC, NFD, NFKC, NFKD"); | 913 isolate->factory()->NewStringFromStaticChars("NFC, NFD, NFKC, NFKD"); |
| 902 THROW_NEW_ERROR_RETURN_FAILURE( | 914 THROW_NEW_ERROR_RETURN_FAILURE( |
| 903 isolate, | 915 isolate, |
| 904 NewRangeError(MessageTemplate::kNormalizationForm, valid_forms)); | 916 NewRangeError(MessageTemplate::kNormalizationForm, valid_forms)); |
| 905 } | 917 } |
| 906 | 918 |
| 907 return *string; | 919 return *string; |
| 908 } | 920 } |
| 909 | 921 |
| 910 // ES6 section B.2.3.1 String.prototype.substr ( start, length ) | 922 // ES6 section B.2.3.1 String.prototype.substr ( start, length ) |
| 911 void Builtins::Generate_StringPrototypeSubstr(CodeStubAssembler* a) { | 923 void Builtins::Generate_StringPrototypeSubstr( |
| 924 compiler::CodeAssemblerState* state) { |
| 912 typedef CodeStubAssembler::Label Label; | 925 typedef CodeStubAssembler::Label Label; |
| 913 typedef compiler::Node Node; | 926 typedef compiler::Node Node; |
| 914 typedef CodeStubAssembler::Variable Variable; | 927 typedef CodeStubAssembler::Variable Variable; |
| 928 CodeStubAssembler a(state); |
| 915 | 929 |
| 916 Label out(a), handle_length(a); | 930 Label out(&a), handle_length(&a); |
| 917 | 931 |
| 918 Variable var_start(a, MachineRepresentation::kTagged); | 932 Variable var_start(&a, MachineRepresentation::kTagged); |
| 919 Variable var_length(a, MachineRepresentation::kTagged); | 933 Variable var_length(&a, MachineRepresentation::kTagged); |
| 920 | 934 |
| 921 Node* const receiver = a->Parameter(0); | 935 Node* const receiver = a.Parameter(0); |
| 922 Node* const start = a->Parameter(1); | 936 Node* const start = a.Parameter(1); |
| 923 Node* const length = a->Parameter(2); | 937 Node* const length = a.Parameter(2); |
| 924 Node* const context = a->Parameter(5); | 938 Node* const context = a.Parameter(5); |
| 925 | 939 |
| 926 Node* const zero = a->SmiConstant(Smi::kZero); | 940 Node* const zero = a.SmiConstant(Smi::kZero); |
| 927 | 941 |
| 928 // Check that {receiver} is coercible to Object and convert it to a String. | 942 // Check that {receiver} is coercible to Object and convert it to a String. |
| 929 Node* const string = | 943 Node* const string = |
| 930 a->ToThisString(context, receiver, "String.prototype.substr"); | 944 a.ToThisString(context, receiver, "String.prototype.substr"); |
| 931 | 945 |
| 932 Node* const string_length = a->LoadStringLength(string); | 946 Node* const string_length = a.LoadStringLength(string); |
| 933 | 947 |
| 934 // Conversions and bounds-checks for {start}. | 948 // Conversions and bounds-checks for {start}. |
| 935 { | 949 { |
| 936 Node* const start_int = | 950 Node* const start_int = |
| 937 a->ToInteger(context, start, CodeStubAssembler::kTruncateMinusZero); | 951 a.ToInteger(context, start, CodeStubAssembler::kTruncateMinusZero); |
| 938 | 952 |
| 939 Label if_issmi(a), if_isheapnumber(a, Label::kDeferred); | 953 Label if_issmi(&a), if_isheapnumber(&a, Label::kDeferred); |
| 940 a->Branch(a->TaggedIsSmi(start_int), &if_issmi, &if_isheapnumber); | 954 a.Branch(a.TaggedIsSmi(start_int), &if_issmi, &if_isheapnumber); |
| 941 | 955 |
| 942 a->Bind(&if_issmi); | 956 a.Bind(&if_issmi); |
| 943 { | 957 { |
| 944 Node* const length_plus_start = a->SmiAdd(string_length, start_int); | 958 Node* const length_plus_start = a.SmiAdd(string_length, start_int); |
| 945 var_start.Bind(a->Select(a->SmiLessThan(start_int, zero), | 959 var_start.Bind(a.Select(a.SmiLessThan(start_int, zero), |
| 946 a->SmiMax(length_plus_start, zero), start_int)); | 960 a.SmiMax(length_plus_start, zero), start_int)); |
| 947 a->Goto(&handle_length); | 961 a.Goto(&handle_length); |
| 948 } | 962 } |
| 949 | 963 |
| 950 a->Bind(&if_isheapnumber); | 964 a.Bind(&if_isheapnumber); |
| 951 { | 965 { |
| 952 // If {start} is a heap number, it is definitely out of bounds. If it is | 966 // If {start} is a heap number, it is definitely out of bounds. If it is |
| 953 // negative, {start} = max({string_length} + {start}),0) = 0'. If it is | 967 // negative, {start} = max({string_length} + {start}),0) = 0'. If it is |
| 954 // positive, set {start} to {string_length} which ultimately results in | 968 // positive, set {start} to {string_length} which ultimately results in |
| 955 // returning an empty string. | 969 // returning an empty string. |
| 956 Node* const float_zero = a->Float64Constant(0.); | 970 Node* const float_zero = a.Float64Constant(0.); |
| 957 Node* const start_float = a->LoadHeapNumberValue(start_int); | 971 Node* const start_float = a.LoadHeapNumberValue(start_int); |
| 958 var_start.Bind(a->Select(a->Float64LessThan(start_float, float_zero), | 972 var_start.Bind(a.Select(a.Float64LessThan(start_float, float_zero), zero, |
| 959 zero, string_length)); | 973 string_length)); |
| 960 a->Goto(&handle_length); | 974 a.Goto(&handle_length); |
| 961 } | 975 } |
| 962 } | 976 } |
| 963 | 977 |
| 964 // Conversions and bounds-checks for {length}. | 978 // Conversions and bounds-checks for {length}. |
| 965 a->Bind(&handle_length); | 979 a.Bind(&handle_length); |
| 966 { | 980 { |
| 967 Label if_issmi(a), if_isheapnumber(a, Label::kDeferred); | 981 Label if_issmi(&a), if_isheapnumber(&a, Label::kDeferred); |
| 968 | 982 |
| 969 // Default to {string_length} if {length} is undefined. | 983 // Default to {string_length} if {length} is undefined. |
| 970 { | 984 { |
| 971 Label if_isundefined(a, Label::kDeferred), if_isnotundefined(a); | 985 Label if_isundefined(&a, Label::kDeferred), if_isnotundefined(&a); |
| 972 a->Branch(a->WordEqual(length, a->UndefinedConstant()), &if_isundefined, | 986 a.Branch(a.WordEqual(length, a.UndefinedConstant()), &if_isundefined, |
| 973 &if_isnotundefined); | 987 &if_isnotundefined); |
| 974 | 988 |
| 975 a->Bind(&if_isundefined); | 989 a.Bind(&if_isundefined); |
| 976 var_length.Bind(string_length); | 990 var_length.Bind(string_length); |
| 977 a->Goto(&if_issmi); | 991 a.Goto(&if_issmi); |
| 978 | 992 |
| 979 a->Bind(&if_isnotundefined); | 993 a.Bind(&if_isnotundefined); |
| 980 var_length.Bind( | 994 var_length.Bind( |
| 981 a->ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero)); | 995 a.ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero)); |
| 982 } | 996 } |
| 983 | 997 |
| 984 a->Branch(a->TaggedIsSmi(var_length.value()), &if_issmi, &if_isheapnumber); | 998 a.Branch(a.TaggedIsSmi(var_length.value()), &if_issmi, &if_isheapnumber); |
| 985 | 999 |
| 986 // Set {length} to min(max({length}, 0), {string_length} - {start} | 1000 // Set {length} to min(max({length}, 0), {string_length} - {start} |
| 987 a->Bind(&if_issmi); | 1001 a.Bind(&if_issmi); |
| 988 { | 1002 { |
| 989 Node* const positive_length = a->SmiMax(var_length.value(), zero); | 1003 Node* const positive_length = a.SmiMax(var_length.value(), zero); |
| 990 | 1004 |
| 991 Node* const minimal_length = a->SmiSub(string_length, var_start.value()); | 1005 Node* const minimal_length = a.SmiSub(string_length, var_start.value()); |
| 992 var_length.Bind(a->SmiMin(positive_length, minimal_length)); | 1006 var_length.Bind(a.SmiMin(positive_length, minimal_length)); |
| 993 | 1007 |
| 994 a->GotoUnless(a->SmiLessThanOrEqual(var_length.value(), zero), &out); | 1008 a.GotoUnless(a.SmiLessThanOrEqual(var_length.value(), zero), &out); |
| 995 a->Return(a->EmptyStringConstant()); | 1009 a.Return(a.EmptyStringConstant()); |
| 996 } | 1010 } |
| 997 | 1011 |
| 998 a->Bind(&if_isheapnumber); | 1012 a.Bind(&if_isheapnumber); |
| 999 { | 1013 { |
| 1000 // If {length} is a heap number, it is definitely out of bounds. There are | 1014 // If {length} is a heap number, it is definitely out of bounds. There are |
| 1001 // two cases according to the spec: if it is negative, "" is returned; if | 1015 // two cases according to the spec: if it is negative, "" is returned; if |
| 1002 // it is positive, then length is set to {string_length} - {start}. | 1016 // it is positive, then length is set to {string_length} - {start}. |
| 1003 | 1017 |
| 1004 CSA_ASSERT(a, a->WordEqual(a->LoadMap(var_length.value()), | 1018 CSA_ASSERT(&a, a.WordEqual(a.LoadMap(var_length.value()), |
| 1005 a->HeapNumberMapConstant())); | 1019 a.HeapNumberMapConstant())); |
| 1006 | 1020 |
| 1007 Label if_isnegative(a), if_ispositive(a); | 1021 Label if_isnegative(&a), if_ispositive(&a); |
| 1008 Node* const float_zero = a->Float64Constant(0.); | 1022 Node* const float_zero = a.Float64Constant(0.); |
| 1009 Node* const length_float = a->LoadHeapNumberValue(var_length.value()); | 1023 Node* const length_float = a.LoadHeapNumberValue(var_length.value()); |
| 1010 a->Branch(a->Float64LessThan(length_float, float_zero), &if_isnegative, | 1024 a.Branch(a.Float64LessThan(length_float, float_zero), &if_isnegative, |
| 1011 &if_ispositive); | 1025 &if_ispositive); |
| 1012 | 1026 |
| 1013 a->Bind(&if_isnegative); | 1027 a.Bind(&if_isnegative); |
| 1014 a->Return(a->EmptyStringConstant()); | 1028 a.Return(a.EmptyStringConstant()); |
| 1015 | 1029 |
| 1016 a->Bind(&if_ispositive); | 1030 a.Bind(&if_ispositive); |
| 1017 { | 1031 { |
| 1018 var_length.Bind(a->SmiSub(string_length, var_start.value())); | 1032 var_length.Bind(a.SmiSub(string_length, var_start.value())); |
| 1019 a->GotoUnless(a->SmiLessThanOrEqual(var_length.value(), zero), &out); | 1033 a.GotoUnless(a.SmiLessThanOrEqual(var_length.value(), zero), &out); |
| 1020 a->Return(a->EmptyStringConstant()); | 1034 a.Return(a.EmptyStringConstant()); |
| 1021 } | 1035 } |
| 1022 } | 1036 } |
| 1023 } | 1037 } |
| 1024 | 1038 |
| 1025 a->Bind(&out); | 1039 a.Bind(&out); |
| 1026 { | 1040 { |
| 1027 Node* const end = a->SmiAdd(var_start.value(), var_length.value()); | 1041 Node* const end = a.SmiAdd(var_start.value(), var_length.value()); |
| 1028 Node* const result = a->SubString(context, string, var_start.value(), end); | 1042 Node* const result = a.SubString(context, string, var_start.value(), end); |
| 1029 a->Return(result); | 1043 a.Return(result); |
| 1030 } | 1044 } |
| 1031 } | 1045 } |
| 1032 | 1046 |
| 1033 namespace { | 1047 namespace { |
| 1034 | 1048 |
| 1035 compiler::Node* ToSmiBetweenZeroAnd(CodeStubAssembler* a, | 1049 compiler::Node* ToSmiBetweenZeroAnd(CodeStubAssembler* a, |
| 1036 compiler::Node* context, | 1050 compiler::Node* context, |
| 1037 compiler::Node* value, | 1051 compiler::Node* value, |
| 1038 compiler::Node* limit) { | 1052 compiler::Node* limit) { |
| 1039 typedef CodeStubAssembler::Label Label; | 1053 typedef CodeStubAssembler::Label Label; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1082 a->Goto(&out); | 1096 a->Goto(&out); |
| 1083 } | 1097 } |
| 1084 | 1098 |
| 1085 a->Bind(&out); | 1099 a->Bind(&out); |
| 1086 return var_result.value(); | 1100 return var_result.value(); |
| 1087 } | 1101 } |
| 1088 | 1102 |
| 1089 } // namespace | 1103 } // namespace |
| 1090 | 1104 |
| 1091 // ES6 section 21.1.3.19 String.prototype.substring ( start, end ) | 1105 // ES6 section 21.1.3.19 String.prototype.substring ( start, end ) |
| 1092 void Builtins::Generate_StringPrototypeSubstring(CodeStubAssembler* a) { | 1106 void Builtins::Generate_StringPrototypeSubstring( |
| 1107 compiler::CodeAssemblerState* state) { |
| 1093 typedef CodeStubAssembler::Label Label; | 1108 typedef CodeStubAssembler::Label Label; |
| 1094 typedef compiler::Node Node; | 1109 typedef compiler::Node Node; |
| 1095 typedef CodeStubAssembler::Variable Variable; | 1110 typedef CodeStubAssembler::Variable Variable; |
| 1111 CodeStubAssembler a(state); |
| 1096 | 1112 |
| 1097 Label out(a); | 1113 Label out(&a); |
| 1098 | 1114 |
| 1099 Variable var_start(a, MachineRepresentation::kTagged); | 1115 Variable var_start(&a, MachineRepresentation::kTagged); |
| 1100 Variable var_end(a, MachineRepresentation::kTagged); | 1116 Variable var_end(&a, MachineRepresentation::kTagged); |
| 1101 | 1117 |
| 1102 Node* const receiver = a->Parameter(0); | 1118 Node* const receiver = a.Parameter(0); |
| 1103 Node* const start = a->Parameter(1); | 1119 Node* const start = a.Parameter(1); |
| 1104 Node* const end = a->Parameter(2); | 1120 Node* const end = a.Parameter(2); |
| 1105 Node* const context = a->Parameter(5); | 1121 Node* const context = a.Parameter(5); |
| 1106 | 1122 |
| 1107 // Check that {receiver} is coercible to Object and convert it to a String. | 1123 // Check that {receiver} is coercible to Object and convert it to a String. |
| 1108 Node* const string = | 1124 Node* const string = |
| 1109 a->ToThisString(context, receiver, "String.prototype.substring"); | 1125 a.ToThisString(context, receiver, "String.prototype.substring"); |
| 1110 | 1126 |
| 1111 Node* const length = a->LoadStringLength(string); | 1127 Node* const length = a.LoadStringLength(string); |
| 1112 | 1128 |
| 1113 // Conversion and bounds-checks for {start}. | 1129 // Conversion and bounds-checks for {start}. |
| 1114 var_start.Bind(ToSmiBetweenZeroAnd(a, context, start, length)); | 1130 var_start.Bind(ToSmiBetweenZeroAnd(&a, context, start, length)); |
| 1115 | 1131 |
| 1116 // Conversion and bounds-checks for {end}. | 1132 // Conversion and bounds-checks for {end}. |
| 1117 { | 1133 { |
| 1118 var_end.Bind(length); | 1134 var_end.Bind(length); |
| 1119 a->GotoIf(a->WordEqual(end, a->UndefinedConstant()), &out); | 1135 a.GotoIf(a.WordEqual(end, a.UndefinedConstant()), &out); |
| 1120 | 1136 |
| 1121 var_end.Bind(ToSmiBetweenZeroAnd(a, context, end, length)); | 1137 var_end.Bind(ToSmiBetweenZeroAnd(&a, context, end, length)); |
| 1122 | 1138 |
| 1123 Label if_endislessthanstart(a); | 1139 Label if_endislessthanstart(&a); |
| 1124 a->Branch(a->SmiLessThan(var_end.value(), var_start.value()), | 1140 a.Branch(a.SmiLessThan(var_end.value(), var_start.value()), |
| 1125 &if_endislessthanstart, &out); | 1141 &if_endislessthanstart, &out); |
| 1126 | 1142 |
| 1127 a->Bind(&if_endislessthanstart); | 1143 a.Bind(&if_endislessthanstart); |
| 1128 { | 1144 { |
| 1129 Node* const tmp = var_end.value(); | 1145 Node* const tmp = var_end.value(); |
| 1130 var_end.Bind(var_start.value()); | 1146 var_end.Bind(var_start.value()); |
| 1131 var_start.Bind(tmp); | 1147 var_start.Bind(tmp); |
| 1132 a->Goto(&out); | 1148 a.Goto(&out); |
| 1133 } | 1149 } |
| 1134 } | 1150 } |
| 1135 | 1151 |
| 1136 a->Bind(&out); | 1152 a.Bind(&out); |
| 1137 { | 1153 { |
| 1138 Node* result = | 1154 Node* result = |
| 1139 a->SubString(context, string, var_start.value(), var_end.value()); | 1155 a.SubString(context, string, var_start.value(), var_end.value()); |
| 1140 a->Return(result); | 1156 a.Return(result); |
| 1141 } | 1157 } |
| 1142 } | 1158 } |
| 1143 | 1159 |
| 1144 BUILTIN(StringPrototypeStartsWith) { | 1160 BUILTIN(StringPrototypeStartsWith) { |
| 1145 HandleScope handle_scope(isolate); | 1161 HandleScope handle_scope(isolate); |
| 1146 TO_THIS_STRING(str, "String.prototype.startsWith"); | 1162 TO_THIS_STRING(str, "String.prototype.startsWith"); |
| 1147 | 1163 |
| 1148 // Check if the search string is a regExp and fail if it is. | 1164 // Check if the search string is a regExp and fail if it is. |
| 1149 Handle<Object> search = args.atOrUndefined(isolate, 1); | 1165 Handle<Object> search = args.atOrUndefined(isolate, 1); |
| 1150 Maybe<bool> is_reg_exp = RegExpUtils::IsRegExp(isolate, search); | 1166 Maybe<bool> is_reg_exp = RegExpUtils::IsRegExp(isolate, search); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1184 | 1200 |
| 1185 for (int i = 0; i < search_string->length(); i++) { | 1201 for (int i = 0; i < search_string->length(); i++) { |
| 1186 if (str_reader.Get(start + i) != search_reader.Get(i)) { | 1202 if (str_reader.Get(start + i) != search_reader.Get(i)) { |
| 1187 return isolate->heap()->false_value(); | 1203 return isolate->heap()->false_value(); |
| 1188 } | 1204 } |
| 1189 } | 1205 } |
| 1190 return isolate->heap()->true_value(); | 1206 return isolate->heap()->true_value(); |
| 1191 } | 1207 } |
| 1192 | 1208 |
| 1193 // ES6 section 21.1.3.25 String.prototype.toString () | 1209 // ES6 section 21.1.3.25 String.prototype.toString () |
| 1194 void Builtins::Generate_StringPrototypeToString(CodeStubAssembler* assembler) { | 1210 void Builtins::Generate_StringPrototypeToString( |
| 1211 compiler::CodeAssemblerState* state) { |
| 1195 typedef compiler::Node Node; | 1212 typedef compiler::Node Node; |
| 1213 CodeStubAssembler assembler(state); |
| 1196 | 1214 |
| 1197 Node* receiver = assembler->Parameter(0); | 1215 Node* receiver = assembler.Parameter(0); |
| 1198 Node* context = assembler->Parameter(3); | 1216 Node* context = assembler.Parameter(3); |
| 1199 | 1217 |
| 1200 Node* result = assembler->ToThisValue( | 1218 Node* result = assembler.ToThisValue( |
| 1201 context, receiver, PrimitiveType::kString, "String.prototype.toString"); | 1219 context, receiver, PrimitiveType::kString, "String.prototype.toString"); |
| 1202 assembler->Return(result); | 1220 assembler.Return(result); |
| 1203 } | 1221 } |
| 1204 | 1222 |
| 1205 // ES6 section 21.1.3.27 String.prototype.trim () | 1223 // ES6 section 21.1.3.27 String.prototype.trim () |
| 1206 BUILTIN(StringPrototypeTrim) { | 1224 BUILTIN(StringPrototypeTrim) { |
| 1207 HandleScope scope(isolate); | 1225 HandleScope scope(isolate); |
| 1208 TO_THIS_STRING(string, "String.prototype.trim"); | 1226 TO_THIS_STRING(string, "String.prototype.trim"); |
| 1209 return *String::Trim(string, String::kTrim); | 1227 return *String::Trim(string, String::kTrim); |
| 1210 } | 1228 } |
| 1211 | 1229 |
| 1212 // Non-standard WebKit extension | 1230 // Non-standard WebKit extension |
| 1213 BUILTIN(StringPrototypeTrimLeft) { | 1231 BUILTIN(StringPrototypeTrimLeft) { |
| 1214 HandleScope scope(isolate); | 1232 HandleScope scope(isolate); |
| 1215 TO_THIS_STRING(string, "String.prototype.trimLeft"); | 1233 TO_THIS_STRING(string, "String.prototype.trimLeft"); |
| 1216 return *String::Trim(string, String::kTrimLeft); | 1234 return *String::Trim(string, String::kTrimLeft); |
| 1217 } | 1235 } |
| 1218 | 1236 |
| 1219 // Non-standard WebKit extension | 1237 // Non-standard WebKit extension |
| 1220 BUILTIN(StringPrototypeTrimRight) { | 1238 BUILTIN(StringPrototypeTrimRight) { |
| 1221 HandleScope scope(isolate); | 1239 HandleScope scope(isolate); |
| 1222 TO_THIS_STRING(string, "String.prototype.trimRight"); | 1240 TO_THIS_STRING(string, "String.prototype.trimRight"); |
| 1223 return *String::Trim(string, String::kTrimRight); | 1241 return *String::Trim(string, String::kTrimRight); |
| 1224 } | 1242 } |
| 1225 | 1243 |
| 1226 // ES6 section 21.1.3.28 String.prototype.valueOf ( ) | 1244 // ES6 section 21.1.3.28 String.prototype.valueOf ( ) |
| 1227 void Builtins::Generate_StringPrototypeValueOf(CodeStubAssembler* assembler) { | 1245 void Builtins::Generate_StringPrototypeValueOf( |
| 1246 compiler::CodeAssemblerState* state) { |
| 1228 typedef compiler::Node Node; | 1247 typedef compiler::Node Node; |
| 1248 CodeStubAssembler assembler(state); |
| 1229 | 1249 |
| 1230 Node* receiver = assembler->Parameter(0); | 1250 Node* receiver = assembler.Parameter(0); |
| 1231 Node* context = assembler->Parameter(3); | 1251 Node* context = assembler.Parameter(3); |
| 1232 | 1252 |
| 1233 Node* result = assembler->ToThisValue( | 1253 Node* result = assembler.ToThisValue( |
| 1234 context, receiver, PrimitiveType::kString, "String.prototype.valueOf"); | 1254 context, receiver, PrimitiveType::kString, "String.prototype.valueOf"); |
| 1235 assembler->Return(result); | 1255 assembler.Return(result); |
| 1236 } | 1256 } |
| 1237 | 1257 |
| 1238 void Builtins::Generate_StringPrototypeIterator(CodeStubAssembler* assembler) { | 1258 void Builtins::Generate_StringPrototypeIterator( |
| 1259 compiler::CodeAssemblerState* state) { |
| 1239 typedef compiler::Node Node; | 1260 typedef compiler::Node Node; |
| 1261 CodeStubAssembler assembler(state); |
| 1240 | 1262 |
| 1241 Node* receiver = assembler->Parameter(0); | 1263 Node* receiver = assembler.Parameter(0); |
| 1242 Node* context = assembler->Parameter(3); | 1264 Node* context = assembler.Parameter(3); |
| 1243 | 1265 |
| 1244 Node* string = assembler->ToThisString(context, receiver, | 1266 Node* string = assembler.ToThisString(context, receiver, |
| 1245 "String.prototype[Symbol.iterator]"); | 1267 "String.prototype[Symbol.iterator]"); |
| 1246 | 1268 |
| 1247 Node* native_context = assembler->LoadNativeContext(context); | 1269 Node* native_context = assembler.LoadNativeContext(context); |
| 1248 Node* map = assembler->LoadFixedArrayElement( | 1270 Node* map = assembler.LoadFixedArrayElement( |
| 1249 native_context, | 1271 native_context, |
| 1250 assembler->IntPtrConstant(Context::STRING_ITERATOR_MAP_INDEX), 0, | 1272 assembler.IntPtrConstant(Context::STRING_ITERATOR_MAP_INDEX), 0, |
| 1251 CodeStubAssembler::INTPTR_PARAMETERS); | 1273 CodeStubAssembler::INTPTR_PARAMETERS); |
| 1252 Node* iterator = assembler->Allocate(JSStringIterator::kSize); | 1274 Node* iterator = assembler.Allocate(JSStringIterator::kSize); |
| 1253 assembler->StoreMapNoWriteBarrier(iterator, map); | 1275 assembler.StoreMapNoWriteBarrier(iterator, map); |
| 1254 assembler->StoreObjectFieldRoot(iterator, JSValue::kPropertiesOffset, | 1276 assembler.StoreObjectFieldRoot(iterator, JSValue::kPropertiesOffset, |
| 1255 Heap::kEmptyFixedArrayRootIndex); | 1277 Heap::kEmptyFixedArrayRootIndex); |
| 1256 assembler->StoreObjectFieldRoot(iterator, JSObject::kElementsOffset, | 1278 assembler.StoreObjectFieldRoot(iterator, JSObject::kElementsOffset, |
| 1257 Heap::kEmptyFixedArrayRootIndex); | 1279 Heap::kEmptyFixedArrayRootIndex); |
| 1258 assembler->StoreObjectFieldNoWriteBarrier( | 1280 assembler.StoreObjectFieldNoWriteBarrier( |
| 1259 iterator, JSStringIterator::kStringOffset, string); | 1281 iterator, JSStringIterator::kStringOffset, string); |
| 1260 Node* index = assembler->SmiConstant(Smi::kZero); | 1282 Node* index = assembler.SmiConstant(Smi::kZero); |
| 1261 assembler->StoreObjectFieldNoWriteBarrier( | 1283 assembler.StoreObjectFieldNoWriteBarrier( |
| 1262 iterator, JSStringIterator::kNextIndexOffset, index); | 1284 iterator, JSStringIterator::kNextIndexOffset, index); |
| 1263 assembler->Return(iterator); | 1285 assembler.Return(iterator); |
| 1264 } | 1286 } |
| 1265 | 1287 |
| 1266 namespace { | 1288 namespace { |
| 1267 | 1289 |
| 1268 // Return the |word32| codepoint at {index}. Supports SeqStrings and | 1290 // Return the |word32| codepoint at {index}. Supports SeqStrings and |
| 1269 // ExternalStrings. | 1291 // ExternalStrings. |
| 1270 compiler::Node* LoadSurrogatePairInternal(CodeStubAssembler* assembler, | 1292 compiler::Node* LoadSurrogatePairInternal(CodeStubAssembler* assembler, |
| 1271 compiler::Node* string, | 1293 compiler::Node* string, |
| 1272 compiler::Node* length, | 1294 compiler::Node* length, |
| 1273 compiler::Node* index, | 1295 compiler::Node* index, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1348 compiler::Node* string, | 1370 compiler::Node* string, |
| 1349 compiler::Node* length, | 1371 compiler::Node* length, |
| 1350 compiler::Node* index) { | 1372 compiler::Node* index) { |
| 1351 return LoadSurrogatePairInternal(assembler, string, length, index, | 1373 return LoadSurrogatePairInternal(assembler, string, length, index, |
| 1352 UnicodeEncoding::UTF16); | 1374 UnicodeEncoding::UTF16); |
| 1353 } | 1375 } |
| 1354 | 1376 |
| 1355 } // namespace | 1377 } // namespace |
| 1356 | 1378 |
| 1357 void Builtins::Generate_StringIteratorPrototypeNext( | 1379 void Builtins::Generate_StringIteratorPrototypeNext( |
| 1358 CodeStubAssembler* assembler) { | 1380 compiler::CodeAssemblerState* state) { |
| 1359 typedef CodeStubAssembler::Label Label; | 1381 typedef CodeStubAssembler::Label Label; |
| 1360 typedef compiler::Node Node; | 1382 typedef compiler::Node Node; |
| 1361 typedef CodeStubAssembler::Variable Variable; | 1383 typedef CodeStubAssembler::Variable Variable; |
| 1384 CodeStubAssembler assembler(state); |
| 1362 | 1385 |
| 1363 Variable var_value(assembler, MachineRepresentation::kTagged); | 1386 Variable var_value(&assembler, MachineRepresentation::kTagged); |
| 1364 Variable var_done(assembler, MachineRepresentation::kTagged); | 1387 Variable var_done(&assembler, MachineRepresentation::kTagged); |
| 1365 | 1388 |
| 1366 var_value.Bind(assembler->UndefinedConstant()); | 1389 var_value.Bind(assembler.UndefinedConstant()); |
| 1367 var_done.Bind(assembler->BooleanConstant(true)); | 1390 var_done.Bind(assembler.BooleanConstant(true)); |
| 1368 | 1391 |
| 1369 Label throw_bad_receiver(assembler), next_codepoint(assembler), | 1392 Label throw_bad_receiver(&assembler), next_codepoint(&assembler), |
| 1370 return_result(assembler); | 1393 return_result(&assembler); |
| 1371 | 1394 |
| 1372 Node* iterator = assembler->Parameter(0); | 1395 Node* iterator = assembler.Parameter(0); |
| 1373 Node* context = assembler->Parameter(3); | 1396 Node* context = assembler.Parameter(3); |
| 1374 | 1397 |
| 1375 assembler->GotoIf(assembler->TaggedIsSmi(iterator), &throw_bad_receiver); | 1398 assembler.GotoIf(assembler.TaggedIsSmi(iterator), &throw_bad_receiver); |
| 1376 assembler->GotoUnless( | 1399 assembler.GotoUnless( |
| 1377 assembler->WordEqual(assembler->LoadInstanceType(iterator), | 1400 assembler.WordEqual(assembler.LoadInstanceType(iterator), |
| 1378 assembler->Int32Constant(JS_STRING_ITERATOR_TYPE)), | 1401 assembler.Int32Constant(JS_STRING_ITERATOR_TYPE)), |
| 1379 &throw_bad_receiver); | 1402 &throw_bad_receiver); |
| 1380 | 1403 |
| 1381 Node* string = | 1404 Node* string = |
| 1382 assembler->LoadObjectField(iterator, JSStringIterator::kStringOffset); | 1405 assembler.LoadObjectField(iterator, JSStringIterator::kStringOffset); |
| 1383 Node* position = | 1406 Node* position = |
| 1384 assembler->LoadObjectField(iterator, JSStringIterator::kNextIndexOffset); | 1407 assembler.LoadObjectField(iterator, JSStringIterator::kNextIndexOffset); |
| 1385 Node* length = assembler->LoadObjectField(string, String::kLengthOffset); | 1408 Node* length = assembler.LoadObjectField(string, String::kLengthOffset); |
| 1386 | 1409 |
| 1387 assembler->Branch(assembler->SmiLessThan(position, length), &next_codepoint, | 1410 assembler.Branch(assembler.SmiLessThan(position, length), &next_codepoint, |
| 1388 &return_result); | 1411 &return_result); |
| 1389 | 1412 |
| 1390 assembler->Bind(&next_codepoint); | 1413 assembler.Bind(&next_codepoint); |
| 1391 { | 1414 { |
| 1392 Node* ch = LoadSurrogatePairAt(assembler, string, length, position); | 1415 Node* ch = LoadSurrogatePairAt(&assembler, string, length, position); |
| 1393 Node* value = assembler->StringFromCodePoint(ch, UnicodeEncoding::UTF16); | 1416 Node* value = assembler.StringFromCodePoint(ch, UnicodeEncoding::UTF16); |
| 1394 var_value.Bind(value); | 1417 var_value.Bind(value); |
| 1395 Node* length = assembler->LoadObjectField(value, String::kLengthOffset); | 1418 Node* length = assembler.LoadObjectField(value, String::kLengthOffset); |
| 1396 assembler->StoreObjectFieldNoWriteBarrier( | 1419 assembler.StoreObjectFieldNoWriteBarrier( |
| 1397 iterator, JSStringIterator::kNextIndexOffset, | 1420 iterator, JSStringIterator::kNextIndexOffset, |
| 1398 assembler->SmiAdd(position, length)); | 1421 assembler.SmiAdd(position, length)); |
| 1399 var_done.Bind(assembler->BooleanConstant(false)); | 1422 var_done.Bind(assembler.BooleanConstant(false)); |
| 1400 assembler->Goto(&return_result); | 1423 assembler.Goto(&return_result); |
| 1401 } | 1424 } |
| 1402 | 1425 |
| 1403 assembler->Bind(&return_result); | 1426 assembler.Bind(&return_result); |
| 1404 { | 1427 { |
| 1405 Node* native_context = assembler->LoadNativeContext(context); | 1428 Node* native_context = assembler.LoadNativeContext(context); |
| 1406 Node* map = assembler->LoadFixedArrayElement( | 1429 Node* map = assembler.LoadFixedArrayElement( |
| 1407 native_context, | 1430 native_context, |
| 1408 assembler->IntPtrConstant(Context::ITERATOR_RESULT_MAP_INDEX), 0, | 1431 assembler.IntPtrConstant(Context::ITERATOR_RESULT_MAP_INDEX), 0, |
| 1409 CodeStubAssembler::INTPTR_PARAMETERS); | 1432 CodeStubAssembler::INTPTR_PARAMETERS); |
| 1410 Node* result = assembler->Allocate(JSIteratorResult::kSize); | 1433 Node* result = assembler.Allocate(JSIteratorResult::kSize); |
| 1411 assembler->StoreMapNoWriteBarrier(result, map); | 1434 assembler.StoreMapNoWriteBarrier(result, map); |
| 1412 assembler->StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset, | 1435 assembler.StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset, |
| 1413 Heap::kEmptyFixedArrayRootIndex); | 1436 Heap::kEmptyFixedArrayRootIndex); |
| 1414 assembler->StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset, | 1437 assembler.StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset, |
| 1415 Heap::kEmptyFixedArrayRootIndex); | 1438 Heap::kEmptyFixedArrayRootIndex); |
| 1416 assembler->StoreObjectFieldNoWriteBarrier( | 1439 assembler.StoreObjectFieldNoWriteBarrier( |
| 1417 result, JSIteratorResult::kValueOffset, var_value.value()); | 1440 result, JSIteratorResult::kValueOffset, var_value.value()); |
| 1418 assembler->StoreObjectFieldNoWriteBarrier( | 1441 assembler.StoreObjectFieldNoWriteBarrier( |
| 1419 result, JSIteratorResult::kDoneOffset, var_done.value()); | 1442 result, JSIteratorResult::kDoneOffset, var_done.value()); |
| 1420 assembler->Return(result); | 1443 assembler.Return(result); |
| 1421 } | 1444 } |
| 1422 | 1445 |
| 1423 assembler->Bind(&throw_bad_receiver); | 1446 assembler.Bind(&throw_bad_receiver); |
| 1424 { | 1447 { |
| 1425 // The {receiver} is not a valid JSGeneratorObject. | 1448 // The {receiver} is not a valid JSGeneratorObject. |
| 1426 Node* result = assembler->CallRuntime( | 1449 Node* result = assembler.CallRuntime( |
| 1427 Runtime::kThrowIncompatibleMethodReceiver, context, | 1450 Runtime::kThrowIncompatibleMethodReceiver, context, |
| 1428 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( | 1451 assembler.HeapConstant(assembler.factory()->NewStringFromAsciiChecked( |
| 1429 "String Iterator.prototype.next", TENURED)), | 1452 "String Iterator.prototype.next", TENURED)), |
| 1430 iterator); | 1453 iterator); |
| 1431 assembler->Return(result); // Never reached. | 1454 assembler.Return(result); // Never reached. |
| 1432 } | 1455 } |
| 1433 } | 1456 } |
| 1434 | 1457 |
| 1435 } // namespace internal | 1458 } // namespace internal |
| 1436 } // namespace v8 | 1459 } // namespace v8 |
| OLD | NEW |