| Index: src/builtins/builtins-regexp-gen.cc
|
| diff --git a/src/builtins/builtins-regexp-gen.cc b/src/builtins/builtins-regexp-gen.cc
|
| index 953254739594abaaa0f1841ac68fa548fe680e09..338556809f3c28a03933c658d1882d98ec8c1ece 100644
|
| --- a/src/builtins/builtins-regexp-gen.cc
|
| +++ b/src/builtins/builtins-regexp-gen.cc
|
| @@ -448,10 +448,12 @@ Node* RegExpBuiltinsAssembler::IrregexpExec(Node* const context,
|
| Branch(IsTheHole(pending_exception), &stack_overflow, &rethrow);
|
|
|
| Bind(&stack_overflow);
|
| - TailCallRuntime(Runtime::kThrowStackOverflow, context);
|
| + CallRuntime(Runtime::kThrowStackOverflow, context);
|
| + Unreachable();
|
|
|
| Bind(&rethrow);
|
| - TailCallRuntime(Runtime::kRegExpExecReThrow, context);
|
| + CallRuntime(Runtime::kRegExpExecReThrow, context);
|
| + Unreachable();
|
| }
|
|
|
| Bind(&runtime);
|
| @@ -726,6 +728,17 @@ void RegExpBuiltinsAssembler::BranchIfFastRegExpResult(Node* context, Node* map,
|
| if_ismodified);
|
| }
|
|
|
| +// Slow path stub for RegExpPrototypeExec to decrease code size.
|
| +TF_BUILTIN(RegExpPrototypeExecSlow, RegExpBuiltinsAssembler) {
|
| + typedef RegExpPrototypeExecSlowDescriptor Descriptor;
|
| +
|
| + Node* const regexp = Parameter(Descriptor::kReceiver);
|
| + Node* const string = Parameter(Descriptor::kString);
|
| + Node* const context = Parameter(Descriptor::kContext);
|
| +
|
| + Return(RegExpPrototypeExecBody(context, regexp, string, false));
|
| +}
|
| +
|
| // ES#sec-regexp.prototype.exec
|
| // RegExp.prototype.exec ( string )
|
| TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) {
|
| @@ -754,8 +767,8 @@ TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) {
|
|
|
| Bind(&if_isslowpath);
|
| {
|
| - Node* const result =
|
| - RegExpPrototypeExecBody(context, receiver, string, false);
|
| + Node* const result = CallBuiltin(Builtins::kRegExpPrototypeExecSlow,
|
| + context, receiver, string);
|
| Return(result);
|
| }
|
| }
|
| @@ -1330,64 +1343,49 @@ TF_BUILTIN(RegExpPrototypeUnicodeGetter, RegExpBuiltinsAssembler) {
|
| // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
|
| Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp,
|
| Node* string) {
|
| - Isolate* isolate = this->isolate();
|
| -
|
| - Node* const null = NullConstant();
|
| + CSA_ASSERT(this, Word32BinaryNot(IsFastRegExpMap(context, LoadMap(regexp))));
|
|
|
| Variable var_result(this, MachineRepresentation::kTagged);
|
| - Label out(this), if_isfastpath(this), if_isslowpath(this);
|
| -
|
| - Node* const map = LoadMap(regexp);
|
| - BranchIfFastRegExp(context, map, &if_isfastpath, &if_isslowpath);
|
| -
|
| - Bind(&if_isfastpath);
|
| - {
|
| - Node* const result = RegExpPrototypeExecBody(context, regexp, string, true);
|
| - var_result.Bind(result);
|
| - Goto(&out);
|
| - }
|
| + Label out(this);
|
|
|
| - Bind(&if_isslowpath);
|
| - {
|
| - // Take the slow path of fetching the exec property, calling it, and
|
| - // verifying its return value.
|
| + // Take the slow path of fetching the exec property, calling it, and
|
| + // verifying its return value.
|
|
|
| - // Get the exec property.
|
| - Node* const exec =
|
| - GetProperty(context, regexp, isolate->factory()->exec_string());
|
| + // Get the exec property.
|
| + Node* const exec =
|
| + GetProperty(context, regexp, isolate()->factory()->exec_string());
|
|
|
| - // Is {exec} callable?
|
| - Label if_iscallable(this), if_isnotcallable(this);
|
| + // Is {exec} callable?
|
| + Label if_iscallable(this), if_isnotcallable(this);
|
|
|
| - GotoIf(TaggedIsSmi(exec), &if_isnotcallable);
|
| + GotoIf(TaggedIsSmi(exec), &if_isnotcallable);
|
|
|
| - Node* const exec_map = LoadMap(exec);
|
| - Branch(IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable);
|
| + Node* const exec_map = LoadMap(exec);
|
| + Branch(IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable);
|
|
|
| - Bind(&if_iscallable);
|
| - {
|
| - Callable call_callable = CodeFactory::Call(isolate);
|
| - Node* const result = CallJS(call_callable, context, exec, regexp, string);
|
| + Bind(&if_iscallable);
|
| + {
|
| + Callable call_callable = CodeFactory::Call(isolate());
|
| + Node* const result = CallJS(call_callable, context, exec, regexp, string);
|
|
|
| - var_result.Bind(result);
|
| - GotoIf(WordEqual(result, null), &out);
|
| + var_result.Bind(result);
|
| + GotoIf(WordEqual(result, NullConstant()), &out);
|
|
|
| - ThrowIfNotJSReceiver(context, result,
|
| - MessageTemplate::kInvalidRegExpExecResult, "unused");
|
| + ThrowIfNotJSReceiver(context, result,
|
| + MessageTemplate::kInvalidRegExpExecResult, "unused");
|
|
|
| - Goto(&out);
|
| - }
|
| + Goto(&out);
|
| + }
|
|
|
| - Bind(&if_isnotcallable);
|
| - {
|
| - ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE,
|
| - "RegExp.prototype.exec");
|
| + Bind(&if_isnotcallable);
|
| + {
|
| + ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE,
|
| + "RegExp.prototype.exec");
|
|
|
| - Node* const result =
|
| - RegExpPrototypeExecBody(context, regexp, string, false);
|
| - var_result.Bind(result);
|
| - Goto(&out);
|
| - }
|
| + Node* const result = CallBuiltin(Builtins::kRegExpPrototypeExecSlow,
|
| + context, regexp, string);
|
| + var_result.Bind(result);
|
| + Goto(&out);
|
| }
|
|
|
| Bind(&out);
|
|
|