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 |