builtins-string-gen.h 9.59 KB
Newer Older
1 2 3 4 5 6 7
// 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.

#ifndef V8_BUILTINS_BUILTINS_STRING_GEN_H_
#define V8_BUILTINS_BUILTINS_STRING_GEN_H_

8
#include "src/codegen/code-stub-assembler.h"
9 10 11 12 13 14 15 16 17 18

namespace v8 {
namespace internal {

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

  // ES#sec-getsubstitution
19 20 21 22 23
  TNode<String> GetSubstitution(TNode<Context> context,
                                TNode<String> subject_string,
                                TNode<Smi> match_start_index,
                                TNode<Smi> match_end_index,
                                TNode<String> replace_string);
24 25 26 27
  void StringEqual_Core(SloppyTNode<String> lhs, Node* lhs_instance_type,
                        SloppyTNode<String> rhs, Node* rhs_instance_type,
                        TNode<IntPtrT> length, Label* if_equal,
                        Label* if_not_equal, Label* if_indirect);
28 29 30 31
  void BranchIfStringPrimitiveWithNoCustomIteration(TNode<Object> object,
                                                    TNode<Context> context,
                                                    Label* if_true,
                                                    Label* if_false);
32

33 34 35 36 37
  TNode<Int32T> LoadSurrogatePairAt(SloppyTNode<String> string,
                                    SloppyTNode<IntPtrT> length,
                                    SloppyTNode<IntPtrT> index,
                                    UnicodeEncoding encoding);

38 39
  TNode<String> StringFromSingleUTF16EncodedCodePoint(TNode<Int32T> codepoint);

40 41
  // Return a new string object which holds a substring containing the range
  // [from,to[ of string.
42 43
  // TODO(v8:9880): Fix implementation to use UintPtrT arguments and drop
  // IntPtrT version once all callers use UintPtrT version.
44 45
  TNode<String> SubString(TNode<String> string, TNode<IntPtrT> from,
                          TNode<IntPtrT> to);
46 47 48 49
  TNode<String> SubString(TNode<String> string, TNode<UintPtrT> from,
                          TNode<UintPtrT> to) {
    return SubString(string, Signed(from), Signed(to));
  }
50 51 52 53 54 55 56 57 58 59 60 61 62

  // Copies |character_count| elements from |from_string| to |to_string|
  // starting at the |from_index|'th character. |from_string| and |to_string|
  // can either be one-byte strings or two-byte strings, although if
  // |from_string| is two-byte, then |to_string| must be two-byte.
  // |from_index|, |to_index| and |character_count| must be intptr_ts s.t. 0 <=
  // |from_index| <= |from_index| + |character_count| <= from_string.length and
  // 0 <= |to_index| <= |to_index| + |character_count| <= to_string.length.
  V8_EXPORT_PRIVATE void CopyStringCharacters(
      Node* from_string, Node* to_string, TNode<IntPtrT> from_index,
      TNode<IntPtrT> to_index, TNode<IntPtrT> character_count,
      String::Encoding from_encoding, String::Encoding to_encoding);

63
 protected:
64 65 66
  void StringEqual_Loop(Node* lhs, Node* lhs_instance_type,
                        MachineType lhs_type, Node* rhs,
                        Node* rhs_instance_type, MachineType rhs_type,
67 68
                        TNode<IntPtrT> length, Label* if_equal,
                        Label* if_not_equal);
69 70 71 72 73 74 75 76 77 78 79 80
  Node* DirectStringData(Node* string, Node* string_instance_type);

  void 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);

  template <typename SubjectChar, typename PatternChar>
  Node* CallSearchStringRaw(Node* const subject_ptr, Node* const subject_length,
                            Node* const search_ptr, Node* const search_length,
                            Node* const start_position);

81 82
  TNode<RawPtrT> PointerToStringDataAtIndex(TNode<RawPtrT> string_data,
                                            TNode<IntPtrT> index,
83
                                            String::Encoding encoding);
84 85 86 87 88

  // substr and slice have a common way of handling the {start} argument.
  void ConvertAndBoundsCheckStartArgument(Node* context, Variable* var_start,
                                          Node* start, Node* string_length);

89 90 91
  void GenerateStringEqual(TNode<String> left, TNode<String> right);
  void GenerateStringRelationalComparison(TNode<String> left,
                                          TNode<String> right, Operation op);
92

93 94
  using StringAtAccessor = std::function<TNode<Object>(
      TNode<String> receiver, TNode<IntPtrT> length, TNode<IntPtrT> index)>;
95

96 97 98
  void StringIndexOf(const TNode<String> subject_string,
                     const TNode<String> search_string,
                     const TNode<Smi> position,
99
                     const std::function<void(TNode<Smi>)>& f_return);
100

101
  TNode<Smi> IndexOfDollarChar(Node* const context, Node* const string);
102

103
  TNode<JSArray> StringToArray(TNode<NativeContext> context,
104 105 106 107
                               TNode<String> subject_string,
                               TNode<Smi> subject_length,
                               TNode<Number> limit_number);

108
  TNode<BoolT> SmiIsNegative(TNode<Smi> value) {
109 110 111
    return SmiLessThan(value, SmiConstant(0));
  }

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
  TNode<String> AllocateConsString(TNode<Uint32T> length, TNode<String> left,
                                   TNode<String> right);

  TNode<String> StringAdd(Node* context, TNode<String> left,
                          TNode<String> right);

  // Check if |string| is an indirect (thin or flat cons) string type that can
  // be dereferenced by DerefIndirectString.
  void BranchIfCanDerefIndirectString(TNode<String> string,
                                      TNode<Int32T> instance_type,
                                      Label* can_deref, Label* cannot_deref);
  // Allocate an appropriate one- or two-byte ConsString with the first and
  // second parts specified by |left| and |right|.
  // Unpack an indirect (thin or flat cons) string type.
  void DerefIndirectString(TVariable<String>* var_string,
                           TNode<Int32T> instance_type);
  // Check if |var_string| has an indirect (thin or flat cons) string type, and
  // unpack it if so.
  void MaybeDerefIndirectString(TVariable<String>* var_string,
                                TNode<Int32T> instance_type, Label* did_deref,
                                Label* cannot_deref);
  // Check if |var_left| or |var_right| has an indirect (thin or flat cons)
  // string type, and unpack it/them if so. Fall through if nothing was done.
  void MaybeDerefIndirectStrings(TVariable<String>* var_left,
                                 TNode<Int32T> left_instance_type,
                                 TVariable<String>* var_right,
                                 TNode<Int32T> right_instance_type,
                                 Label* did_something);
  TNode<String> DerefIndirectString(TNode<String> string,
                                    TNode<Int32T> instance_type,
                                    Label* cannot_deref);

144 145 146 147 148 149 150 151 152 153 154
  // Implements boilerplate logic for {match, split, replace, search} of the
  // form:
  //
  //  if (!IS_NULL_OR_UNDEFINED(object)) {
  //    var maybe_function = object[symbol];
  //    if (!IS_UNDEFINED(maybe_function)) {
  //      return %_Call(maybe_function, ...);
  //    }
  //  }
  //
  // Contains fast paths for Smi and RegExp objects.
155
  // Important: {regexp_call} may not contain any code that can call into JS.
156 157
  using NodeFunction0 = std::function<void()>;
  using NodeFunction1 = std::function<void(Node* fn)>;
158 159 160 161 162 163 164
  using DescriptorIndexNameValue =
      PrototypeCheckAssembler::DescriptorIndexNameValue;
  void MaybeCallFunctionAtSymbol(
      Node* const context, Node* const object, Node* const maybe_string,
      Handle<Symbol> symbol,
      DescriptorIndexNameValue additional_property_to_check,
      const NodeFunction0& regexp_call, const NodeFunction1& generic_call);
165 166 167 168 169 170

 private:
  TNode<String> AllocAndCopyStringCharacters(Node* from,
                                             Node* from_instance_type,
                                             TNode<IntPtrT> from_index,
                                             TNode<IntPtrT> character_count);
171 172
};

173 174 175 176 177 178 179 180
class StringIncludesIndexOfAssembler : public StringBuiltinsAssembler {
 public:
  explicit StringIncludesIndexOfAssembler(compiler::CodeAssemblerState* state)
      : StringBuiltinsAssembler(state) {}

 protected:
  enum SearchVariant { kIncludes, kIndexOf };

181 182
  void Generate(SearchVariant variant, TNode<IntPtrT> argc,
                TNode<Context> context);
183 184
};

185 186 187 188 189
class StringTrimAssembler : public StringBuiltinsAssembler {
 public:
  explicit StringTrimAssembler(compiler::CodeAssemblerState* state)
      : StringBuiltinsAssembler(state) {}

190
  V8_EXPORT_PRIVATE void GotoIfNotWhiteSpaceOrLineTerminator(
191
      const TNode<Word32T> char_code, Label* const if_not_whitespace);
192 193

 protected:
194 195
  void Generate(String::TrimMode mode, const char* method, TNode<IntPtrT> argc,
                TNode<Context> context);
196

197 198 199
  void ScanForNonWhiteSpaceOrLineTerminator(
      Node* const string_data, Node* const string_data_offset,
      Node* const is_stringonebyte, TVariable<IntPtrT>* const var_index,
200
      const TNode<IntPtrT> end, int increment, Label* const if_none_found);
201

202
  void BuildLoop(TVariable<IntPtrT>* const var_index, const TNode<IntPtrT> end,
203
                 int increment, Label* const if_none_found, Label* const out,
204
                 const std::function<Node*(Node*)>& get_character);
205 206
};

207 208 209 210
}  // namespace internal
}  // namespace v8

#endif  // V8_BUILTINS_BUILTINS_STRING_GEN_H_