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 runtime { 8extern transitioning runtime 9RegExpSplit(implicit context: Context)(JSReceiver, String, Object): JSAny; 10} // namespace runtime 11 12namespace regexp { 13 14const kMaxValueSmi: constexpr int31 15 generates 'Smi::kMaxValue'; 16 17extern transitioning macro RegExpBuiltinsAssembler::RegExpPrototypeSplitBody( 18 implicit context: Context)(JSRegExp, String, Smi): JSArray; 19 20// Helper that skips a few initial checks. 21transitioning builtin 22RegExpSplit(implicit context: Context)( 23 regexp: FastJSRegExp, string: String, limit: JSAny): JSAny { 24 let sanitizedLimit: Smi; 25 26 // We need to be extra-strict and require the given limit to be either 27 // undefined or a positive smi. We can't call ToUint32(maybe_limit) since 28 // that might move us onto the slow path, resulting in ordering spec 29 // violations (see https://crbug.com/801171). 30 31 if (limit == Undefined) { 32 // TODO(jgruber): In this case, we can probably avoid generation of limit 33 // checks in Generate_RegExpPrototypeSplitBody. 34 sanitizedLimit = SmiConstant(kMaxValueSmi); 35 } else if (!TaggedIsPositiveSmi(limit)) { 36 return runtime::RegExpSplit(regexp, string, limit); 37 } else { 38 sanitizedLimit = UnsafeCast<Smi>(limit); 39 } 40 41 // Due to specific shortcuts we take on the fast path (specifically, we 42 // don't allocate a new regexp instance as specced), we need to ensure that 43 // the given regexp is non-sticky to avoid invalid results. See 44 // crbug.com/v8/6706. 45 46 if (FastFlagGetter(regexp, Flag::kSticky)) { 47 return runtime::RegExpSplit(regexp, string, sanitizedLimit); 48 } 49 50 // We're good to go on the fast path, which is inlined here. 51 return RegExpPrototypeSplitBody(regexp, string, sanitizedLimit); 52} 53 54// ES#sec-regexp.prototype-@@split 55// RegExp.prototype [ @@split ] ( string, limit ) 56transitioning javascript builtin RegExpPrototypeSplit( 57 js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny { 58 ThrowIfNotJSReceiver( 59 receiver, MessageTemplate::kIncompatibleMethodReceiver, 60 'RegExp.prototype.@@split'); 61 const receiver = UnsafeCast<JSReceiver>(receiver); 62 const string: String = ToString_Inline(arguments[0]); 63 const limit = arguments[1]; 64 65 // Strict: Reads the flags property. 66 // TODO(jgruber): Handle slow flag accesses on the fast path and make this 67 // permissive. 68 const fastRegExp = Cast<FastJSRegExp>(receiver) 69 otherwise return runtime::RegExpSplit(receiver, string, limit); 70 return RegExpSplit(fastRegExp, string, limit); 71} 72} 73