| // 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, Flag::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: NativeContext, receiver: JSAny)(...arguments): JSAny { |
| ThrowIfNotJSReceiver( |
| receiver, MessageTemplate::kIncompatibleMethodReceiver, |
| 'RegExp.prototype.@@split'); |
| const receiver = UnsafeCast<JSReceiver>(receiver); |
| const string: String = ToString_Inline(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); |
| } |
| } |