• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include 'src/builtins/builtins-regexp-gen.h'
6
7namespace regexp {
8
9transitioning macro
10RegExpPrototypeSearchBodyFast(implicit context: Context)(
11    regexp: JSRegExp, string: String): JSAny {
12  assert(IsFastRegExpPermissive(regexp));
13
14  // Grab the initial value of last index.
15  const previousLastIndex: Smi = FastLoadLastIndex(regexp);
16
17  // Ensure last index is 0.
18  FastStoreLastIndex(regexp, 0);
19
20  // Call exec.
21  try {
22    const matchIndices: RegExpMatchInfo =
23        RegExpPrototypeExecBodyWithoutResultFast(
24            UnsafeCast<JSRegExp>(regexp), string)
25        otherwise DidNotMatch;
26
27    // Successful match.
28    // Reset last index.
29    FastStoreLastIndex(regexp, previousLastIndex);
30
31    // Return the index of the match.
32    return UnsafeCast<Smi>(
33        matchIndices.objects[kRegExpMatchInfoFirstCaptureIndex]);
34  } label DidNotMatch {
35    // Reset last index and return -1.
36    FastStoreLastIndex(regexp, previousLastIndex);
37    return SmiConstant(-1);
38  }
39}
40
41extern macro RegExpBuiltinsAssembler::BranchIfRegExpResult(
42    implicit context: Context)(Object): never labels IsUnmodified,
43    IsModified;
44
45macro
46IsRegExpResult(implicit context: Context)(execResult: HeapObject): bool {
47  BranchIfRegExpResult(execResult) otherwise return true, return false;
48}
49
50transitioning macro RegExpPrototypeSearchBodySlow(implicit context: Context)(
51    regexp: JSReceiver, string: String): JSAny {
52  // Grab the initial value of last index.
53  const previousLastIndex = SlowLoadLastIndex(regexp);
54  const smiZero: Smi = 0;
55
56  // Ensure last index is 0.
57  if (!SameValue(previousLastIndex, smiZero)) {
58    SlowStoreLastIndex(regexp, smiZero);
59  }
60
61  // Call exec.
62  const execResult = RegExpExec(regexp, string);
63
64  // Reset last index if necessary.
65  const currentLastIndex = SlowLoadLastIndex(regexp);
66  if (!SameValue(currentLastIndex, previousLastIndex)) {
67    SlowStoreLastIndex(regexp, previousLastIndex);
68  }
69
70  // Return -1 if no match was found.
71  if (execResult == Null) {
72    return SmiConstant(-1);
73  }
74
75  // Return the index of the match.
76  const fastExecResult = Cast<JSRegExpResult>(execResult)
77      otherwise return GetProperty(execResult, 'index');
78  return fastExecResult.index;
79}
80
81// Helper that skips a few initial checks. and assumes...
82// 1) receiver is a "fast permissive" RegExp
83// 2) pattern is a string
84transitioning builtin RegExpSearchFast(implicit context: Context)(
85    receiver: JSRegExp, string: String): JSAny {
86  return RegExpPrototypeSearchBodyFast(receiver, string);
87}
88
89// ES#sec-regexp.prototype-@@search
90// RegExp.prototype [ @@search ] ( string )
91transitioning javascript builtin RegExpPrototypeSearch(
92    js-implicit context: NativeContext, receiver: JSAny)(string: JSAny): JSAny {
93  ThrowIfNotJSReceiver(
94      receiver, MessageTemplate::kIncompatibleMethodReceiver,
95      'RegExp.prototype.@@search');
96  const receiver = UnsafeCast<JSReceiver>(receiver);
97  const string: String = ToString_Inline(string);
98
99  if (IsFastRegExpPermissive(receiver)) {
100    // TODO(pwong): Could be optimized to remove the overhead of calling the
101    //              builtin (at the cost of a larger builtin).
102    return RegExpSearchFast(UnsafeCast<JSRegExp>(receiver), string);
103  }
104  return RegExpPrototypeSearchBodySlow(receiver, string);
105}
106}
107