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