Commit 95af75c1 authored by Z Nguyen-Huu's avatar Z Nguyen-Huu Committed by Commit Bot

[builtins] Port some RegExp builtins to Torque

RegExpPrototypeDotAllGetter, RegExpPrototypeGlobalGetter,
RegExpPrototypeIgnoreCaseGetter, RegExpPrototypeMultilineGetter,
RegExpPrototypeStickyGetter, RegExpPrototypeUnicodeGetter.

Bug: v8:8976
Change-Id: I2a5c19256cacc2438a6b40516565960f5c847205
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1764491
Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63406}
parent 14f1796f
......@@ -1768,6 +1768,8 @@ extern operator '&' macro Word32And(int32, int32): int32;
extern operator '&' macro Word32And(uint32, uint32): uint32;
extern operator '==' macro
ConstexprInt31Equal(constexpr int31, constexpr int31): constexpr bool;
extern operator '!=' macro
ConstexprInt31NotEqual(constexpr int31, constexpr int31): constexpr bool;
extern operator '>=' macro
ConstexprInt31GreaterThanEqual(
constexpr int31, constexpr int31): constexpr bool;
......
......@@ -847,27 +847,15 @@ namespace internal {
TFJ(RegExpPrototypeCompile, 2, kReceiver, kPattern, kFlags) \
/* ES #sec-regexp.prototype.exec */ \
TFJ(RegExpPrototypeExec, 1, kReceiver, kString) \
/* ES #sec-get-regexp.prototype.dotAll */ \
TFJ(RegExpPrototypeDotAllGetter, 0, kReceiver) \
/* ES #sec-get-regexp.prototype.flags */ \
TFJ(RegExpPrototypeFlagsGetter, 0, kReceiver) \
/* ES #sec-get-regexp.prototype.global */ \
TFJ(RegExpPrototypeGlobalGetter, 0, kReceiver) \
/* ES #sec-get-regexp.prototype.ignorecase */ \
TFJ(RegExpPrototypeIgnoreCaseGetter, 0, kReceiver) \
/* ES #sec-regexp.prototype-@@match */ \
TFJ(RegExpPrototypeMatch, 1, kReceiver, kString) \
/* https://tc39.github.io/proposal-string-matchall/ */ \
TFJ(RegExpPrototypeMatchAll, 1, kReceiver, kString) \
/* ES #sec-get-regexp.prototype.multiline */ \
TFJ(RegExpPrototypeMultilineGetter, 0, kReceiver) \
/* ES #sec-regexp.prototype-@@search */ \
TFJ(RegExpPrototypeSearch, 1, kReceiver, kString) \
/* ES #sec-get-regexp.prototype.sticky */ \
TFJ(RegExpPrototypeStickyGetter, 0, kReceiver) \
CPP(RegExpPrototypeToString) \
/* ES #sec-get-regexp.prototype.unicode */ \
TFJ(RegExpPrototypeUnicodeGetter, 0, kReceiver) \
CPP(RegExpRightContextGetter) \
\
/* ES #sec-regexp.prototype-@@split */ \
......
......@@ -1562,20 +1562,21 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) {
}
// Fast-path implementation for flag checks on an unmodified JSRegExp instance.
TNode<Int32T> RegExpBuiltinsAssembler::FastFlagGetter(TNode<JSRegExp> regexp,
TNode<BoolT> RegExpBuiltinsAssembler::FastFlagGetter(TNode<JSRegExp> regexp,
JSRegExp::Flag flag) {
TNode<Smi> flags = CAST(LoadObjectField(regexp, JSRegExp::kFlagsOffset));
TNode<Smi> mask = SmiConstant(flag);
return SmiToInt32(SmiShr(SmiAnd(flags, mask), base::bits::CountTrailingZeros(
static_cast<int>(flag))));
return ReinterpretCast<BoolT>(SmiToInt32(
SmiShr(SmiAnd(flags, mask),
base::bits::CountTrailingZeros(static_cast<int>(flag)))));
}
// Load through the GetProperty stub.
TNode<Int32T> RegExpBuiltinsAssembler::SlowFlagGetter(TNode<Context> context,
TNode<BoolT> RegExpBuiltinsAssembler::SlowFlagGetter(TNode<Context> context,
TNode<Object> regexp,
JSRegExp::Flag flag) {
Label out(this);
TVARIABLE(Int32T, var_result);
TVARIABLE(BoolT, var_result);
Handle<String> name;
switch (flag) {
......@@ -1607,18 +1608,18 @@ TNode<Int32T> RegExpBuiltinsAssembler::SlowFlagGetter(TNode<Context> context,
BranchIfToBooleanIsTrue(value, &if_true, &if_false);
BIND(&if_true);
var_result = Int32Constant(1);
var_result = BoolConstant(true);
Goto(&out);
BIND(&if_false);
var_result = Int32Constant(0);
var_result = BoolConstant(false);
Goto(&out);
BIND(&out);
return var_result.value();
}
TNode<Int32T> RegExpBuiltinsAssembler::FlagGetter(TNode<Context> context,
TNode<BoolT> RegExpBuiltinsAssembler::FlagGetter(TNode<Context> context,
TNode<Object> regexp,
JSRegExp::Flag flag,
bool is_fastpath) {
......@@ -1626,105 +1627,6 @@ TNode<Int32T> RegExpBuiltinsAssembler::FlagGetter(TNode<Context> context,
: SlowFlagGetter(context, regexp, flag);
}
void RegExpBuiltinsAssembler::FlagGetter(TNode<Context> context,
TNode<Object> receiver,
JSRegExp::Flag flag, int counter,
const char* method_name) {
// Check whether we have an unmodified regexp instance.
Label if_isunmodifiedjsregexp(this),
if_isnotunmodifiedjsregexp(this, Label::kDeferred);
GotoIf(TaggedIsSmi(receiver), &if_isnotunmodifiedjsregexp);
Branch(IsJSRegExp(CAST(receiver)), &if_isunmodifiedjsregexp,
&if_isnotunmodifiedjsregexp);
BIND(&if_isunmodifiedjsregexp);
{
// Refer to JSRegExp's flag property on the fast-path.
TNode<Int32T> is_flag_set = FastFlagGetter(CAST(receiver), flag);
Return(
SelectBooleanConstant(Word32NotEqual(is_flag_set, Int32Constant(0))));
}
BIND(&if_isnotunmodifiedjsregexp);
{
Label if_isprototype(this), if_isnotprototype(this);
Branch(IsReceiverInitialRegExpPrototype(context, receiver), &if_isprototype,
&if_isnotprototype);
BIND(&if_isprototype);
{
if (counter != -1) {
Node* const counter_smi = SmiConstant(counter);
CallRuntime(Runtime::kIncrementUseCounter, context, counter_smi);
}
Return(UndefinedConstant());
}
BIND(&if_isnotprototype);
{ ThrowTypeError(context, MessageTemplate::kRegExpNonRegExp, method_name); }
}
}
// ES6 21.2.5.4.
// ES #sec-get-regexp.prototype.global
TF_BUILTIN(RegExpPrototypeGlobalGetter, RegExpBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
FlagGetter(context, receiver, JSRegExp::kGlobal,
v8::Isolate::kRegExpPrototypeOldFlagGetter,
"RegExp.prototype.global");
}
// ES6 21.2.5.5.
// ES #sec-get-regexp.prototype.ignorecase
TF_BUILTIN(RegExpPrototypeIgnoreCaseGetter, RegExpBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
FlagGetter(context, receiver, JSRegExp::kIgnoreCase,
v8::Isolate::kRegExpPrototypeOldFlagGetter,
"RegExp.prototype.ignoreCase");
}
// ES6 21.2.5.7.
// ES #sec-get-regexp.prototype.multiline
TF_BUILTIN(RegExpPrototypeMultilineGetter, RegExpBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
FlagGetter(context, receiver, JSRegExp::kMultiline,
v8::Isolate::kRegExpPrototypeOldFlagGetter,
"RegExp.prototype.multiline");
}
// ES #sec-get-regexp.prototype.dotAll
TF_BUILTIN(RegExpPrototypeDotAllGetter, RegExpBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
static const int kNoCounter = -1;
FlagGetter(context, receiver, JSRegExp::kDotAll, kNoCounter,
"RegExp.prototype.dotAll");
}
// ES6 21.2.5.12.
// ES #sec-get-regexp.prototype.sticky
TF_BUILTIN(RegExpPrototypeStickyGetter, RegExpBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
FlagGetter(context, receiver, JSRegExp::kSticky,
v8::Isolate::kRegExpPrototypeStickyGetter,
"RegExp.prototype.sticky");
}
// ES6 21.2.5.15.
// ES #sec-get-regexp.prototype.unicode
TF_BUILTIN(RegExpPrototypeUnicodeGetter, RegExpBuiltinsAssembler) {
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver));
FlagGetter(context, receiver, JSRegExp::kUnicode,
v8::Isolate::kRegExpPrototypeUnicodeGetter,
"RegExp.prototype.unicode");
}
// ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
TNode<Object> RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp,
Node* string) {
......@@ -2035,8 +1937,8 @@ void RegExpMatchAllAssembler::Generate(TNode<Context> context,
TNode<String> string = ToString_Inline(context, maybe_string);
TVARIABLE(Object, var_matcher);
TVARIABLE(Int32T, var_global);
TVARIABLE(Int32T, var_unicode);
TVARIABLE(BoolT, var_global);
TVARIABLE(BoolT, var_unicode);
Label create_iterator(this), if_fast_regexp(this),
if_slow_regexp(this, Label::kDeferred);
......@@ -2105,8 +2007,7 @@ void RegExpMatchAllAssembler::Generate(TNode<Context> context,
TNode<Smi> global_ix =
CAST(CallBuiltin(Builtins::kStringIndexOf, context, flags_string,
global_char_string, SmiZero()));
var_global =
SelectInt32Constant(SmiEqual(global_ix, SmiConstant(-1)), 0, 1);
var_global = SmiNotEqual(global_ix, SmiConstant(-1));
// 11. If flags contains "u", let fullUnicode be true.
// 12. Else, let fullUnicode be false.
......@@ -2114,8 +2015,7 @@ void RegExpMatchAllAssembler::Generate(TNode<Context> context,
TNode<Smi> unicode_ix =
CAST(CallBuiltin(Builtins::kStringIndexOf, context, flags_string,
unicode_char_string, SmiZero()));
var_unicode =
SelectInt32Constant(SmiEqual(unicode_ix, SmiConstant(-1)), 0, 1);
var_unicode = SmiNotEqual(unicode_ix, SmiConstant(-1));
Goto(&create_iterator);
}
......@@ -2144,7 +2044,7 @@ void RegExpMatchAllAssembler::Generate(TNode<Context> context,
// CreateRegExpStringIterator ( R, S, global, fullUnicode )
TNode<Object> RegExpMatchAllAssembler::CreateRegExpStringIterator(
TNode<Context> native_context, TNode<Object> regexp, TNode<String> string,
TNode<Int32T> global, TNode<Int32T> full_unicode) {
TNode<BoolT> global, TNode<BoolT> full_unicode) {
TNode<Map> map = CAST(LoadContextElement(
native_context,
Context::INITIAL_REGEXP_STRING_ITERATOR_PROTOTYPE_MAP_INDEX));
......@@ -2168,23 +2068,15 @@ TNode<Object> RegExpMatchAllAssembler::CreateRegExpStringIterator(
StoreObjectFieldNoWriteBarrier(
iterator, JSRegExpStringIterator::kIteratedStringOffset, string);
#ifdef DEBUG
// Verify global and full_unicode can be bitwise shifted without masking.
TNode<Int32T> zero = Int32Constant(0);
TNode<Int32T> one = Int32Constant(1);
CSA_ASSERT(this,
Word32Or(Word32Equal(global, zero), Word32Equal(global, one)));
CSA_ASSERT(this, Word32Or(Word32Equal(full_unicode, zero),
Word32Equal(full_unicode, one)));
#endif // DEBUG
// 7. Set iterator.[[Global]] to global.
// 8. Set iterator.[[Unicode]] to fullUnicode.
// 9. Set iterator.[[Done]] to false.
TNode<Int32T> global_flag =
Word32Shl(global, Int32Constant(JSRegExpStringIterator::kGlobalBit));
TNode<Int32T> unicode_flag = Word32Shl(
full_unicode, Int32Constant(JSRegExpStringIterator::kUnicodeBit));
Word32Shl(ReinterpretCast<Int32T>(global),
Int32Constant(JSRegExpStringIterator::kGlobalBit));
TNode<Int32T> unicode_flag =
Word32Shl(ReinterpretCast<Int32T>(full_unicode),
Int32Constant(JSRegExpStringIterator::kUnicodeBit));
TNode<Word32T> iterator_flags = Word32Or(global_flag, unicode_flag);
StoreObjectFieldNoWriteBarrier(iterator, JSRegExpStringIterator::kFlagsOffset,
SmiFromInt32(Signed(iterator_flags)));
......
......@@ -154,21 +154,18 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
TNode<String> FlagsGetter(Node* const context, Node* const regexp,
bool is_fastpath);
TNode<Int32T> FastFlagGetter(TNode<JSRegExp> regexp, JSRegExp::Flag flag);
TNode<BoolT> FastFlagGetter(TNode<JSRegExp> regexp, JSRegExp::Flag flag);
TNode<BoolT> FastFlagGetterGlobal(TNode<JSRegExp> regexp) {
return ReinterpretCast<BoolT>(FastFlagGetter(regexp, JSRegExp::kGlobal));
return FastFlagGetter(regexp, JSRegExp::kGlobal);
}
TNode<BoolT> FastFlagGetterUnicode(TNode<JSRegExp> regexp) {
return ReinterpretCast<BoolT>(FastFlagGetter(regexp, JSRegExp::kUnicode));
return FastFlagGetter(regexp, JSRegExp::kUnicode);
}
TNode<Int32T> SlowFlagGetter(TNode<Context> context, TNode<Object> regexp,
TNode<BoolT> SlowFlagGetter(TNode<Context> context, TNode<Object> regexp,
JSRegExp::Flag flag);
TNode<Int32T> FlagGetter(TNode<Context> context, TNode<Object> regexp,
TNode<BoolT> FlagGetter(TNode<Context> context, TNode<Object> regexp,
JSRegExp::Flag flag, bool is_fastpath);
void FlagGetter(TNode<Context> context, TNode<Object> receiver,
JSRegExp::Flag flag, int counter, const char* method_name);
Node* RegExpInitialize(Node* const context, Node* const regexp,
Node* const maybe_pattern, Node* const maybe_flags);
......@@ -207,8 +204,8 @@ class RegExpMatchAllAssembler : public RegExpBuiltinsAssembler {
TNode<Object> CreateRegExpStringIterator(TNode<Context> native_context,
TNode<Object> regexp,
TNode<String> string,
TNode<Int32T> global,
TNode<Int32T> full_unicode);
TNode<BoolT> global,
TNode<BoolT> full_unicode);
void Generate(TNode<Context> context, TNode<Context> native_context,
TNode<Object> receiver, TNode<Object> maybe_string);
};
......
......@@ -6,9 +6,6 @@
namespace regexp {
const kRegExpNonRegExp: constexpr MessageTemplate
generates 'MessageTemplate::kRegExpNonRegExp';
extern runtime IncrementUseCounter(Context, Smi): void;
const kRegExpPrototypeSourceGetter: constexpr int31
generates 'v8::Isolate::kRegExpPrototypeSourceGetter';
......
......@@ -32,4 +32,102 @@ namespace regexp {
extern macro RegExpBuiltinsAssembler::IsReceiverInitialRegExpPrototype(
implicit context: Context)(Object): bool;
type Flag constexpr 'JSRegExp::Flag';
const kGlobal: constexpr Flag
generates 'JSRegExp::kGlobal';
const kIgnoreCase: constexpr Flag
generates 'JSRegExp::kIgnoreCase';
const kMultiline: constexpr Flag
generates 'JSRegExp::kMultiline';
const kDotAll: constexpr Flag
generates 'JSRegExp::kDotAll';
const kSticky: constexpr Flag
generates 'JSRegExp::kSticky';
const kUnicode: constexpr Flag
generates 'JSRegExp::kUnicode';
const kRegExpPrototypeOldFlagGetter: constexpr int31
generates 'v8::Isolate::kRegExpPrototypeOldFlagGetter';
const kRegExpPrototypeStickyGetter: constexpr int31
generates 'v8::Isolate::kRegExpPrototypeStickyGetter';
const kRegExpPrototypeUnicodeGetter: constexpr int31
generates 'v8::Isolate::kRegExpPrototypeUnicodeGetter';
extern macro RegExpBuiltinsAssembler::FastFlagGetter(
JSRegExp, constexpr Flag): bool;
const kRegExpNonRegExp: constexpr MessageTemplate
generates 'MessageTemplate::kRegExpNonRegExp';
extern runtime IncrementUseCounter(Context, Smi): void;
macro FlagGetter(implicit context: Context)(
receiver: Object, flag: constexpr Flag, counter: constexpr int31,
methodName: constexpr string): JSAny {
typeswitch (receiver) {
case (receiver: JSRegExp): {
return SelectBooleanConstant(FastFlagGetter(receiver, flag));
}
case (Object): {
}
}
if (!IsReceiverInitialRegExpPrototype(receiver)) {
ThrowTypeError(kRegExpNonRegExp, methodName);
}
if constexpr (counter != -1) {
IncrementUseCounter(context, SmiConstant(counter));
}
return Undefined;
}
// ES6 21.2.5.4.
// ES #sec-get-regexp.prototype.global
transitioning javascript builtin RegExpPrototypeGlobalGetter(
js-implicit context: Context, receiver: JSAny)(): JSAny {
return FlagGetter(
receiver, kGlobal, kRegExpPrototypeOldFlagGetter,
'RegExp.prototype.global');
}
// ES6 21.2.5.5.
// ES #sec-get-regexp.prototype.ignorecase
transitioning javascript builtin RegExpPrototypeIgnoreCaseGetter(
js-implicit context: Context, receiver: JSAny)(): JSAny {
return FlagGetter(
receiver, kIgnoreCase, kRegExpPrototypeOldFlagGetter,
'RegExp.prototype.ignoreCase');
}
// ES6 21.2.5.7.
// ES #sec-get-regexp.prototype.multiline
transitioning javascript builtin RegExpPrototypeMultilineGetter(
js-implicit context: Context, receiver: JSAny)(): JSAny {
return FlagGetter(
receiver, kMultiline, kRegExpPrototypeOldFlagGetter,
'RegExp.prototype.multiline');
}
// ES #sec-get-regexp.prototype.dotAll
transitioning javascript builtin RegExpPrototypeDotAllGetter(
js-implicit context: Context, receiver: JSAny)(): JSAny {
const kNoCounter: constexpr int31 = -1;
return FlagGetter(receiver, kDotAll, kNoCounter, 'RegExp.prototype.dotAll');
}
// ES6 21.2.5.12.
// ES #sec-get-regexp.prototype.sticky
transitioning javascript builtin RegExpPrototypeStickyGetter(
js-implicit context: Context, receiver: JSAny)(): JSAny {
return FlagGetter(
receiver, kSticky, kRegExpPrototypeStickyGetter,
'RegExp.prototype.sticky');
}
// ES6 21.2.5.15.
// ES #sec-get-regexp.prototype.unicode
transitioning javascript builtin RegExpPrototypeUnicodeGetter(
js-implicit context: Context, receiver: JSAny)(): JSAny {
return FlagGetter(
receiver, kUnicode, kRegExpPrototypeUnicodeGetter,
'RegExp.prototype.unicode');
}
}
......@@ -3524,6 +3524,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
bool ConstexprBoolNot(bool value) { return !value; }
bool ConstexprInt31Equal(int31_t a, int31_t b) { return a == b; }
bool ConstexprInt31NotEqual(int31_t a, int31_t b) { return a != b; }
bool ConstexprInt31GreaterThanEqual(int31_t a, int31_t b) { return a >= b; }
uint32_t ConstexprUint32Add(uint32_t a, uint32_t b) { return a + b; }
int31_t ConstexprInt31Add(int31_t a, int31_t b) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment