Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: src/builtins/builtins-regexp-gen.cc

Issue 2745053003: [regexp] Add slow exec stub to reduce code size (Closed)
Patch Set: Rebase and non-generic descriptor Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins.h ('k') | src/interface-descriptors.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 the V8 project authors. All rights reserved. 1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/builtins/builtins-regexp-gen.h" 5 #include "src/builtins/builtins-regexp-gen.h"
6 6
7 #include "src/builtins/builtins-constructor.h" 7 #include "src/builtins/builtins-constructor.h"
8 #include "src/builtins/builtins-utils-gen.h" 8 #include "src/builtins/builtins-utils-gen.h"
9 #include "src/builtins/builtins.h" 9 #include "src/builtins/builtins.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 Node* const pending_exception = 441 Node* const pending_exception =
442 Load(MachineType::AnyTagged(), pending_exception_address); 442 Load(MachineType::AnyTagged(), pending_exception_address);
443 443
444 // If there is no pending exception, a 444 // If there is no pending exception, a
445 // stack overflow (on the backtrack stack) was detected in RegExp code. 445 // stack overflow (on the backtrack stack) was detected in RegExp code.
446 446
447 Label stack_overflow(this), rethrow(this); 447 Label stack_overflow(this), rethrow(this);
448 Branch(IsTheHole(pending_exception), &stack_overflow, &rethrow); 448 Branch(IsTheHole(pending_exception), &stack_overflow, &rethrow);
449 449
450 Bind(&stack_overflow); 450 Bind(&stack_overflow);
451 TailCallRuntime(Runtime::kThrowStackOverflow, context); 451 CallRuntime(Runtime::kThrowStackOverflow, context);
452 Unreachable();
452 453
453 Bind(&rethrow); 454 Bind(&rethrow);
454 TailCallRuntime(Runtime::kRegExpExecReThrow, context); 455 CallRuntime(Runtime::kRegExpExecReThrow, context);
456 Unreachable();
455 } 457 }
456 458
457 Bind(&runtime); 459 Bind(&runtime);
458 { 460 {
459 Node* const result = CallRuntime(Runtime::kRegExpExec, context, regexp, 461 Node* const result = CallRuntime(Runtime::kRegExpExec, context, regexp,
460 string, last_index, match_info); 462 string, last_index, match_info);
461 var_result.Bind(result); 463 var_result.Bind(result);
462 Goto(&out); 464 Goto(&out);
463 } 465 }
464 466
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 Label* if_isunmodified, 721 Label* if_isunmodified,
720 Label* if_ismodified) { 722 Label* if_ismodified) {
721 Node* const native_context = LoadNativeContext(context); 723 Node* const native_context = LoadNativeContext(context);
722 Node* const initial_regexp_result_map = 724 Node* const initial_regexp_result_map =
723 LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX); 725 LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX);
724 726
725 Branch(WordEqual(map, initial_regexp_result_map), if_isunmodified, 727 Branch(WordEqual(map, initial_regexp_result_map), if_isunmodified,
726 if_ismodified); 728 if_ismodified);
727 } 729 }
728 730
731 // Slow path stub for RegExpPrototypeExec to decrease code size.
732 TF_BUILTIN(RegExpPrototypeExecSlow, RegExpBuiltinsAssembler) {
733 typedef RegExpPrototypeExecSlowDescriptor Descriptor;
734
735 Node* const regexp = Parameter(Descriptor::kReceiver);
736 Node* const string = Parameter(Descriptor::kString);
737 Node* const context = Parameter(Descriptor::kContext);
738
739 Return(RegExpPrototypeExecBody(context, regexp, string, false));
740 }
741
729 // ES#sec-regexp.prototype.exec 742 // ES#sec-regexp.prototype.exec
730 // RegExp.prototype.exec ( string ) 743 // RegExp.prototype.exec ( string )
731 TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) { 744 TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) {
732 Node* const maybe_receiver = Parameter(0); 745 Node* const maybe_receiver = Parameter(0);
733 Node* const maybe_string = Parameter(1); 746 Node* const maybe_string = Parameter(1);
734 Node* const context = Parameter(4); 747 Node* const context = Parameter(4);
735 748
736 // Ensure {maybe_receiver} is a JSRegExp. 749 // Ensure {maybe_receiver} is a JSRegExp.
737 Node* const regexp_map = ThrowIfNotInstanceType( 750 Node* const regexp_map = ThrowIfNotInstanceType(
738 context, maybe_receiver, JS_REGEXP_TYPE, "RegExp.prototype.exec"); 751 context, maybe_receiver, JS_REGEXP_TYPE, "RegExp.prototype.exec");
739 Node* const receiver = maybe_receiver; 752 Node* const receiver = maybe_receiver;
740 753
741 // Convert {maybe_string} to a String. 754 // Convert {maybe_string} to a String.
742 Node* const string = ToString(context, maybe_string); 755 Node* const string = ToString(context, maybe_string);
743 756
744 Label if_isfastpath(this), if_isslowpath(this); 757 Label if_isfastpath(this), if_isslowpath(this);
745 Branch(IsInitialRegExpMap(context, regexp_map), &if_isfastpath, 758 Branch(IsInitialRegExpMap(context, regexp_map), &if_isfastpath,
746 &if_isslowpath); 759 &if_isslowpath);
747 760
748 Bind(&if_isfastpath); 761 Bind(&if_isfastpath);
749 { 762 {
750 Node* const result = 763 Node* const result =
751 RegExpPrototypeExecBody(context, receiver, string, true); 764 RegExpPrototypeExecBody(context, receiver, string, true);
752 Return(result); 765 Return(result);
753 } 766 }
754 767
755 Bind(&if_isslowpath); 768 Bind(&if_isslowpath);
756 { 769 {
757 Node* const result = 770 Node* const result = CallBuiltin(Builtins::kRegExpPrototypeExecSlow,
758 RegExpPrototypeExecBody(context, receiver, string, false); 771 context, receiver, string);
759 Return(result); 772 Return(result);
760 } 773 }
761 } 774 }
762 775
763 Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, 776 Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context,
764 Node* const regexp, 777 Node* const regexp,
765 bool is_fastpath) { 778 bool is_fastpath) {
766 Isolate* isolate = this->isolate(); 779 Isolate* isolate = this->isolate();
767 780
768 Node* const int_zero = IntPtrConstant(0); 781 Node* const int_zero = IntPtrConstant(0);
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
1323 1336
1324 // ES6 21.2.5.15. 1337 // ES6 21.2.5.15.
1325 TF_BUILTIN(RegExpPrototypeUnicodeGetter, RegExpBuiltinsAssembler) { 1338 TF_BUILTIN(RegExpPrototypeUnicodeGetter, RegExpBuiltinsAssembler) {
1326 FlagGetter(JSRegExp::kUnicode, v8::Isolate::kRegExpPrototypeUnicodeGetter, 1339 FlagGetter(JSRegExp::kUnicode, v8::Isolate::kRegExpPrototypeUnicodeGetter,
1327 "RegExp.prototype.unicode"); 1340 "RegExp.prototype.unicode");
1328 } 1341 }
1329 1342
1330 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) 1343 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
1331 Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp, 1344 Node* RegExpBuiltinsAssembler::RegExpExec(Node* context, Node* regexp,
1332 Node* string) { 1345 Node* string) {
1333 Isolate* isolate = this->isolate(); 1346 CSA_ASSERT(this, Word32BinaryNot(IsFastRegExpMap(context, LoadMap(regexp))));
1334
1335 Node* const null = NullConstant();
1336 1347
1337 Variable var_result(this, MachineRepresentation::kTagged); 1348 Variable var_result(this, MachineRepresentation::kTagged);
1338 Label out(this), if_isfastpath(this), if_isslowpath(this); 1349 Label out(this);
1339 1350
1340 Node* const map = LoadMap(regexp); 1351 // Take the slow path of fetching the exec property, calling it, and
1341 BranchIfFastRegExp(context, map, &if_isfastpath, &if_isslowpath); 1352 // verifying its return value.
1342 1353
1343 Bind(&if_isfastpath); 1354 // Get the exec property.
1355 Node* const exec =
1356 GetProperty(context, regexp, isolate()->factory()->exec_string());
1357
1358 // Is {exec} callable?
1359 Label if_iscallable(this), if_isnotcallable(this);
1360
1361 GotoIf(TaggedIsSmi(exec), &if_isnotcallable);
1362
1363 Node* const exec_map = LoadMap(exec);
1364 Branch(IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable);
1365
1366 Bind(&if_iscallable);
1344 { 1367 {
1345 Node* const result = RegExpPrototypeExecBody(context, regexp, string, true); 1368 Callable call_callable = CodeFactory::Call(isolate());
1369 Node* const result = CallJS(call_callable, context, exec, regexp, string);
1370
1371 var_result.Bind(result);
1372 GotoIf(WordEqual(result, NullConstant()), &out);
1373
1374 ThrowIfNotJSReceiver(context, result,
1375 MessageTemplate::kInvalidRegExpExecResult, "unused");
1376
1377 Goto(&out);
1378 }
1379
1380 Bind(&if_isnotcallable);
1381 {
1382 ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE,
1383 "RegExp.prototype.exec");
1384
1385 Node* const result = CallBuiltin(Builtins::kRegExpPrototypeExecSlow,
1386 context, regexp, string);
1346 var_result.Bind(result); 1387 var_result.Bind(result);
1347 Goto(&out); 1388 Goto(&out);
1348 } 1389 }
1349 1390
1350 Bind(&if_isslowpath);
1351 {
1352 // Take the slow path of fetching the exec property, calling it, and
1353 // verifying its return value.
1354
1355 // Get the exec property.
1356 Node* const exec =
1357 GetProperty(context, regexp, isolate->factory()->exec_string());
1358
1359 // Is {exec} callable?
1360 Label if_iscallable(this), if_isnotcallable(this);
1361
1362 GotoIf(TaggedIsSmi(exec), &if_isnotcallable);
1363
1364 Node* const exec_map = LoadMap(exec);
1365 Branch(IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable);
1366
1367 Bind(&if_iscallable);
1368 {
1369 Callable call_callable = CodeFactory::Call(isolate);
1370 Node* const result = CallJS(call_callable, context, exec, regexp, string);
1371
1372 var_result.Bind(result);
1373 GotoIf(WordEqual(result, null), &out);
1374
1375 ThrowIfNotJSReceiver(context, result,
1376 MessageTemplate::kInvalidRegExpExecResult, "unused");
1377
1378 Goto(&out);
1379 }
1380
1381 Bind(&if_isnotcallable);
1382 {
1383 ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE,
1384 "RegExp.prototype.exec");
1385
1386 Node* const result =
1387 RegExpPrototypeExecBody(context, regexp, string, false);
1388 var_result.Bind(result);
1389 Goto(&out);
1390 }
1391 }
1392
1393 Bind(&out); 1391 Bind(&out);
1394 return var_result.value(); 1392 return var_result.value();
1395 } 1393 }
1396 1394
1397 // ES#sec-regexp.prototype.test 1395 // ES#sec-regexp.prototype.test
1398 // RegExp.prototype.test ( S ) 1396 // RegExp.prototype.test ( S )
1399 TF_BUILTIN(RegExpPrototypeTest, RegExpBuiltinsAssembler) { 1397 TF_BUILTIN(RegExpPrototypeTest, RegExpBuiltinsAssembler) {
1400 Node* const maybe_receiver = Parameter(0); 1398 Node* const maybe_receiver = Parameter(0);
1401 Node* const maybe_string = Parameter(1); 1399 Node* const maybe_string = Parameter(1);
1402 Node* const context = Parameter(4); 1400 Node* const context = Parameter(4);
(...skipping 1266 matching lines...) Expand 10 before | Expand all | Expand 10 after
2669 Bind(&if_matched); 2667 Bind(&if_matched);
2670 { 2668 {
2671 Node* result = 2669 Node* result =
2672 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); 2670 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string);
2673 Return(result); 2671 Return(result);
2674 } 2672 }
2675 } 2673 }
2676 2674
2677 } // namespace internal 2675 } // namespace internal
2678 } // namespace v8 2676 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/interface-descriptors.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698