summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/regexp-split.tq
blob: 8a9a30a7e90f3df96e111a7bba4612311776c23f (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
// Copyright 2019 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-regexp-gen.h'

namespace runtime {
  extern transitioning runtime
  RegExpSplit(implicit context: Context)(JSReceiver, String, Object): JSAny;
}  // namespace runtime

namespace regexp {

  const kMaxValueSmi: constexpr int31
  generates 'Smi::kMaxValue';

  extern transitioning macro RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(
      implicit context: Context)(JSRegExp, String, Smi): JSArray;

  // Helper that skips a few initial checks.
  transitioning builtin
  RegExpSplit(implicit context: Context)(
      regexp: FastJSRegExp, string: String, limit: JSAny): JSAny {
    let sanitizedLimit: Smi;

    // We need to be extra-strict and require the given limit to be either
    // undefined or a positive smi. We can't call ToUint32(maybe_limit) since
    // that might move us onto the slow path, resulting in ordering spec
    // violations (see https://crbug.com/801171).

    if (limit == Undefined) {
      // TODO(jgruber): In this case, we can probably avoid generation of limit
      // checks in Generate_RegExpPrototypeSplitBody.
      sanitizedLimit = SmiConstant(kMaxValueSmi);
    } else if (!TaggedIsPositiveSmi(limit)) {
      return runtime::RegExpSplit(regexp, string, limit);
    } else {
      sanitizedLimit = UnsafeCast<Smi>(limit);
    }

    // Due to specific shortcuts we take on the fast path (specifically, we
    // don't allocate a new regexp instance as specced), we need to ensure that
    // the given regexp is non-sticky to avoid invalid results. See
    // crbug.com/v8/6706.

    if (FastFlagGetter(regexp, kSticky)) {
      return runtime::RegExpSplit(regexp, string, sanitizedLimit);
    }

    // We're good to go on the fast path, which is inlined here.
    return RegExpPrototypeSplitBody(regexp, string, sanitizedLimit);
  }

  // ES#sec-regexp.prototype-@@split
  // RegExp.prototype [ @@split ] ( string, limit )
  transitioning javascript builtin RegExpPrototypeSplit(
      js-implicit context: Context, receiver: JSAny)(...arguments): JSAny {
    ThrowIfNotJSReceiver(
        receiver, kIncompatibleMethodReceiver, 'RegExp.prototype.@@split');
    const receiver = UnsafeCast<JSReceiver>(receiver);
    const string: String = ToString_Inline(context, arguments[0]);
    const limit = arguments[1];

    // Strict: Reads the flags property.
    // TODO(jgruber): Handle slow flag accesses on the fast path and make this
    // permissive.
    const fastRegExp = Cast<FastJSRegExp>(receiver)
        otherwise return runtime::RegExpSplit(receiver, string, limit);
    return RegExpSplit(fastRegExp, string, limit);
  }

}