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 |