summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/builtins-string-gen.h
blob: 2420ad301404b1e7406249df2d72f99475bbe69e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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
144
145
146
147
148
149
150
151
152
153
154
155
156
// 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_

#include "src/code-stub-assembler.h"

namespace v8 {
namespace internal {

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

  // ES#sec-getsubstitution
  Node* GetSubstitution(Node* context, Node* subject_string,
                        Node* match_start_index, Node* match_end_index,
                        Node* replace_string);
  void StringEqual_Core(Node* context, Node* lhs, Node* lhs_instance_type,
                        Node* rhs, Node* rhs_instance_type,
                        TNode<IntPtrT> length, Label* if_equal,
                        Label* if_not_equal, Label* if_indirect);
  TNode<BoolT> IsStringPrimitiveWithNoCustomIteration(TNode<Object> object,
                                                      TNode<Context> context);

 protected:
  TNode<JSArray> StringToList(TNode<Context> context, TNode<String> string);

  void StringEqual_Loop(Node* lhs, Node* lhs_instance_type,
                        MachineType lhs_type, Node* rhs,
                        Node* rhs_instance_type, MachineType rhs_type,
                        TNode<IntPtrT> length, Label* if_equal,
                        Label* if_not_equal);
  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);

  Node* PointerToStringDataAtIndex(Node* const string_data, Node* const index,
                                   String::Encoding encoding);

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

  void GenerateStringEqual(Node* context, Node* left, Node* right);
  void GenerateStringRelationalComparison(Node* context, Node* left,
                                          Node* right, Operation op);

  TNode<Smi> ToSmiBetweenZeroAnd(SloppyTNode<Context> context,
                                 SloppyTNode<Object> value,
                                 SloppyTNode<Smi> limit);

  typedef std::function<TNode<Object>(
      TNode<String> receiver, TNode<IntPtrT> length, TNode<IntPtrT> index)>
      StringAtAccessor;

  void GenerateStringAt(const char* method_name, TNode<Context> context,
                        Node* receiver, TNode<Object> maybe_position,
                        TNode<Object> default_return,
                        const StringAtAccessor& accessor);

  TNode<Int32T> LoadSurrogatePairAt(SloppyTNode<String> string,
                                    SloppyTNode<IntPtrT> length,
                                    SloppyTNode<IntPtrT> index,
                                    UnicodeEncoding encoding);

  void StringIndexOf(Node* const subject_string, Node* const search_string,
                     Node* const position,
                     const std::function<void(Node*)>& f_return);

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

  TNode<JSArray> StringToArray(TNode<Context> context,
                               TNode<String> subject_string,
                               TNode<Smi> subject_length,
                               TNode<Number> limit_number);

  void RequireObjectCoercible(Node* const context, Node* const value,
                              const char* method_name);

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

  // 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.
  // Important: {regexp_call} may not contain any code that can call into JS.
  typedef std::function<void()> NodeFunction0;
  typedef std::function<void(Node* fn)> NodeFunction1;
  void MaybeCallFunctionAtSymbol(Node* const context, Node* const object,
                                 Node* const maybe_string,
                                 Handle<Symbol> symbol,
                                 const NodeFunction0& regexp_call,
                                 const NodeFunction1& generic_call);
};

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

 protected:
  enum SearchVariant { kIncludes, kIndexOf };

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

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

  void GotoIfNotWhiteSpaceOrLineTerminator(Node* const char_code,
                                           Label* const if_not_whitespace);

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

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

  void BuildLoop(Variable* const var_index, Node* const end, int increment,
                 Label* const if_none_found, Label* const out,
                 const std::function<Node*(Node*)>& get_character);
};

}  // namespace internal
}  // namespace v8

#endif  // V8_BUILTINS_BUILTINS_STRING_GEN_H_