// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/builtins/builtins-string-gen.h"

#include "src/builtins/builtins-regexp-gen.h"
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h"
#include "src/code-factory.h"
#include "src/factory-inl.h"
#include "src/objects.h"

namespace v8 {
namespace internal {

typedef CodeStubAssembler::RelationalComparisonMode RelationalComparisonMode;
typedef compiler::Node Node;
template <class A>
using TNode = compiler::TNode<A>;

Node* StringBuiltinsAssembler::DirectStringData(Node* string,
                                                Node* string_instance_type) {
  // Compute the effective offset of the first character.
  VARIABLE(var_data, MachineType::PointerRepresentation());
  Label if_sequential(this), if_external(this), if_join(this);
  Branch(Word32Equal(Word32And(string_instance_type,
                               Int32Constant(kStringRepresentationMask)),
                     Int32Constant(kSeqStringTag)),
         &if_sequential, &if_external);

  BIND(&if_sequential);
  {
    var_data.Bind(IntPtrAdd(
        IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag),
        BitcastTaggedToWord(string)));
    Goto(&if_join);
  }

  BIND(&if_external);
  {
    // This is only valid for ExternalStrings where the resource data
    // pointer is cached (i.e. no short external strings).
    CSA_ASSERT(
        this, Word32NotEqual(Word32And(string_instance_type,
                                       Int32Constant(kShortExternalStringMask)),
                             Int32Constant(kShortExternalStringTag)));
    var_data.Bind(LoadObjectField(string, ExternalString::kResourceDataOffset,
                                  MachineType::Pointer()));
    Goto(&if_join);
  }

  BIND(&if_join);
  return var_data.value();
}

void StringBuiltinsAssembler::DispatchOnStringEncodings(
    Node* const lhs_instance_type, Node* const rhs_instance_type,
    Label* if_one_one, Label* if_one_two, Label* if_two_one,
    Label* if_two_two) {
  STATIC_ASSERT(kStringEncodingMask == 0x8);
  STATIC_ASSERT(kTwoByteStringTag == 0x0);
  STATIC_ASSERT(kOneByteStringTag == 0x8);

  // First combine the encodings.

  Node* const encoding_mask = Int32Constant(kStringEncodingMask);
  Node* const lhs_encoding = Word32And(lhs_instance_type, encoding_mask);
  Node* const rhs_encoding = Word32And(rhs_instance_type, encoding_mask);

  Node* const combined_encodings =
      Word32Or(lhs_encoding, Word32Shr(rhs_encoding, 1));

  // Then dispatch on the combined encoding.

  Label unreachable(this, Label::kDeferred);

  int32_t values[] = {
      kOneByteStringTag | (kOneByteStringTag >> 1),
      kOneByteStringTag | (kTwoByteStringTag >> 1),
      kTwoByteStringTag | (kOneByteStringTag >> 1),
      kTwoByteStringTag | (kTwoByteStringTag >> 1),
  };
  Label* labels[] = {
      if_one_one, if_one_two, if_two_one, if_two_two,
  };

  STATIC_ASSERT(arraysize(values) == arraysize(labels));
  Switch(combined_encodings, &unreachable, values, labels, arraysize(values));

  BIND(&unreachable);
  Unreachable();
}

template <typename SubjectChar, typename PatternChar>
Node* StringBuiltinsAssembler::CallSearchStringRaw(Node* const subject_ptr,
                                                   Node* const subject_length,
                                                   Node* const search_ptr,
                                                   Node* const search_length,
                                                   Node* const start_position) {
  Node* const function_addr = ExternalConstant(
      ExternalReference::search_string_raw<SubjectChar, PatternChar>(
          isolate()));
  Node* const isolate_ptr =
      ExternalConstant(ExternalReference::isolate_address(isolate()));

  MachineType type_ptr = MachineType::Pointer();
  MachineType type_intptr = MachineType::IntPtr();

  Node* const result = CallCFunction6(
      type_intptr, type_ptr, type_ptr, type_intptr, type_ptr, type_intptr,
      type_intptr, function_addr, isolate_ptr, subject_ptr, subject_length,
      search_ptr, search_length, start_position);

  return result;
}

Node* StringBuiltinsAssembler::PointerToStringDataAtIndex(
    Node* const string_data, Node* const index, String::Encoding encoding) {
  const ElementsKind kind = (encoding == String::ONE_BYTE_ENCODING)
                                ? UINT8_ELEMENTS
                                : UINT16_ELEMENTS;
  Node* const offset_in_bytes =
      ElementOffsetFromIndex(index, kind, INTPTR_PARAMETERS);
  return IntPtrAdd(string_data, offset_in_bytes);
}

void StringBuiltinsAssembler::ConvertAndBoundsCheckStartArgument(
    Node* context, Variable* var_start, Node* start, Node* string_length) {
  TNode<Object> const start_int =
      ToInteger(context, start, CodeStubAssembler::kTruncateMinusZero);
  TNode<Smi> const zero = SmiConstant(0);

  Label done(this);
  Label if_issmi(this), if_isheapnumber(this, Label::kDeferred);
  Branch(TaggedIsSmi(start_int), &if_issmi, &if_isheapnumber);

  BIND(&if_issmi);
  {
    TNode<Smi> const start_int_smi = CAST(start_int);
    var_start->Bind(Select(
        SmiLessThan(start_int_smi, zero),
        [&] { return SmiMax(SmiAdd(string_length, start_int_smi), zero); },
        [&] { return start_int_smi; }, MachineRepresentation::kTagged));
    Goto(&done);
  }

  BIND(&if_isheapnumber);
  {
    // If {start} is a heap number, it is definitely out of bounds. If it is
    // negative, {start} = max({string_length} + {start}),0) = 0'. If it is
    // positive, set {start} to {string_length} which ultimately results in
    // returning an empty string.
    TNode<HeapNumber> const start_int_hn = CAST(start_int);
    TNode<Float64T> const float_zero = Float64Constant(0.);
    TNode<Float64T> const start_float = LoadHeapNumberValue(start_int_hn);
    var_start->Bind(SelectTaggedConstant<Smi>(
        Float64LessThan(start_float, float_zero), zero, string_length));
    Goto(&done);
  }
  BIND(&done);
}

void StringBuiltinsAssembler::GenerateStringEqual(Node* context, Node* left,
                                                  Node* right) {
  // Here's pseudo-code for the algorithm below:
  //
  // if (lhs->length() != rhs->length()) return false;
  // restart:
  // if (lhs == rhs) return true;
  // if (lhs->IsInternalizedString() && rhs->IsInternalizedString()) {
  //   return false;
  // }
  // if (lhs->IsSeqOneByteString() && rhs->IsSeqOneByteString()) {
  //   for (i = 0; i != lhs->length(); ++i) {
  //     if (lhs[i] != rhs[i]) return false;
  //   }
  //   return true;
  // }
  // if (lhs and/or rhs are indirect strings) {
  //   unwrap them and restart from the "restart:" label;
  // }
  // return %StringEqual(lhs, rhs);

  VARIABLE(var_left, MachineRepresentation::kTagged, left);
  VARIABLE(var_right, MachineRepresentation::kTagged, right);
  Variable* input_vars[2] = {&var_left, &var_right};
  Label if_equal(this), if_notequal(this), if_notbothdirectonebytestrings(this),
      restart(this, 2, input_vars);

  Node* lhs_length = LoadStringLength(left);
  Node* rhs_length = LoadStringLength(right);

  // Strings with different lengths cannot be equal.
  GotoIf(WordNotEqual(lhs_length, rhs_length), &if_notequal);

  Goto(&restart);
  BIND(&restart);
  Node* lhs = var_left.value();
  Node* rhs = var_right.value();

  Node* lhs_instance_type = LoadInstanceType(lhs);
  Node* rhs_instance_type = LoadInstanceType(rhs);

  StringEqual_Core(context, lhs, lhs_instance_type, lhs_length, rhs,
                   rhs_instance_type, &if_equal, &if_notequal,
                   &if_notbothdirectonebytestrings);

  BIND(&if_notbothdirectonebytestrings);
  {
    // Try to unwrap indirect strings, restart the above attempt on success.
    MaybeDerefIndirectStrings(&var_left, lhs_instance_type, &var_right,
                              rhs_instance_type, &restart);
    // TODO(bmeurer): Add support for two byte string equality checks.

    TailCallRuntime(Runtime::kStringEqual, context, lhs, rhs);
  }

  BIND(&if_equal);
  Return(TrueConstant());

  BIND(&if_notequal);
  Return(FalseConstant());
}

void StringBuiltinsAssembler::StringEqual_Core(
    Node* context, Node* lhs, Node* lhs_instance_type, Node* lhs_length,
    Node* rhs, Node* rhs_instance_type, Label* if_equal, Label* if_not_equal,
    Label* if_notbothdirectonebyte) {
  CSA_ASSERT(this, IsString(lhs));
  CSA_ASSERT(this, IsString(rhs));
  CSA_ASSERT(this, WordEqual(LoadStringLength(lhs), lhs_length));
  CSA_ASSERT(this, WordEqual(LoadStringLength(rhs), lhs_length));
  // Fast check to see if {lhs} and {rhs} refer to the same String object.
  GotoIf(WordEqual(lhs, rhs), if_equal);

  // Combine the instance types into a single 16-bit value, so we can check
  // both of them at once.
  Node* both_instance_types = Word32Or(
      lhs_instance_type, Word32Shl(rhs_instance_type, Int32Constant(8)));

  // Check if both {lhs} and {rhs} are internalized. Since we already know
  // that they're not the same object, they're not equal in that case.
  int const kBothInternalizedMask =
      kIsNotInternalizedMask | (kIsNotInternalizedMask << 8);
  int const kBothInternalizedTag = kInternalizedTag | (kInternalizedTag << 8);
  GotoIf(Word32Equal(Word32And(both_instance_types,
                               Int32Constant(kBothInternalizedMask)),
                     Int32Constant(kBothInternalizedTag)),
         if_not_equal);

  // Check that both {lhs} and {rhs} are flat one-byte strings, and that
  // in case of ExternalStrings the data pointer is cached..
  STATIC_ASSERT(kShortExternalStringTag != 0);
  int const kBothDirectOneByteStringMask =
      kStringEncodingMask | kIsIndirectStringMask | kShortExternalStringMask |
      ((kStringEncodingMask | kIsIndirectStringMask | kShortExternalStringMask)
       << 8);
  int const kBothDirectOneByteStringTag =
      kOneByteStringTag | (kOneByteStringTag << 8);
  GotoIfNot(Word32Equal(Word32And(both_instance_types,
                                  Int32Constant(kBothDirectOneByteStringMask)),
                        Int32Constant(kBothDirectOneByteStringTag)),
            if_notbothdirectonebyte);

  // At this point we know that we have two direct one-byte strings.

  // Compute the effective offset of the first character.
  Node* lhs_data = DirectStringData(lhs, lhs_instance_type);
  Node* rhs_data = DirectStringData(rhs, rhs_instance_type);

  // Compute the first offset after the string from the length.
  Node* length = SmiUntag(lhs_length);

  // Loop over the {lhs} and {rhs} strings to see if they are equal.
  VARIABLE(var_offset, MachineType::PointerRepresentation());
  Label loop(this, &var_offset);
  var_offset.Bind(IntPtrConstant(0));
  Goto(&loop);
  BIND(&loop);
  {
    // If {offset} equals {end}, no difference was found, so the
    // strings are equal.
    Node* offset = var_offset.value();
    GotoIf(WordEqual(offset, length), if_equal);

    // Load the next characters from {lhs} and {rhs}.
    Node* lhs_value = Load(MachineType::Uint8(), lhs_data, offset);
    Node* rhs_value = Load(MachineType::Uint8(), rhs_data, offset);

    // Check if the characters match.
    GotoIf(Word32NotEqual(lhs_value, rhs_value), if_not_equal);

    // Advance to next character.
    var_offset.Bind(IntPtrAdd(offset, IntPtrConstant(1)));
    Goto(&loop);
  }
}

void StringBuiltinsAssembler::GenerateStringRelationalComparison(
    Node* context, Node* left, Node* right, RelationalComparisonMode mode) {
  VARIABLE(var_left, MachineRepresentation::kTagged, left);
  VARIABLE(var_right, MachineRepresentation::kTagged, right);

  Variable* input_vars[2] = {&var_left, &var_right};
  Label if_less(this), if_equal(this), if_greater(this);
  Label restart(this, 2, input_vars);
  Goto(&restart);
  BIND(&restart);

  Node* lhs = var_left.value();
  Node* rhs = var_right.value();
  // Fast check to see if {lhs} and {rhs} refer to the same String object.
  GotoIf(WordEqual(lhs, rhs), &if_equal);

  // Load instance types of {lhs} and {rhs}.
  Node* lhs_instance_type = LoadInstanceType(lhs);
  Node* rhs_instance_type = LoadInstanceType(rhs);

  // Combine the instance types into a single 16-bit value, so we can check
  // both of them at once.
  Node* both_instance_types = Word32Or(
      lhs_instance_type, Word32Shl(rhs_instance_type, Int32Constant(8)));

  // Check that both {lhs} and {rhs} are flat one-byte strings.
  int const kBothSeqOneByteStringMask =
      kStringEncodingMask | kStringRepresentationMask |
      ((kStringEncodingMask | kStringRepresentationMask) << 8);
  int const kBothSeqOneByteStringTag =
      kOneByteStringTag | kSeqStringTag |
      ((kOneByteStringTag | kSeqStringTag) << 8);
  Label if_bothonebyteseqstrings(this), if_notbothonebyteseqstrings(this);
  Branch(Word32Equal(Word32And(both_instance_types,
                               Int32Constant(kBothSeqOneByteStringMask)),
                     Int32Constant(kBothSeqOneByteStringTag)),
         &if_bothonebyteseqstrings, &if_notbothonebyteseqstrings);

  BIND(&if_bothonebyteseqstrings);
  {
    // Load the length of {lhs} and {rhs}.
    Node* lhs_length = LoadStringLength(lhs);
    Node* rhs_length = LoadStringLength(rhs);

    // Determine the minimum length.
    Node* length = SmiMin(lhs_length, rhs_length);

    // Compute the effective offset of the first character.
    Node* begin =
        IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag);

    // Compute the first offset after the string from the length.
    Node* end = IntPtrAdd(begin, SmiUntag(length));

    // Loop over the {lhs} and {rhs} strings to see if they are equal.
    VARIABLE(var_offset, MachineType::PointerRepresentation());
    Label loop(this, &var_offset);
    var_offset.Bind(begin);
    Goto(&loop);
    BIND(&loop);
    {
      // Check if {offset} equals {end}.
      Node* offset = var_offset.value();
      Label if_done(this), if_notdone(this);
      Branch(WordEqual(offset, end), &if_done, &if_notdone);

      BIND(&if_notdone);
      {
        // Load the next characters from {lhs} and {rhs}.
        Node* lhs_value = Load(MachineType::Uint8(), lhs, offset);
        Node* rhs_value = Load(MachineType::Uint8(), rhs, offset);

        // Check if the characters match.
        Label if_valueissame(this), if_valueisnotsame(this);
        Branch(Word32Equal(lhs_value, rhs_value), &if_valueissame,
               &if_valueisnotsame);

        BIND(&if_valueissame);
        {
          // Advance to next character.
          var_offset.Bind(IntPtrAdd(offset, IntPtrConstant(1)));
        }
        Goto(&loop);

        BIND(&if_valueisnotsame);
        Branch(Uint32LessThan(lhs_value, rhs_value), &if_less, &if_greater);
      }

      BIND(&if_done);
      {
        // All characters up to the min length are equal, decide based on
        // string length.
        GotoIf(SmiEqual(lhs_length, rhs_length), &if_equal);
        BranchIfSmiLessThan(lhs_length, rhs_length, &if_less, &if_greater);
      }
    }
  }

  BIND(&if_notbothonebyteseqstrings);
  {
    // Try to unwrap indirect strings, restart the above attempt on success.
    MaybeDerefIndirectStrings(&var_left, lhs_instance_type, &var_right,
                              rhs_instance_type, &restart);
    // TODO(bmeurer): Add support for two byte string relational comparisons.
    switch (mode) {
      case RelationalComparisonMode::kLessThan:
        TailCallRuntime(Runtime::kStringLessThan, context, lhs, rhs);
        break;
      case RelationalComparisonMode::kLessThanOrEqual:
        TailCallRuntime(Runtime::kStringLessThanOrEqual, context, lhs, rhs);
        break;
      case RelationalComparisonMode::kGreaterThan:
        TailCallRuntime(Runtime::kStringGreaterThan, context, lhs, rhs);
        break;
      case RelationalComparisonMode::kGreaterThanOrEqual:
        TailCallRuntime(Runtime::kStringGreaterThanOrEqual, context, lhs, rhs);
        break;
    }
  }

  BIND(&if_less);
  switch (mode) {
    case RelationalComparisonMode::kLessThan:
    case RelationalComparisonMode::kLessThanOrEqual:
      Return(BooleanConstant(true));
      break;

    case RelationalComparisonMode::kGreaterThan:
    case RelationalComparisonMode::kGreaterThanOrEqual:
      Return(BooleanConstant(false));
      break;
  }

  BIND(&if_equal);
  switch (mode) {
    case RelationalComparisonMode::kLessThan:
    case RelationalComparisonMode::kGreaterThan:
      Return(BooleanConstant(false));
      break;

    case RelationalComparisonMode::kLessThanOrEqual:
    case RelationalComparisonMode::kGreaterThanOrEqual:
      Return(BooleanConstant(true));
      break;
  }

  BIND(&if_greater);
  switch (mode) {
    case RelationalComparisonMode::kLessThan:
    case RelationalComparisonMode::kLessThanOrEqual:
      Return(BooleanConstant(false));
      break;

    case RelationalComparisonMode::kGreaterThan:
    case RelationalComparisonMode::kGreaterThanOrEqual:
      Return(BooleanConstant(true));
      break;
  }
}

TF_BUILTIN(StringEqual, StringBuiltinsAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* left = Parameter(Descriptor::kLeft);
  Node* right = Parameter(Descriptor::kRight);
  GenerateStringEqual(context, left, right);
}

TF_BUILTIN(StringLessThan, StringBuiltinsAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* left = Parameter(Descriptor::kLeft);
  Node* right = Parameter(Descriptor::kRight);
  GenerateStringRelationalComparison(context, left, right,
                                     RelationalComparisonMode::kLessThan);
}

TF_BUILTIN(StringLessThanOrEqual, StringBuiltinsAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* left = Parameter(Descriptor::kLeft);
  Node* right = Parameter(Descriptor::kRight);
  GenerateStringRelationalComparison(
      context, left, right, RelationalComparisonMode::kLessThanOrEqual);
}

TF_BUILTIN(StringGreaterThan, StringBuiltinsAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* left = Parameter(Descriptor::kLeft);
  Node* right = Parameter(Descriptor::kRight);
  GenerateStringRelationalComparison(context, left, right,
                                     RelationalComparisonMode::kGreaterThan);
}

TF_BUILTIN(StringGreaterThanOrEqual, StringBuiltinsAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* left = Parameter(Descriptor::kLeft);
  Node* right = Parameter(Descriptor::kRight);
  GenerateStringRelationalComparison(
      context, left, right, RelationalComparisonMode::kGreaterThanOrEqual);
}

TF_BUILTIN(StringCharAt, CodeStubAssembler) {
  Node* receiver = Parameter(Descriptor::kReceiver);
  Node* position = Parameter(Descriptor::kPosition);

  // Load the character code at the {position} from the {receiver}.
  Node* code = StringCharCodeAt(receiver, position, INTPTR_PARAMETERS);

  // And return the single character string with only that {code}
  Node* result = StringFromCharCode(code);
  Return(result);
}

TF_BUILTIN(StringCharCodeAt, CodeStubAssembler) {
  Node* receiver = Parameter(Descriptor::kReceiver);
  Node* position = Parameter(Descriptor::kPosition);

  // Load the character code at the {position} from the {receiver}.
  Node* code = StringCharCodeAt(receiver, position, INTPTR_PARAMETERS);

  // And return it as TaggedSigned value.
  // TODO(turbofan): Allow builtins to return values untagged.
  Node* result = SmiFromWord32(code);
  Return(result);
}

// -----------------------------------------------------------------------------
// ES6 section 21.1 String Objects

// ES6 #sec-string.fromcharcode
TF_BUILTIN(StringFromCharCode, CodeStubAssembler) {
  // TODO(ishell): use constants from Descriptor once the JSFunction linkage
  // arguments are reordered.
  Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
  Node* context = Parameter(BuiltinDescriptor::kContext);

  CodeStubArguments arguments(this, ChangeInt32ToIntPtr(argc));
  // From now on use word-size argc value.
  argc = arguments.GetLength();

  // Check if we have exactly one argument (plus the implicit receiver), i.e.
  // if the parent frame is not an arguments adaptor frame.
  Label if_oneargument(this), if_notoneargument(this);
  Branch(WordEqual(argc, IntPtrConstant(1)), &if_oneargument,
         &if_notoneargument);

  BIND(&if_oneargument);
  {
    // Single argument case, perform fast single character string cache lookup
    // for one-byte code units, or fall back to creating a single character
    // string on the fly otherwise.
    Node* code = arguments.AtIndex(0);
    Node* code32 = TruncateTaggedToWord32(context, code);
    Node* code16 = Word32And(code32, Int32Constant(String::kMaxUtf16CodeUnit));
    Node* result = StringFromCharCode(code16);
    arguments.PopAndReturn(result);
  }

  Node* code16 = nullptr;
  BIND(&if_notoneargument);
  {
    Label two_byte(this);
    // Assume that the resulting string contains only one-byte characters.
    Node* one_byte_result = AllocateSeqOneByteString(context, argc);

    VARIABLE(max_index, MachineType::PointerRepresentation());
    max_index.Bind(IntPtrConstant(0));

    // Iterate over the incoming arguments, converting them to 8-bit character
    // codes. Stop if any of the conversions generates a code that doesn't fit
    // in 8 bits.
    CodeStubAssembler::VariableList vars({&max_index}, zone());
    arguments.ForEach(vars, [this, context, &two_byte, &max_index, &code16,
                             one_byte_result](Node* arg) {
      Node* code32 = TruncateTaggedToWord32(context, arg);
      code16 = Word32And(code32, Int32Constant(String::kMaxUtf16CodeUnit));

      GotoIf(
          Int32GreaterThan(code16, Int32Constant(String::kMaxOneByteCharCode)),
          &two_byte);

      // The {code16} fits into the SeqOneByteString {one_byte_result}.
      Node* offset = ElementOffsetFromIndex(
          max_index.value(), UINT8_ELEMENTS,
          CodeStubAssembler::INTPTR_PARAMETERS,
          SeqOneByteString::kHeaderSize - kHeapObjectTag);
      StoreNoWriteBarrier(MachineRepresentation::kWord8, one_byte_result,
                          offset, code16);
      max_index.Bind(IntPtrAdd(max_index.value(), IntPtrConstant(1)));
    });
    arguments.PopAndReturn(one_byte_result);

    BIND(&two_byte);

    // At least one of the characters in the string requires a 16-bit
    // representation.  Allocate a SeqTwoByteString to hold the resulting
    // string.
    Node* two_byte_result = AllocateSeqTwoByteString(context, argc);

    // Copy the characters that have already been put in the 8-bit string into
    // their corresponding positions in the new 16-bit string.
    Node* zero = IntPtrConstant(0);
    CopyStringCharacters(one_byte_result, two_byte_result, zero, zero,
                         max_index.value(), String::ONE_BYTE_ENCODING,
                         String::TWO_BYTE_ENCODING,
                         CodeStubAssembler::INTPTR_PARAMETERS);

    // Write the character that caused the 8-bit to 16-bit fault.
    Node* max_index_offset =
        ElementOffsetFromIndex(max_index.value(), UINT16_ELEMENTS,
                               CodeStubAssembler::INTPTR_PARAMETERS,
                               SeqTwoByteString::kHeaderSize - kHeapObjectTag);
    StoreNoWriteBarrier(MachineRepresentation::kWord16, two_byte_result,
                        max_index_offset, code16);
    max_index.Bind(IntPtrAdd(max_index.value(), IntPtrConstant(1)));

    // Resume copying the passed-in arguments from the same place where the
    // 8-bit copy stopped, but this time copying over all of the characters
    // using a 16-bit representation.
    arguments.ForEach(
        vars,
        [this, context, two_byte_result, &max_index](Node* arg) {
          Node* code32 = TruncateTaggedToWord32(context, arg);
          Node* code16 =
              Word32And(code32, Int32Constant(String::kMaxUtf16CodeUnit));

          Node* offset = ElementOffsetFromIndex(
              max_index.value(), UINT16_ELEMENTS,
              CodeStubAssembler::INTPTR_PARAMETERS,
              SeqTwoByteString::kHeaderSize - kHeapObjectTag);
          StoreNoWriteBarrier(MachineRepresentation::kWord16, two_byte_result,
                              offset, code16);
          max_index.Bind(IntPtrAdd(max_index.value(), IntPtrConstant(1)));
        },
        max_index.value());

    arguments.PopAndReturn(two_byte_result);
  }
}

// ES6 #sec-string.prototype.charat
TF_BUILTIN(StringPrototypeCharAt, CodeStubAssembler) {
  Node* receiver = Parameter(Descriptor::kReceiver);
  Node* position = Parameter(Descriptor::kPosition);
  Node* context = Parameter(Descriptor::kContext);

  // Check that {receiver} is coercible to Object and convert it to a String.
  receiver = ToThisString(context, receiver, "String.prototype.charAt");

  // Convert the {position} to a Smi and check that it's in bounds of the
  // {receiver}.
  {
    Label return_emptystring(this, Label::kDeferred);
    position =
        ToInteger(context, position, CodeStubAssembler::kTruncateMinusZero);
    GotoIfNot(TaggedIsSmi(position), &return_emptystring);

    // Determine the actual length of the {receiver} String.
    Node* receiver_length = LoadObjectField(receiver, String::kLengthOffset);

    // Return "" if the Smi {position} is outside the bounds of the {receiver}.
    Label if_positioninbounds(this);
    Branch(SmiAboveOrEqual(position, receiver_length), &return_emptystring,
           &if_positioninbounds);

    BIND(&return_emptystring);
    Return(EmptyStringConstant());

    BIND(&if_positioninbounds);
  }

  // Load the character code at the {position} from the {receiver}.
  Node* code = StringCharCodeAt(receiver, position);

  // And return the single character string with only that {code}.
  Node* result = StringFromCharCode(code);
  Return(result);
}

// ES6 #sec-string.prototype.charcodeat
TF_BUILTIN(StringPrototypeCharCodeAt, CodeStubAssembler) {
  Node* receiver = Parameter(Descriptor::kReceiver);
  Node* position = Parameter(Descriptor::kPosition);
  Node* context = Parameter(Descriptor::kContext);

  // Check that {receiver} is coercible to Object and convert it to a String.
  receiver = ToThisString(context, receiver, "String.prototype.charCodeAt");

  // Convert the {position} to a Smi and check that it's in bounds of the
  // {receiver}.
  {
    Label return_nan(this, Label::kDeferred);
    position =
        ToInteger(context, position, CodeStubAssembler::kTruncateMinusZero);
    GotoIfNot(TaggedIsSmi(position), &return_nan);

    // Determine the actual length of the {receiver} String.
    Node* receiver_length = LoadObjectField(receiver, String::kLengthOffset);

    // Return NaN if the Smi {position} is outside the bounds of the {receiver}.
    Label if_positioninbounds(this);
    Branch(SmiAboveOrEqual(position, receiver_length), &return_nan,
           &if_positioninbounds);

    BIND(&return_nan);
    Return(NaNConstant());

    BIND(&if_positioninbounds);
  }

  // Load the character at the {position} from the {receiver}.
  Node* value = StringCharCodeAt(receiver, position);
  Node* result = SmiFromWord32(value);
  Return(result);
}

// ES6 #sec-string.prototype.codepointat
TF_BUILTIN(StringPrototypeCodePointAt, StringBuiltinsAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* receiver = Parameter(Descriptor::kReceiver);
  Node* position = Parameter(Descriptor::kPosition);

  // Check that {receiver} is coercible to Object and convert it to a String.
  receiver = ToThisString(context, receiver, "String.prototype.codePointAt");

  // Convert the {position} to a Smi and check that it's in bounds of the
  // {receiver}.
  Label if_inbounds(this), if_outofbounds(this, Label::kDeferred);
  position =
      ToInteger(context, position, CodeStubAssembler::kTruncateMinusZero);
  GotoIfNot(TaggedIsSmi(position), &if_outofbounds);
  Node* receiver_length = LoadObjectField(receiver, String::kLengthOffset);
  Branch(SmiBelow(position, receiver_length), &if_inbounds, &if_outofbounds);

  BIND(&if_inbounds);
  {
    Node* value = LoadSurrogatePairAt(receiver, receiver_length, position,
                                      UnicodeEncoding::UTF32);
    Node* result = SmiFromWord32(value);
    Return(result);
  }

  BIND(&if_outofbounds);
  Return(UndefinedConstant());
}

// ES6 String.prototype.concat(...args)
// ES6 #sec-string.prototype.concat
TF_BUILTIN(StringPrototypeConcat, CodeStubAssembler) {
  // TODO(ishell): use constants from Descriptor once the JSFunction linkage
  // arguments are reordered.
  CodeStubArguments arguments(
      this, ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount)));
  Node* receiver = arguments.GetReceiver();
  Node* context = Parameter(BuiltinDescriptor::kContext);

  // Check that {receiver} is coercible to Object and convert it to a String.
  receiver = ToThisString(context, receiver, "String.prototype.concat");

  // Concatenate all the arguments passed to this builtin.
  VARIABLE(var_result, MachineRepresentation::kTagged);
  var_result.Bind(receiver);
  arguments.ForEach(
      CodeStubAssembler::VariableList({&var_result}, zone()),
      [this, context, &var_result](Node* arg) {
        arg = ToString_Inline(context, arg);
        var_result.Bind(CallStub(CodeFactory::StringAdd(isolate()), context,
                                 var_result.value(), arg));
      });
  arguments.PopAndReturn(var_result.value());
}

void StringBuiltinsAssembler::StringIndexOf(
    Node* const subject_string, Node* const search_string, Node* const position,
    std::function<void(Node*)> f_return) {
  CSA_ASSERT(this, IsString(subject_string));
  CSA_ASSERT(this, IsString(search_string));
  CSA_ASSERT(this, TaggedIsSmi(position));

  Node* const int_zero = IntPtrConstant(0);

  VARIABLE(var_needle_byte, MachineType::PointerRepresentation(), int_zero);
  VARIABLE(var_string_addr, MachineType::PointerRepresentation(), int_zero);

  Node* const search_length = SmiUntag(LoadStringLength(search_string));
  Node* const subject_length = SmiUntag(LoadStringLength(subject_string));
  Node* const start_position = IntPtrMax(SmiUntag(position), int_zero);

  Label zero_length_needle(this), return_minus_1(this);
  {
    GotoIf(IntPtrEqual(int_zero, search_length), &zero_length_needle);

    // Check that the needle fits in the start position.
    GotoIfNot(IntPtrLessThanOrEqual(search_length,
                                    IntPtrSub(subject_length, start_position)),
              &return_minus_1);
  }

  // If the string pointers are identical, we can just return 0. Note that this
  // implies {start_position} == 0 since we've passed the check above.
  Label return_zero(this);
  GotoIf(WordEqual(subject_string, search_string), &return_zero);

  // Try to unpack subject and search strings. Bail to runtime if either needs
  // to be flattened.
  ToDirectStringAssembler subject_to_direct(state(), subject_string);
  ToDirectStringAssembler search_to_direct(state(), search_string);

  Label call_runtime_unchecked(this, Label::kDeferred);

  subject_to_direct.TryToDirect(&call_runtime_unchecked);
  search_to_direct.TryToDirect(&call_runtime_unchecked);

  // Load pointers to string data.
  Node* const subject_ptr =
      subject_to_direct.PointerToData(&call_runtime_unchecked);
  Node* const search_ptr =
      search_to_direct.PointerToData(&call_runtime_unchecked);

  Node* const subject_offset = subject_to_direct.offset();
  Node* const search_offset = search_to_direct.offset();

  // Like String::IndexOf, the actual matching is done by the optimized
  // SearchString method in string-search.h. Dispatch based on string instance
  // types, then call straight into C++ for matching.

  CSA_ASSERT(this, IntPtrGreaterThan(search_length, int_zero));
  CSA_ASSERT(this, IntPtrGreaterThanOrEqual(start_position, int_zero));
  CSA_ASSERT(this, IntPtrGreaterThanOrEqual(subject_length, start_position));
  CSA_ASSERT(this,
             IntPtrLessThanOrEqual(search_length,
                                   IntPtrSub(subject_length, start_position)));

  Label one_one(this), one_two(this), two_one(this), two_two(this);
  DispatchOnStringEncodings(subject_to_direct.instance_type(),
                            search_to_direct.instance_type(), &one_one,
                            &one_two, &two_one, &two_two);

  typedef const uint8_t onebyte_t;
  typedef const uc16 twobyte_t;

  BIND(&one_one);
  {
    Node* const adjusted_subject_ptr = PointerToStringDataAtIndex(
        subject_ptr, subject_offset, String::ONE_BYTE_ENCODING);
    Node* const adjusted_search_ptr = PointerToStringDataAtIndex(
        search_ptr, search_offset, String::ONE_BYTE_ENCODING);

    Label direct_memchr_call(this), generic_fast_path(this);
    Branch(IntPtrEqual(search_length, IntPtrConstant(1)), &direct_memchr_call,
           &generic_fast_path);

    // An additional fast path that calls directly into memchr for 1-length
    // search strings.
    BIND(&direct_memchr_call);
    {
      Node* const string_addr = IntPtrAdd(adjusted_subject_ptr, start_position);
      Node* const search_length = IntPtrSub(subject_length, start_position);
      Node* const search_byte =
          ChangeInt32ToIntPtr(Load(MachineType::Uint8(), adjusted_search_ptr));

      Node* const memchr =
          ExternalConstant(ExternalReference::libc_memchr_function(isolate()));
      Node* const result_address =
          CallCFunction3(MachineType::Pointer(), MachineType::Pointer(),
                         MachineType::IntPtr(), MachineType::UintPtr(), memchr,
                         string_addr, search_byte, search_length);
      GotoIf(WordEqual(result_address, int_zero), &return_minus_1);
      Node* const result_index =
          IntPtrAdd(IntPtrSub(result_address, string_addr), start_position);
      f_return(SmiTag(result_index));
    }

    BIND(&generic_fast_path);
    {
      Node* const result = CallSearchStringRaw<onebyte_t, onebyte_t>(
          adjusted_subject_ptr, subject_length, adjusted_search_ptr,
          search_length, start_position);
      f_return(SmiTag(result));
    }
  }

  BIND(&one_two);
  {
    Node* const adjusted_subject_ptr = PointerToStringDataAtIndex(
        subject_ptr, subject_offset, String::ONE_BYTE_ENCODING);
    Node* const adjusted_search_ptr = PointerToStringDataAtIndex(
        search_ptr, search_offset, String::TWO_BYTE_ENCODING);

    Node* const result = CallSearchStringRaw<onebyte_t, twobyte_t>(
        adjusted_subject_ptr, subject_length, adjusted_search_ptr,
        search_length, start_position);
    f_return(SmiTag(result));
  }

  BIND(&two_one);
  {
    Node* const adjusted_subject_ptr = PointerToStringDataAtIndex(
        subject_ptr, subject_offset, String::TWO_BYTE_ENCODING);
    Node* const adjusted_search_ptr = PointerToStringDataAtIndex(
        search_ptr, search_offset, String::ONE_BYTE_ENCODING);

    Node* const result = CallSearchStringRaw<twobyte_t, onebyte_t>(
        adjusted_subject_ptr, subject_length, adjusted_search_ptr,
        search_length, start_position);
    f_return(SmiTag(result));
  }

  BIND(&two_two);
  {
    Node* const adjusted_subject_ptr = PointerToStringDataAtIndex(
        subject_ptr, subject_offset, String::TWO_BYTE_ENCODING);
    Node* const adjusted_search_ptr = PointerToStringDataAtIndex(
        search_ptr, search_offset, String::TWO_BYTE_ENCODING);

    Node* const result = CallSearchStringRaw<twobyte_t, twobyte_t>(
        adjusted_subject_ptr, subject_length, adjusted_search_ptr,
        search_length, start_position);
    f_return(SmiTag(result));
  }

  BIND(&return_minus_1);
  f_return(SmiConstant(-1));

  BIND(&return_zero);
  f_return(SmiConstant(0));

  BIND(&zero_length_needle);
  {
    Comment("0-length search_string");
    f_return(SmiTag(IntPtrMin(subject_length, start_position)));
  }

  BIND(&call_runtime_unchecked);
  {
    // Simplified version of the runtime call where the types of the arguments
    // are already known due to type checks in this stub.
    Comment("Call Runtime Unchecked");
    Node* result =
        CallRuntime(Runtime::kStringIndexOfUnchecked, NoContextConstant(),
                    subject_string, search_string, position);
    f_return(result);
  }
}

// ES6 String.prototype.indexOf(searchString [, position])
// #sec-string.prototype.indexof
// Unchecked helper for builtins lowering.
TF_BUILTIN(StringIndexOf, StringBuiltinsAssembler) {
  Node* receiver = Parameter(Descriptor::kReceiver);
  Node* search_string = Parameter(Descriptor::kSearchString);
  Node* position = Parameter(Descriptor::kPosition);
  StringIndexOf(receiver, search_string, position,
                [this](Node* result) { this->Return(result); });
}

// ES6 String.prototype.includes(searchString [, position])
// #sec-string.prototype.includes
TF_BUILTIN(StringPrototypeIncludes, StringIncludesIndexOfAssembler) {
  Generate(kIncludes);
}

// ES6 String.prototype.indexOf(searchString [, position])
// #sec-string.prototype.indexof
TF_BUILTIN(StringPrototypeIndexOf, StringIncludesIndexOfAssembler) {
  Generate(kIndexOf);
}

void StringIncludesIndexOfAssembler::Generate(SearchVariant variant) {
  // TODO(ishell): use constants from Descriptor once the JSFunction linkage
  // arguments are reordered.
  Node* argc = Parameter(BuiltinDescriptor::kArgumentsCount);
  Node* const context = Parameter(BuiltinDescriptor::kContext);
  CodeStubArguments arguments(this, ChangeInt32ToIntPtr(argc));
  Node* const receiver = arguments.GetReceiver();
  // From now on use word-size argc value.
  argc = arguments.GetLength();

  VARIABLE(var_search_string, MachineRepresentation::kTagged);
  VARIABLE(var_position, MachineRepresentation::kTagged);
  Label argc_1(this), argc_2(this), call_runtime(this, Label::kDeferred),
      fast_path(this);

  GotoIf(IntPtrEqual(argc, IntPtrConstant(1)), &argc_1);
  GotoIf(IntPtrGreaterThan(argc, IntPtrConstant(1)), &argc_2);
  {
    Comment("0 Argument case");
    CSA_ASSERT(this, IntPtrEqual(argc, IntPtrConstant(0)));
    Node* const undefined = UndefinedConstant();
    var_search_string.Bind(undefined);
    var_position.Bind(undefined);
    Goto(&call_runtime);
  }
  BIND(&argc_1);
  {
    Comment("1 Argument case");
    var_search_string.Bind(arguments.AtIndex(0));
    var_position.Bind(SmiConstant(0));
    Goto(&fast_path);
  }
  BIND(&argc_2);
  {
    Comment("2 Argument case");
    var_search_string.Bind(arguments.AtIndex(0));
    var_position.Bind(arguments.AtIndex(1));
    GotoIfNot(TaggedIsSmi(var_position.value()), &call_runtime);
    Goto(&fast_path);
  }
  BIND(&fast_path);
  {
    Comment("Fast Path");
    Node* const search = var_search_string.value();
    Node* const position = var_position.value();
    GotoIf(TaggedIsSmi(receiver), &call_runtime);
    GotoIf(TaggedIsSmi(search), &call_runtime);
    GotoIfNot(IsString(receiver), &call_runtime);
    GotoIfNot(IsString(search), &call_runtime);

    StringIndexOf(receiver, search, position, [&](Node* result) {
      CSA_ASSERT(this, TaggedIsSmi(result));
      arguments.PopAndReturn((variant == kIndexOf)
                                 ? result
                                 : SelectBooleanConstant(SmiGreaterThanOrEqual(
                                       result, SmiConstant(0))));
    });
  }
  BIND(&call_runtime);
  {
    Comment("Call Runtime");
    Runtime::FunctionId runtime = variant == kIndexOf
                                      ? Runtime::kStringIndexOf
                                      : Runtime::kStringIncludes;
    Node* const result =
        CallRuntime(runtime, context, receiver, var_search_string.value(),
                    var_position.value());
    arguments.PopAndReturn(result);
  }
}

compiler::Node* StringBuiltinsAssembler::IsNullOrUndefined(Node* const value) {
  return Word32Or(IsUndefined(value), IsNull(value));
}

void StringBuiltinsAssembler::RequireObjectCoercible(Node* const context,
                                                     Node* const value,
                                                     const char* method_name) {
  Label out(this), throw_exception(this, Label::kDeferred);
  Branch(IsNullOrUndefined(value), &throw_exception, &out);

  BIND(&throw_exception);
  TailCallRuntime(Runtime::kThrowCalledOnNullOrUndefined, context,
                  StringConstant(method_name));

  BIND(&out);
}

void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
    Node* const context, Node* const object, Handle<Symbol> symbol,
    const NodeFunction0& regexp_call, const NodeFunction1& generic_call,
    CodeStubArguments* args) {
  Label out(this);

  // Smis definitely don't have an attached symbol.
  GotoIf(TaggedIsSmi(object), &out);

  Node* const object_map = LoadMap(object);

  // Skip the slow lookup for Strings.
  {
    Label next(this);

    GotoIfNot(IsStringInstanceType(LoadMapInstanceType(object_map)), &next);

    Node* const native_context = LoadNativeContext(context);
    Node* const initial_proto_initial_map = LoadContextElement(
        native_context, Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX);

    Node* const string_fun =
        LoadContextElement(native_context, Context::STRING_FUNCTION_INDEX);
    Node* const initial_map =
        LoadObjectField(string_fun, JSFunction::kPrototypeOrInitialMapOffset);
    Node* const proto_map = LoadMap(CAST(LoadMapPrototype(initial_map)));

    Branch(WordEqual(proto_map, initial_proto_initial_map), &out, &next);

    BIND(&next);
  }

  // Take the fast path for RegExps.
  {
    Label stub_call(this), slow_lookup(this);

    RegExpBuiltinsAssembler regexp_asm(state());
    regexp_asm.BranchIfFastRegExp(context, object, object_map, &stub_call,
                                  &slow_lookup);

    BIND(&stub_call);
    Node* const result = regexp_call();
    if (args == nullptr) {
      Return(result);
    } else {
      args->PopAndReturn(result);
    }

    BIND(&slow_lookup);
  }

  GotoIf(IsNullOrUndefined(object), &out);

  // Fall back to a slow lookup of {object[symbol]}.
  //
  // The spec uses GetMethod({object}, {symbol}), which has a few quirks:
  // * null values are turned into undefined, and
  // * an exception is thrown if the value is not undefined, null, or callable.
  // We handle the former by jumping to {out} for null values as well, while
  // the latter is already handled by the Call({maybe_func}) operation.

  Node* const maybe_func = GetProperty(context, object, symbol);
  GotoIf(IsUndefined(maybe_func), &out);
  GotoIf(IsNull(maybe_func), &out);

  // Attempt to call the function.
  Node* const result = generic_call(maybe_func);
  if (args == nullptr) {
    Return(result);
  } else {
    args->PopAndReturn(result);
  }

  BIND(&out);
}

compiler::Node* StringBuiltinsAssembler::IndexOfDollarChar(Node* const context,
                                                           Node* const string) {
  CSA_ASSERT(this, IsString(string));

  Node* const dollar_string = HeapConstant(
      isolate()->factory()->LookupSingleCharacterStringFromCode('$'));
  Node* const dollar_ix = CallBuiltin(Builtins::kStringIndexOf, context, string,
                                      dollar_string, SmiConstant(0));

  CSA_ASSERT(this, TaggedIsSmi(dollar_ix));
  return dollar_ix;
}

compiler::Node* StringBuiltinsAssembler::GetSubstitution(
    Node* context, Node* subject_string, Node* match_start_index,
    Node* match_end_index, Node* replace_string) {
  CSA_ASSERT(this, IsString(subject_string));
  CSA_ASSERT(this, IsString(replace_string));
  CSA_ASSERT(this, TaggedIsPositiveSmi(match_start_index));
  CSA_ASSERT(this, TaggedIsPositiveSmi(match_end_index));

  VARIABLE(var_result, MachineRepresentation::kTagged, replace_string);
  Label runtime(this), out(this);

  // In this primitive implementation we simply look for the next '$' char in
  // {replace_string}. If it doesn't exist, we can simply return
  // {replace_string} itself. If it does, then we delegate to
  // String::GetSubstitution, passing in the index of the first '$' to avoid
  // repeated scanning work.
  // TODO(jgruber): Possibly extend this in the future to handle more complex
  // cases without runtime calls.

  Node* const dollar_index = IndexOfDollarChar(context, replace_string);
  Branch(SmiIsNegative(dollar_index), &out, &runtime);

  BIND(&runtime);
  {
    CSA_ASSERT(this, TaggedIsPositiveSmi(dollar_index));

    Callable substring_callable = CodeFactory::SubString(isolate());
    Node* const matched = CallStub(substring_callable, context, subject_string,
                                   match_start_index, match_end_index);
    Node* const replacement_string =
        CallRuntime(Runtime::kGetSubstitution, context, matched, subject_string,
                    match_start_index, replace_string, dollar_index);
    var_result.Bind(replacement_string);

    Goto(&out);
  }

  BIND(&out);
  return var_result.value();
}

// ES6 #sec-string.prototype.repeat
TF_BUILTIN(StringPrototypeRepeat, StringBuiltinsAssembler) {
  Label invalid_count(this), invalid_string_length(this),
      return_emptystring(this);

  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Node* const count = Parameter(Descriptor::kCount);
  Node* const string =
      ToThisString(context, receiver, "String.prototype.repeat");
  Node* const is_stringempty =
      SmiEqual(LoadStringLength(string), SmiConstant(0));

  VARIABLE(var_count, MachineRepresentation::kTagged,
           ToInteger(context, count, CodeStubAssembler::kTruncateMinusZero));

  // Verifies a valid count and takes a fast path when the result will be an
  // empty string.
  {
    Label next(this), if_count_isheapnumber(this, Label::kDeferred);

    GotoIfNot(TaggedIsSmi(var_count.value()), &if_count_isheapnumber);

    // If count is a SMI, throw a RangeError if less than 0 or greater than
    // the maximum string length.
    {
      GotoIf(SmiLessThan(var_count.value(), SmiConstant(0)), &invalid_count);
      GotoIf(SmiEqual(var_count.value(), SmiConstant(0)), &return_emptystring);
      GotoIf(is_stringempty, &return_emptystring);
      GotoIf(SmiGreaterThan(var_count.value(), SmiConstant(String::kMaxLength)),
             &invalid_string_length);
      Goto(&next);
    }

    // If count is a Heap Number...
    // 1) If count is Infinity, throw a RangeError exception
    // 2) If receiver is an empty string, return an empty string
    // 3) Otherwise, throw RangeError exception
    BIND(&if_count_isheapnumber);
    {
      CSA_ASSERT(this, IsNumberNormalized(var_count.value()));
      Node* const number_value = LoadHeapNumberValue(var_count.value());
      GotoIf(Float64Equal(number_value, Float64Constant(V8_INFINITY)),
             &invalid_count);
      GotoIf(Float64LessThan(number_value, Float64Constant(0.0)),
             &invalid_count);
      Branch(is_stringempty, &return_emptystring, &invalid_string_length);
    }
    BIND(&next);
  }

  // The receiver is repeated with the following algorithm:
  //   let n = count;
  //   let power_of_two_repeats = receiver;
  //   let result = "";
  //   while (true) {
  //     if (n & 1) result += s;
  //     n >>= 1;
  //     if (n === 0) return result;
  //     power_of_two_repeats += power_of_two_repeats;
  //   }
  {
    VARIABLE(var_result, MachineRepresentation::kTagged, EmptyStringConstant());
    VARIABLE(var_temp, MachineRepresentation::kTagged, string);

    Callable stringadd_callable =
        CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);

    Label loop(this, {&var_count, &var_result, &var_temp}), return_result(this);
    Goto(&loop);
    BIND(&loop);
    {
      {
        Label next(this);
        GotoIfNot(SmiToWord32(SmiAnd(var_count.value(), SmiConstant(1))),
                  &next);
        var_result.Bind(CallStub(stringadd_callable, context,
                                 var_result.value(), var_temp.value()));
        Goto(&next);
        BIND(&next);
      }

      var_count.Bind(SmiShr(var_count.value(), 1));
      GotoIf(SmiEqual(var_count.value(), SmiConstant(0)), &return_result);
      var_temp.Bind(CallStub(stringadd_callable, context, var_temp.value(),
                             var_temp.value()));
      Goto(&loop);
    }

    BIND(&return_result);
    Return(var_result.value());
  }

  BIND(&return_emptystring);
  Return(EmptyStringConstant());

  BIND(&invalid_count);
  {
    CallRuntime(Runtime::kThrowRangeError, context,
                SmiConstant(MessageTemplate::kInvalidCountValue),
                var_count.value());
    Unreachable();
  }
  BIND(&invalid_string_length);
  {
    CallRuntime(Runtime::kThrowInvalidStringLength, context);
    Unreachable();
  }
}

// ES6 #sec-string.prototype.replace
TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) {
  Label out(this);

  Node* const receiver = Parameter(Descriptor::kReceiver);
  Node* const search = Parameter(Descriptor::kSearch);
  Node* const replace = Parameter(Descriptor::kReplace);
  Node* const context = Parameter(Descriptor::kContext);

  Node* const smi_zero = SmiConstant(0);

  RequireObjectCoercible(context, receiver, "String.prototype.replace");

  // Redirect to replacer method if {search[@@replace]} is not undefined.

  MaybeCallFunctionAtSymbol(
      context, search, isolate()->factory()->replace_symbol(),
      [=]() {
        Node* const subject_string = ToString_Inline(context, receiver);

        return CallBuiltin(Builtins::kRegExpReplace, context, search,
                           subject_string, replace);
      },
      [=](Node* fn) {
        Callable call_callable = CodeFactory::Call(isolate());
        return CallJS(call_callable, context, fn, search, receiver, replace);
      });

  // Convert {receiver} and {search} to strings.

  Node* const subject_string = ToString_Inline(context, receiver);
  Node* const search_string = ToString_Inline(context, search);

  Node* const subject_length = LoadStringLength(subject_string);
  Node* const search_length = LoadStringLength(search_string);

  // Fast-path single-char {search}, long cons {receiver}, and simple string
  // {replace}.
  {
    Label next(this);

    GotoIfNot(SmiEqual(search_length, SmiConstant(1)), &next);
    GotoIfNot(SmiGreaterThan(subject_length, SmiConstant(0xFF)), &next);
    GotoIf(TaggedIsSmi(replace), &next);
    GotoIfNot(IsString(replace), &next);

    Node* const subject_instance_type = LoadInstanceType(subject_string);
    GotoIfNot(IsConsStringInstanceType(subject_instance_type), &next);

    GotoIf(TaggedIsPositiveSmi(IndexOfDollarChar(context, replace)), &next);

    // Searching by traversing a cons string tree and replace with cons of
    // slices works only when the replaced string is a single character, being
    // replaced by a simple string and only pays off for long strings.
    // TODO(jgruber): Reevaluate if this is still beneficial.
    // TODO(jgruber): TailCallRuntime when it correctly handles adapter frames.
    Return(CallRuntime(Runtime::kStringReplaceOneCharWithString, context,
                       subject_string, search_string, replace));

    BIND(&next);
  }

  // TODO(jgruber): Extend StringIndexOf to handle two-byte strings and
  // longer substrings - we can handle up to 8 chars (one-byte) / 4 chars
  // (2-byte).

  Node* const match_start_index =
      CallBuiltin(Builtins::kStringIndexOf, context, subject_string,
                  search_string, smi_zero);
  CSA_ASSERT(this, TaggedIsSmi(match_start_index));

  // Early exit if no match found.
  {
    Label next(this), return_subject(this);

    GotoIfNot(SmiIsNegative(match_start_index), &next);

    // The spec requires to perform ToString(replace) if the {replace} is not
    // callable even if we are going to exit here.
    // Since ToString() being applied to Smi does not have side effects for
    // numbers we can skip it.
    GotoIf(TaggedIsSmi(replace), &return_subject);
    GotoIf(IsCallableMap(LoadMap(replace)), &return_subject);

    // TODO(jgruber): Could introduce ToStringSideeffectsStub which only
    // performs observable parts of ToString.
    ToString_Inline(context, replace);
    Goto(&return_subject);

    BIND(&return_subject);
    Return(subject_string);

    BIND(&next);
  }

  Node* const match_end_index = SmiAdd(match_start_index, search_length);

  Callable substring_callable = CodeFactory::SubString(isolate());
  Callable stringadd_callable =
      CodeFactory::StringAdd(isolate(), STRING_ADD_CHECK_NONE, NOT_TENURED);

  VARIABLE(var_result, MachineRepresentation::kTagged, EmptyStringConstant());

  // Compute the prefix.
  {
    Label next(this);

    GotoIf(SmiEqual(match_start_index, smi_zero), &next);
    Node* const prefix = CallStub(substring_callable, context, subject_string,
                                  smi_zero, match_start_index);
    var_result.Bind(prefix);

    Goto(&next);
    BIND(&next);
  }

  // Compute the string to replace with.

  Label if_iscallablereplace(this), if_notcallablereplace(this);
  GotoIf(TaggedIsSmi(replace), &if_notcallablereplace);
  Branch(IsCallableMap(LoadMap(replace)), &if_iscallablereplace,
         &if_notcallablereplace);

  BIND(&if_iscallablereplace);
  {
    Callable call_callable = CodeFactory::Call(isolate());
    Node* const replacement =
        CallJS(call_callable, context, replace, UndefinedConstant(),
               search_string, match_start_index, subject_string);
    Node* const replacement_string = ToString_Inline(context, replacement);
    var_result.Bind(CallStub(stringadd_callable, context, var_result.value(),
                             replacement_string));
    Goto(&out);
  }

  BIND(&if_notcallablereplace);
  {
    Node* const replace_string = ToString_Inline(context, replace);
    Node* const replacement =
        GetSubstitution(context, subject_string, match_start_index,
                        match_end_index, replace_string);
    var_result.Bind(
        CallStub(stringadd_callable, context, var_result.value(), replacement));
    Goto(&out);
  }

  BIND(&out);
  {
    Node* const suffix = CallStub(substring_callable, context, subject_string,
                                  match_end_index, subject_length);
    Node* const result =
        CallStub(stringadd_callable, context, var_result.value(), suffix);
    Return(result);
  }
}

// ES6 section 21.1.3.18 String.prototype.slice ( start, end )
TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) {
  Label out(this);
  VARIABLE(var_start, MachineRepresentation::kTagged);
  VARIABLE(var_end, MachineRepresentation::kTagged);

  const int kStart = 0;
  const int kEnd = 1;
  Node* argc =
      ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
  CodeStubArguments args(this, argc);
  Node* const receiver = args.GetReceiver();
  Node* const start = args.GetOptionalArgumentValue(kStart);
  Node* const end = args.GetOptionalArgumentValue(kEnd);
  Node* const context = Parameter(BuiltinDescriptor::kContext);

  TNode<Smi> const smi_zero = SmiConstant(0);

  // 1. Let O be ? RequireObjectCoercible(this value).
  RequireObjectCoercible(context, receiver, "String.prototype.slice");

  // 2. Let S be ? ToString(O).
  Node* const subject_string =
      CallBuiltin(Builtins::kToString, context, receiver);

  // 3. Let len be the number of elements in S.
  Node* const length = LoadStringLength(subject_string);

  // Conversions and bounds-checks for {start}.
  ConvertAndBoundsCheckStartArgument(context, &var_start, start, length);

  // 5. If end is undefined, let intEnd be len;
  var_end.Bind(length);
  GotoIf(WordEqual(end, UndefinedConstant()), &out);

  // else let intEnd be ? ToInteger(end).
  Node* const end_int =
      ToInteger(context, end, CodeStubAssembler::kTruncateMinusZero);

  // 7. If intEnd < 0, let to be max(len + intEnd, 0);
  //    otherwise let to be min(intEnd, len).
  Label if_issmi(this), if_isheapnumber(this, Label::kDeferred);
  Branch(TaggedIsSmi(end_int), &if_issmi, &if_isheapnumber);

  BIND(&if_issmi);
  {
    Node* const length_plus_end = SmiAdd(length, end_int);
    var_end.Bind(Select(SmiLessThan(end_int, smi_zero),
                        [&] { return SmiMax(length_plus_end, smi_zero); },
                        [&] { return SmiMin(length, end_int); },
                        MachineRepresentation::kTagged));
    Goto(&out);
  }

  BIND(&if_isheapnumber);
  {
    // If {end} is a heap number, it is definitely out of bounds. If it is
    // negative, {int_end} = max({length} + {int_end}),0) = 0'. If it is
    // positive, set {int_end} to {length} which ultimately results in
    // returning an empty string.
    Node* const float_zero = Float64Constant(0.);
    Node* const end_float = LoadHeapNumberValue(end_int);
    var_end.Bind(SelectTaggedConstant<Smi>(
        Float64LessThan(end_float, float_zero), smi_zero, length));
    Goto(&out);
  }

  Label return_emptystring(this);
  BIND(&out);
  {
    GotoIf(SmiLessThanOrEqual(var_end.value(), var_start.value()),
           &return_emptystring);
    Node* const result =
        SubString(context, subject_string, var_start.value(), var_end.value(),
                  SubStringFlags::FROM_TO_ARE_BOUNDED);
    args.PopAndReturn(result);
  }

  BIND(&return_emptystring);
  args.PopAndReturn(EmptyStringConstant());
}

// ES6 section 21.1.3.19 String.prototype.split ( separator, limit )
TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
  const int kSeparatorArg = 0;
  const int kLimitArg = 1;

  Node* const argc =
      ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
  CodeStubArguments args(this, argc);

  Node* const receiver = args.GetReceiver();
  Node* const separator = args.GetOptionalArgumentValue(kSeparatorArg);
  Node* const limit = args.GetOptionalArgumentValue(kLimitArg);
  Node* const context = Parameter(BuiltinDescriptor::kContext);

  Node* const smi_zero = SmiConstant(0);

  RequireObjectCoercible(context, receiver, "String.prototype.split");

  // Redirect to splitter method if {separator[@@split]} is not undefined.

  MaybeCallFunctionAtSymbol(
      context, separator, isolate()->factory()->split_symbol(),
      [=]() {
        Node* const subject_string = ToString_Inline(context, receiver);

        return CallBuiltin(Builtins::kRegExpSplit, context, separator,
                           subject_string, limit);
      },
      [=](Node* fn) {
        Callable call_callable = CodeFactory::Call(isolate());
        return CallJS(call_callable, context, fn, separator, receiver, limit);
      },
      &args);

  // String and integer conversions.

  Node* const subject_string = ToString_Inline(context, receiver);
  Node* const limit_number =
      Select(IsUndefined(limit), [=]() { return NumberConstant(kMaxUInt32); },
             [=]() { return ToUint32(context, limit); },
             MachineRepresentation::kTagged);
  Node* const separator_string = ToString_Inline(context, separator);

  // Shortcut for {limit} == 0.
  {
    Label next(this);
    GotoIfNot(SmiEqual(limit_number, smi_zero), &next);

    const ElementsKind kind = PACKED_ELEMENTS;
    Node* const native_context = LoadNativeContext(context);
    Node* const array_map = LoadJSArrayElementsMap(kind, native_context);

    Node* const length = smi_zero;
    Node* const capacity = IntPtrConstant(0);
    Node* const result = AllocateJSArray(kind, array_map, capacity, length);

    args.PopAndReturn(result);

    BIND(&next);
  }

  // ECMA-262 says that if {separator} is undefined, the result should
  // be an array of size 1 containing the entire string.
  {
    Label next(this);
    GotoIfNot(IsUndefined(separator), &next);

    const ElementsKind kind = PACKED_ELEMENTS;
    Node* const native_context = LoadNativeContext(context);
    Node* const array_map = LoadJSArrayElementsMap(kind, native_context);

    Node* const length = SmiConstant(1);
    Node* const capacity = IntPtrConstant(1);
    Node* const result = AllocateJSArray(kind, array_map, capacity, length);

    Node* const fixed_array = LoadElements(result);
    StoreFixedArrayElement(fixed_array, 0, subject_string);

    args.PopAndReturn(result);

    BIND(&next);
  }

  // If the separator string is empty then return the elements in the subject.
  {
    Label next(this);
    GotoIfNot(SmiEqual(LoadStringLength(separator_string), smi_zero), &next);

    Node* const result = CallRuntime(Runtime::kStringToArray, context,
                                     subject_string, limit_number);
    args.PopAndReturn(result);

    BIND(&next);
  }

  Node* const result =
      CallRuntime(Runtime::kStringSplit, context, subject_string,
                  separator_string, limit_number);
  args.PopAndReturn(result);
}

// ES6 #sec-string.prototype.substr
TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
  const int kStartArg = 0;
  const int kLengthArg = 1;

  Node* const argc =
      ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
  CodeStubArguments args(this, argc);

  Node* const receiver = args.GetReceiver();
  Node* const start = args.GetOptionalArgumentValue(kStartArg);
  Node* const length = args.GetOptionalArgumentValue(kLengthArg);
  Node* const context = Parameter(BuiltinDescriptor::kContext);

  Label out(this);

  VARIABLE(var_start, MachineRepresentation::kTagged);
  VARIABLE(var_length, MachineRepresentation::kTagged);

  Node* const zero = SmiConstant(0);

  // Check that {receiver} is coercible to Object and convert it to a String.
  Node* const string =
      ToThisString(context, receiver, "String.prototype.substr");

  Node* const string_length = LoadStringLength(string);

  // Conversions and bounds-checks for {start}.
  ConvertAndBoundsCheckStartArgument(context, &var_start, start, string_length);

  // Conversions and bounds-checks for {length}.
  Label if_issmi(this), if_isheapnumber(this, Label::kDeferred);

  // Default to {string_length} if {length} is undefined.
  {
    Label if_isundefined(this, Label::kDeferred), if_isnotundefined(this);
    Branch(WordEqual(length, UndefinedConstant()), &if_isundefined,
           &if_isnotundefined);

    BIND(&if_isundefined);
    var_length.Bind(string_length);
    Goto(&if_issmi);

    BIND(&if_isnotundefined);
    var_length.Bind(
        ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero));
  }

  Branch(TaggedIsSmi(var_length.value()), &if_issmi, &if_isheapnumber);

  // Set {length} to min(max({length}, 0), {string_length} - {start}
  BIND(&if_issmi);
  {
    Node* const positive_length = SmiMax(var_length.value(), zero);

    Node* const minimal_length = SmiSub(string_length, var_start.value());
    var_length.Bind(SmiMin(positive_length, minimal_length));

    GotoIfNot(SmiLessThanOrEqual(var_length.value(), zero), &out);
    args.PopAndReturn(EmptyStringConstant());
  }

  BIND(&if_isheapnumber);
  {
    // If {length} is a heap number, it is definitely out of bounds. There are
    // two cases according to the spec: if it is negative, "" is returned; if
    // it is positive, then length is set to {string_length} - {start}.

    CSA_ASSERT(this, IsHeapNumber(var_length.value()));

    Label if_isnegative(this), if_ispositive(this);
    Node* const float_zero = Float64Constant(0.);
    Node* const length_float = LoadHeapNumberValue(var_length.value());
    Branch(Float64LessThan(length_float, float_zero), &if_isnegative,
           &if_ispositive);

    BIND(&if_isnegative);
    args.PopAndReturn(EmptyStringConstant());

    BIND(&if_ispositive);
    {
      var_length.Bind(SmiSub(string_length, var_start.value()));
      GotoIfNot(SmiLessThanOrEqual(var_length.value(), zero), &out);
      args.PopAndReturn(EmptyStringConstant());
    }
  }

  BIND(&out);
  {
    Node* const end = SmiAdd(var_start.value(), var_length.value());
    Node* const result = SubString(context, string, var_start.value(), end);
    args.PopAndReturn(result);
  }
}

TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd(
    SloppyTNode<Context> context, SloppyTNode<Object> value,
    SloppyTNode<Smi> limit) {
  Label out(this);
  TVARIABLE(Smi, var_result);

  TNode<Object> const value_int =
      this->ToInteger(context, value, CodeStubAssembler::kTruncateMinusZero);

  Label if_issmi(this), if_isnotsmi(this, Label::kDeferred);
  Branch(TaggedIsSmi(value_int), &if_issmi, &if_isnotsmi);

  BIND(&if_issmi);
  {
    Label if_isinbounds(this), if_isoutofbounds(this, Label::kDeferred);
    Branch(SmiAbove(value_int, limit), &if_isoutofbounds, &if_isinbounds);

    BIND(&if_isinbounds);
    {
      var_result = CAST(value_int);
      Goto(&out);
    }

    BIND(&if_isoutofbounds);
    {
      TNode<Smi> const zero = SmiConstant(0);
      var_result =
          SelectTaggedConstant(SmiLessThan(value_int, zero), zero, limit);
      Goto(&out);
    }
  }

  BIND(&if_isnotsmi);
  {
    // {value} is a heap number - in this case, it is definitely out of bounds.
    TNode<HeapNumber> value_int_hn = CAST(value_int);

    TNode<Float64T> const float_zero = Float64Constant(0.);
    TNode<Smi> const smi_zero = SmiConstant(0);
    TNode<Float64T> const value_float = LoadHeapNumberValue(value_int_hn);
    var_result = SelectTaggedConstant(Float64LessThan(value_float, float_zero),
                                      smi_zero, limit);
    Goto(&out);
  }

  BIND(&out);
  return var_result;
}

// ES6 #sec-string.prototype.substring
TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) {
  const int kStartArg = 0;
  const int kEndArg = 1;

  Node* const argc =
      ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
  CodeStubArguments args(this, argc);

  Node* const receiver = args.GetReceiver();
  Node* const start = args.GetOptionalArgumentValue(kStartArg);
  Node* const end = args.GetOptionalArgumentValue(kEndArg);
  Node* const context = Parameter(BuiltinDescriptor::kContext);

  Label out(this);

  VARIABLE(var_start, MachineRepresentation::kTagged);
  VARIABLE(var_end, MachineRepresentation::kTagged);

  // Check that {receiver} is coercible to Object and convert it to a String.
  Node* const string =
      ToThisString(context, receiver, "String.prototype.substring");

  Node* const length = LoadStringLength(string);

  // Conversion and bounds-checks for {start}.
  var_start.Bind(ToSmiBetweenZeroAnd(context, start, length));

  // Conversion and bounds-checks for {end}.
  {
    var_end.Bind(length);
    GotoIf(WordEqual(end, UndefinedConstant()), &out);

    var_end.Bind(ToSmiBetweenZeroAnd(context, end, length));

    Label if_endislessthanstart(this);
    Branch(SmiLessThan(var_end.value(), var_start.value()),
           &if_endislessthanstart, &out);

    BIND(&if_endislessthanstart);
    {
      Node* const tmp = var_end.value();
      var_end.Bind(var_start.value());
      var_start.Bind(tmp);
      Goto(&out);
    }
  }

  BIND(&out);
  {
    Node* result =
        SubString(context, string, var_start.value(), var_end.value());
    args.PopAndReturn(result);
  }
}

// ES6 #sec-string.prototype.trim
TF_BUILTIN(StringPrototypeTrim, StringTrimAssembler) {
  Generate(String::kTrim, "String.prototype.trim");
}

// Non-standard WebKit extension
TF_BUILTIN(StringPrototypeTrimLeft, StringTrimAssembler) {
  Generate(String::kTrimLeft, "String.prototype.trimLeft");
}

// Non-standard WebKit extension
TF_BUILTIN(StringPrototypeTrimRight, StringTrimAssembler) {
  Generate(String::kTrimRight, "String.prototype.trimRight");
}

void StringTrimAssembler::Generate(String::TrimMode mode,
                                   const char* method_name) {
  Label return_emptystring(this), if_runtime(this);

  Node* const argc = Parameter(BuiltinDescriptor::kArgumentsCount);
  Node* const context = Parameter(BuiltinDescriptor::kContext);
  CodeStubArguments arguments(this, ChangeInt32ToIntPtr(argc));
  Node* const receiver = arguments.GetReceiver();

  // Check that {receiver} is coercible to Object and convert it to a String.
  Node* const string = ToThisString(context, receiver, method_name);
  Node* const string_length = SmiUntag(LoadStringLength(string));

  ToDirectStringAssembler to_direct(state(), string);
  to_direct.TryToDirect(&if_runtime);
  Node* const string_data = to_direct.PointerToData(&if_runtime);
  Node* const instance_type = to_direct.instance_type();
  Node* const is_stringonebyte = IsOneByteStringInstanceType(instance_type);
  Node* const string_data_offset = to_direct.offset();

  VARIABLE(var_start, MachineType::PointerRepresentation(), IntPtrConstant(0));
  VARIABLE(var_end, MachineType::PointerRepresentation(),
           IntPtrSub(string_length, IntPtrConstant(1)));

  if (mode == String::kTrimLeft || mode == String::kTrim) {
    ScanForNonWhiteSpaceOrLineTerminator(string_data, string_data_offset,
                                         is_stringonebyte, &var_start,
                                         string_length, 1, &return_emptystring);
  }
  if (mode == String::kTrimRight || mode == String::kTrim) {
    ScanForNonWhiteSpaceOrLineTerminator(
        string_data, string_data_offset, is_stringonebyte, &var_end,
        IntPtrConstant(-1), -1, &return_emptystring);
  }

  arguments.PopAndReturn(
      SubString(context, string, SmiTag(var_start.value()),
                SmiAdd(SmiTag(var_end.value()), SmiConstant(1)),
                SubStringFlags::FROM_TO_ARE_BOUNDED));

  BIND(&if_runtime);
  arguments.PopAndReturn(CallRuntime(Runtime::kStringTrim, context, string,
                                     SmiConstant(static_cast<int>(mode))));

  BIND(&return_emptystring);
  arguments.PopAndReturn(EmptyStringConstant());
}

void StringTrimAssembler::ScanForNonWhiteSpaceOrLineTerminator(
    Node* const string_data, Node* const string_data_offset,
    Node* const is_stringonebyte, Variable* const var_index, Node* const end,
    int increment, Label* const if_none_found) {
  Label if_stringisonebyte(this), out(this);

  GotoIf(is_stringonebyte, &if_stringisonebyte);

  // Two Byte String
  BuildLoop(
      var_index, end, increment, if_none_found, &out, [&](Node* const index) {
        return Load(
            MachineType::Uint16(), string_data,
            WordShl(IntPtrAdd(index, string_data_offset), IntPtrConstant(1)));
      });

  BIND(&if_stringisonebyte);
  BuildLoop(var_index, end, increment, if_none_found, &out,
            [&](Node* const index) {
              return Load(MachineType::Uint8(), string_data,
                          IntPtrAdd(index, string_data_offset));
            });

  BIND(&out);
}

void StringTrimAssembler::BuildLoop(Variable* const var_index, Node* const end,
                                    int increment, Label* const if_none_found,
                                    Label* const out,
                                    std::function<Node*(Node*)> get_character) {
  Label loop(this, var_index);
  Goto(&loop);
  BIND(&loop);
  {
    Node* const index = var_index->value();
    GotoIf(IntPtrEqual(index, end), if_none_found);
    GotoIfNotWhiteSpaceOrLineTerminator(
        UncheckedCast<Uint32T>(get_character(index)), out);
    Increment(var_index, increment);
    Goto(&loop);
  }
}

void StringTrimAssembler::GotoIfNotWhiteSpaceOrLineTerminator(
    Node* const char_code, Label* const if_not_whitespace) {
  Label out(this);

  // 0x0020 - SPACE (Intentionally out of order to fast path a commmon case)
  GotoIf(Word32Equal(char_code, Int32Constant(0x0020)), &out);

  // 0x0009 - HORIZONTAL TAB
  GotoIf(Uint32LessThan(char_code, Int32Constant(0x0009)), if_not_whitespace);
  // 0x000A - LINE FEED OR NEW LINE
  // 0x000B - VERTICAL TAB
  // 0x000C - FORMFEED
  // 0x000D - HORIZONTAL TAB
  GotoIf(Uint32LessThanOrEqual(char_code, Int32Constant(0x000D)), &out);

  // Common Non-whitespace characters
  GotoIf(Uint32LessThan(char_code, Int32Constant(0x00A0)), if_not_whitespace);

  // 0x00A0 - NO-BREAK SPACE
  GotoIf(Word32Equal(char_code, Int32Constant(0x00A0)), &out);

  // 0x1680 - Ogham Space Mark
  GotoIf(Word32Equal(char_code, Int32Constant(0x1680)), &out);

  // 0x2000 - EN QUAD
  GotoIf(Uint32LessThan(char_code, Int32Constant(0x2000)), if_not_whitespace);
  // 0x2001 - EM QUAD
  // 0x2002 - EN SPACE
  // 0x2003 - EM SPACE
  // 0x2004 - THREE-PER-EM SPACE
  // 0x2005 - FOUR-PER-EM SPACE
  // 0x2006 - SIX-PER-EM SPACE
  // 0x2007 - FIGURE SPACE
  // 0x2008 - PUNCTUATION SPACE
  // 0x2009 - THIN SPACE
  // 0x200A - HAIR SPACE
  GotoIf(Uint32LessThanOrEqual(char_code, Int32Constant(0x200A)), &out);

  // 0x2028 - LINE SEPARATOR
  GotoIf(Word32Equal(char_code, Int32Constant(0x2028)), &out);
  // 0x2029 - PARAGRAPH SEPARATOR
  GotoIf(Word32Equal(char_code, Int32Constant(0x2029)), &out);
  // 0x202F - NARROW NO-BREAK SPACE
  GotoIf(Word32Equal(char_code, Int32Constant(0x202F)), &out);
  // 0x205F - MEDIUM MATHEMATICAL SPACE
  GotoIf(Word32Equal(char_code, Int32Constant(0x205F)), &out);
  // 0xFEFF - BYTE ORDER MARK
  GotoIf(Word32Equal(char_code, Int32Constant(0xFEFF)), &out);
  // 0x3000 - IDEOGRAPHIC SPACE
  Branch(Word32Equal(char_code, Int32Constant(0x3000)), &out,
         if_not_whitespace);

  BIND(&out);
}

// ES6 #sec-string.prototype.tostring
TF_BUILTIN(StringPrototypeToString, CodeStubAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* receiver = Parameter(Descriptor::kReceiver);

  Node* result = ToThisValue(context, receiver, PrimitiveType::kString,
                             "String.prototype.toString");
  Return(result);
}

// ES6 #sec-string.prototype.valueof
TF_BUILTIN(StringPrototypeValueOf, CodeStubAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* receiver = Parameter(Descriptor::kReceiver);

  Node* result = ToThisValue(context, receiver, PrimitiveType::kString,
                             "String.prototype.valueOf");
  Return(result);
}

TF_BUILTIN(StringPrototypeIterator, CodeStubAssembler) {
  Node* context = Parameter(Descriptor::kContext);
  Node* receiver = Parameter(Descriptor::kReceiver);

  Node* string =
      ToThisString(context, receiver, "String.prototype[Symbol.iterator]");

  Node* native_context = LoadNativeContext(context);
  Node* map =
      LoadContextElement(native_context, Context::STRING_ITERATOR_MAP_INDEX);
  Node* iterator = Allocate(JSStringIterator::kSize);
  StoreMapNoWriteBarrier(iterator, map);
  StoreObjectFieldRoot(iterator, JSValue::kPropertiesOrHashOffset,
                       Heap::kEmptyFixedArrayRootIndex);
  StoreObjectFieldRoot(iterator, JSObject::kElementsOffset,
                       Heap::kEmptyFixedArrayRootIndex);
  StoreObjectFieldNoWriteBarrier(iterator, JSStringIterator::kStringOffset,
                                 string);
  Node* index = SmiConstant(0);
  StoreObjectFieldNoWriteBarrier(iterator, JSStringIterator::kNextIndexOffset,
                                 index);
  Return(iterator);
}

// Return the |word32| codepoint at {index}. Supports SeqStrings and
// ExternalStrings.
TNode<Uint32T> StringBuiltinsAssembler::LoadSurrogatePairAt(
    SloppyTNode<String> string, SloppyTNode<Smi> length, SloppyTNode<Smi> index,
    UnicodeEncoding encoding) {
  Label handle_surrogate_pair(this), return_result(this);
  TVARIABLE(Uint32T, var_result);
  TVARIABLE(Uint32T, var_trail);
  var_result = StringCharCodeAt(string, index);
  var_trail = Unsigned(Int32Constant(0));

  GotoIf(Word32NotEqual(Word32And(var_result, Int32Constant(0xFC00)),
                        Int32Constant(0xD800)),
         &return_result);
  TNode<Smi> next_index = SmiAdd(index, SmiConstant(1));

  GotoIfNot(SmiLessThan(next_index, length), &return_result);
  var_trail = StringCharCodeAt(string, next_index);
  Branch(Word32Equal(Word32And(var_trail, Int32Constant(0xFC00)),
                     Int32Constant(0xDC00)),
         &handle_surrogate_pair, &return_result);

  BIND(&handle_surrogate_pair);
  {
    TNode<Uint32T> lead = var_result;
    TNode<Uint32T> trail = var_trail;

    // Check that this path is only taken if a surrogate pair is found
    CSA_SLOW_ASSERT(this,
                    Uint32GreaterThanOrEqual(lead, Int32Constant(0xD800)));
    CSA_SLOW_ASSERT(this, Uint32LessThan(lead, Int32Constant(0xDC00)));
    CSA_SLOW_ASSERT(this,
                    Uint32GreaterThanOrEqual(trail, Int32Constant(0xDC00)));
    CSA_SLOW_ASSERT(this, Uint32LessThan(trail, Int32Constant(0xE000)));

    switch (encoding) {
      case UnicodeEncoding::UTF16:
        var_result = Unsigned(Word32Or(
// Need to swap the order for big-endian platforms
#if V8_TARGET_BIG_ENDIAN
            Word32Shl(lead, Int32Constant(16)), trail));
#else
            Word32Shl(trail, Int32Constant(16)), lead));
#endif
        break;

      case UnicodeEncoding::UTF32: {
        // Convert UTF16 surrogate pair into |word32| code point, encoded as
        // UTF32.
        TNode<Int32T> surrogate_offset =
            Int32Constant(0x10000 - (0xD800 << 10) - 0xDC00);

        // (lead << 10) + trail + SURROGATE_OFFSET
        var_result = Unsigned(Int32Add(Word32Shl(lead, Int32Constant(10)),
                                       Int32Add(trail, surrogate_offset)));
        break;
      }
    }
    Goto(&return_result);
  }

  BIND(&return_result);
  return var_result;
}

// ES6 #sec-%stringiteratorprototype%.next
TF_BUILTIN(StringIteratorPrototypeNext, StringBuiltinsAssembler) {
  VARIABLE(var_value, MachineRepresentation::kTagged);
  VARIABLE(var_done, MachineRepresentation::kTagged);

  var_value.Bind(UndefinedConstant());
  var_done.Bind(BooleanConstant(true));

  Label throw_bad_receiver(this), next_codepoint(this), return_result(this);

  Node* context = Parameter(Descriptor::kContext);
  Node* iterator = Parameter(Descriptor::kReceiver);

  GotoIf(TaggedIsSmi(iterator), &throw_bad_receiver);
  GotoIfNot(Word32Equal(LoadInstanceType(iterator),
                        Int32Constant(JS_STRING_ITERATOR_TYPE)),
            &throw_bad_receiver);

  Node* string = LoadObjectField(iterator, JSStringIterator::kStringOffset);
  Node* position =
      LoadObjectField(iterator, JSStringIterator::kNextIndexOffset);
  Node* length = LoadObjectField(string, String::kLengthOffset);

  Branch(SmiLessThan(position, length), &next_codepoint, &return_result);

  BIND(&next_codepoint);
  {
    UnicodeEncoding encoding = UnicodeEncoding::UTF16;
    Node* ch = LoadSurrogatePairAt(string, length, position, encoding);
    Node* value = StringFromCodePoint(ch, encoding);
    var_value.Bind(value);
    Node* length = LoadObjectField(value, String::kLengthOffset);
    StoreObjectFieldNoWriteBarrier(iterator, JSStringIterator::kNextIndexOffset,
                                   SmiAdd(position, length));
    var_done.Bind(BooleanConstant(false));
    Goto(&return_result);
  }

  BIND(&return_result);
  {
    Node* result =
        AllocateJSIteratorResult(context, var_value.value(), var_done.value());
    Return(result);
  }

  BIND(&throw_bad_receiver);
  {
    // The {receiver} is not a valid JSGeneratorObject.
    CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context,
                StringConstant("String Iterator.prototype.next"), iterator);
    Unreachable();
  }
}

// -----------------------------------------------------------------------------
// ES6 section B.2.3 Additional Properties of the String.prototype object

class StringHtmlAssembler : public StringBuiltinsAssembler {
 public:
  explicit StringHtmlAssembler(compiler::CodeAssemblerState* state)
      : StringBuiltinsAssembler(state) {}

 protected:
  void Generate(Node* const context, Node* const receiver,
                const char* method_name, const char* tag_name) {
    Node* const string = ToThisString(context, receiver, method_name);
    std::string open_tag = "<" + std::string(tag_name) + ">";
    std::string close_tag = "</" + std::string(tag_name) + ">";

    Node* strings[] = {StringConstant(open_tag.c_str()), string,
                       StringConstant(close_tag.c_str())};
    Return(ConcatStrings(context, strings, arraysize(strings)));
  }

  void GenerateWithAttribute(Node* const context, Node* const receiver,
                             const char* method_name, const char* tag_name,
                             const char* attr, Node* const value) {
    Node* const string = ToThisString(context, receiver, method_name);
    Node* const value_string =
        EscapeQuotes(context, ToString_Inline(context, value));
    std::string open_tag_attr =
        "<" + std::string(tag_name) + " " + std::string(attr) + "=\"";
    std::string close_tag = "</" + std::string(tag_name) + ">";

    Node* strings[] = {StringConstant(open_tag_attr.c_str()), value_string,
                       StringConstant("\">"), string,
                       StringConstant(close_tag.c_str())};
    Return(ConcatStrings(context, strings, arraysize(strings)));
  }

  Node* ConcatStrings(Node* const context, Node** strings, int len) {
    VARIABLE(var_result, MachineRepresentation::kTagged, strings[0]);
    for (int i = 1; i < len; i++) {
      var_result.Bind(CallStub(CodeFactory::StringAdd(isolate()), context,
                               var_result.value(), strings[i]));
    }
    return var_result.value();
  }

  Node* EscapeQuotes(Node* const context, Node* const string) {
    CSA_ASSERT(this, IsString(string));
    Node* const regexp_function = LoadContextElement(
        LoadNativeContext(context), Context::REGEXP_FUNCTION_INDEX);
    Node* const initial_map = LoadObjectField(
        regexp_function, JSFunction::kPrototypeOrInitialMapOffset);
    // TODO(pwong): Refactor to not allocate RegExp
    Node* const regexp =
        CallRuntime(Runtime::kRegExpInitializeAndCompile, context,
                    AllocateJSObjectFromMap(initial_map), StringConstant("\""),
                    StringConstant("g"));

    return CallRuntime(Runtime::kRegExpInternalReplace, context, regexp, string,
                       StringConstant("&quot;"));
  }
};

// ES6 #sec-string.prototype.anchor
TF_BUILTIN(StringPrototypeAnchor, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Node* const value = Parameter(Descriptor::kValue);
  GenerateWithAttribute(context, receiver, "String.prototype.anchor", "a",
                        "name", value);
}

// ES6 #sec-string.prototype.big
TF_BUILTIN(StringPrototypeBig, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Generate(context, receiver, "String.prototype.big", "big");
}

// ES6 #sec-string.prototype.blink
TF_BUILTIN(StringPrototypeBlink, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Generate(context, receiver, "String.prototype.blink", "blink");
}

// ES6 #sec-string.prototype.bold
TF_BUILTIN(StringPrototypeBold, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Generate(context, receiver, "String.prototype.bold", "b");
}

// ES6 #sec-string.prototype.fontcolor
TF_BUILTIN(StringPrototypeFontcolor, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Node* const value = Parameter(Descriptor::kValue);
  GenerateWithAttribute(context, receiver, "String.prototype.fontcolor", "font",
                        "color", value);
}

// ES6 #sec-string.prototype.fontsize
TF_BUILTIN(StringPrototypeFontsize, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Node* const value = Parameter(Descriptor::kValue);
  GenerateWithAttribute(context, receiver, "String.prototype.fontsize", "font",
                        "size", value);
}

// ES6 #sec-string.prototype.fixed
TF_BUILTIN(StringPrototypeFixed, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Generate(context, receiver, "String.prototype.fixed", "tt");
}

// ES6 #sec-string.prototype.italics
TF_BUILTIN(StringPrototypeItalics, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Generate(context, receiver, "String.prototype.italics", "i");
}

// ES6 #sec-string.prototype.link
TF_BUILTIN(StringPrototypeLink, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Node* const value = Parameter(Descriptor::kValue);
  GenerateWithAttribute(context, receiver, "String.prototype.link", "a", "href",
                        value);
}

// ES6 #sec-string.prototype.small
TF_BUILTIN(StringPrototypeSmall, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Generate(context, receiver, "String.prototype.small", "small");
}

// ES6 #sec-string.prototype.strike
TF_BUILTIN(StringPrototypeStrike, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Generate(context, receiver, "String.prototype.strike", "strike");
}

// ES6 #sec-string.prototype.sub
TF_BUILTIN(StringPrototypeSub, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Generate(context, receiver, "String.prototype.sub", "sub");
}

// ES6 #sec-string.prototype.sup
TF_BUILTIN(StringPrototypeSup, StringHtmlAssembler) {
  Node* const context = Parameter(Descriptor::kContext);
  Node* const receiver = Parameter(Descriptor::kReceiver);
  Generate(context, receiver, "String.prototype.sup", "sup");
}

}  // namespace internal
}  // namespace v8
