Commit 5ea144af authored by jgruber's avatar jgruber Committed by Commit bot

[regexp] Add stub for RegExpExec instead of inlining

The code produced for RegExpExec is quite large, and we ended up completely
inlining it several spots.  This CL moves RegExpPrototypeExecBody into two
stubs (one each for fast and slow paths) and converts inlined uses into stub
calls. This decreases the local x64 snapshot size by around 80K.

BUG=chromium:688972

Review-Url: https://codereview.chromium.org/2677073004
Cr-Commit-Position: refs/heads/master@{#42965}
parent a495fc92
......@@ -340,6 +340,33 @@ Node* RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult(
return var_result.value();
}
// Wrapper around RegExpPrototypeExecBody to reduce code duplication.
TF_BUILTIN(RegExpExecInternalFast, RegExpBuiltinsAssembler) {
typedef RegExpExecInternalDescriptor Descriptor;
Node* const regexp = Parameter(Descriptor::kReceiver);
Node* const string = Parameter(Descriptor::kString);
Node* const context = Parameter(Descriptor::kContext);
CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE));
CSA_ASSERT(this, IsString(string));
Return(RegExpPrototypeExecBody(context, regexp, string, true));
}
// Wrapper around RegExpPrototypeExecBody to reduce code duplication.
TF_BUILTIN(RegExpExecInternalSlow, RegExpBuiltinsAssembler) {
typedef RegExpExecInternalDescriptor Descriptor;
Node* const regexp = Parameter(Descriptor::kReceiver);
Node* const string = Parameter(Descriptor::kString);
Node* const context = Parameter(Descriptor::kContext);
CSA_ASSERT(this, IsString(string));
Return(RegExpPrototypeExecBody(context, regexp, string, false));
}
// ES#sec-regexp.prototype.exec
// RegExp.prototype.exec ( string )
Node* RegExpBuiltinsAssembler::RegExpPrototypeExecBody(Node* const context,
......@@ -498,16 +525,14 @@ TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) {
Bind(&if_isfastpath);
{
Node* const result =
RegExpPrototypeExecBody(context, receiver, string, true);
Return(result);
Callable exec_callable = CodeFactory::RegExpExecInternal(isolate(), true);
Return(CallStub(exec_callable, context, receiver, string));
}
Bind(&if_isslowpath);
{
Node* const result =
RegExpPrototypeExecBody(context, receiver, string, false);
Return(result);
Callable exec_callable = CodeFactory::RegExpExecInternal(isolate(), false);
Return(CallStub(exec_callable, context, receiver, string));
}
}
......@@ -1224,7 +1249,8 @@ Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp,
Bind(&if_isfastpath);
{
Node* const result = RegExpPrototypeExecBody(context, regexp, string, true);
Callable exec_callable = CodeFactory::RegExpExecInternal(isolate, true);
Node* const result = CallStub(exec_callable, context, regexp, string);
var_result.Bind(result);
Goto(&out);
}
......@@ -1266,8 +1292,8 @@ Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp,
ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE,
"RegExp.prototype.exec");
Node* const result =
RegExpPrototypeExecBody(context, regexp, string, false);
Callable exec_callable = CodeFactory::RegExpExecInternal(isolate, false);
Node* const result = CallStub(exec_callable, context, regexp, string);
var_result.Bind(result);
Goto(&out);
}
......@@ -1524,10 +1550,12 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context,
Bind(&if_isnotglobal);
{
Node* const result =
is_fastpath ? RegExpPrototypeExecBody(context, regexp, string, true)
: RegExpExec(context, regexp, string);
Return(result);
if (is_fastpath) {
Callable exec_callable = CodeFactory::RegExpExecInternal(isolate, true);
Return(CallStub(exec_callable, context, regexp, string));
} else {
Return(RegExpExec(context, regexp, string));
}
}
Bind(&if_isglobal);
......
......@@ -677,6 +677,9 @@ class Isolate;
CPP(ReflectSet) \
CPP(ReflectSetPrototypeOf) \
\
TFS(RegExpExecInternalFast, BUILTIN, kNoExtraICState, RegExpExecInternal) \
TFS(RegExpExecInternalSlow, BUILTIN, kNoExtraICState, RegExpExecInternal) \
\
/* RegExp */ \
CPP(RegExpCapture1Getter) \
CPP(RegExpCapture2Getter) \
......
......@@ -264,6 +264,14 @@ TFS_BUILTIN(StringGreaterThanOrEqual)
#undef TFS_BUILTIN
// static
Callable CodeFactory::RegExpExecInternal(Isolate* isolate, bool is_fastpath) {
Handle<Code> code(is_fastpath
? isolate->builtins()->RegExpExecInternalFast()
: isolate->builtins()->RegExpExecInternalSlow());
return Callable(code, RegExpExecInternalDescriptor(isolate));
}
// static
Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags,
PretenureFlag pretenure_flag) {
......
......@@ -96,8 +96,13 @@ class V8_EXPORT_PRIVATE CodeFactory final {
OrdinaryToPrimitiveHint hint);
static Callable NumberToString(Isolate* isolate);
// Platform-dependent entry point into the generated irregexp matcher code.
static Callable RegExpExec(Isolate* isolate);
// Implements part of the specced glue logic around RegExp.prototype.exec.
// Usually results in a call to CodeFactory::RegExpExec.
static Callable RegExpExecInternal(Isolate* isolate, bool is_fastpath);
static Callable Add(Isolate* isolate);
static Callable Subtract(Isolate* isolate);
static Callable Multiply(Isolate* isolate);
......
......@@ -52,6 +52,7 @@ class PlatformInterfaceDescriptor;
V(ConstructStub) \
V(ConstructTrampoline) \
V(RegExpExec) \
V(RegExpExecInternal) \
V(RegExpReplace) \
V(RegExpSplit) \
V(CopyFastSmiOrObjectElements) \
......@@ -657,6 +658,13 @@ class RegExpExecDescriptor : public CallInterfaceDescriptor {
CallInterfaceDescriptor)
};
class RegExpExecInternalDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kReceiver, kString)
DECLARE_DEFAULT_DESCRIPTOR(RegExpExecInternalDescriptor,
CallInterfaceDescriptor, kParameterCount)
};
class RegExpReplaceDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kReceiver, kString, kReplaceValue)
......
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