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

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

Issue 2780173002: [regexp] Add support for dotAll flag (Closed)
Patch Set: Address comments Created 3 years, 8 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-regexp-gen.h ('k') | src/external-reference-table.cc » ('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-gen.h" 7 #include "src/builtins/builtins-constructor-gen.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 763 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, 774 Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context,
775 Node* const regexp, 775 Node* const regexp,
776 bool is_fastpath) { 776 bool is_fastpath) {
777 Isolate* isolate = this->isolate(); 777 Isolate* isolate = this->isolate();
778 778
779 Node* const int_zero = IntPtrConstant(0); 779 Node* const int_zero = IntPtrConstant(0);
780 Node* const int_one = IntPtrConstant(1); 780 Node* const int_one = IntPtrConstant(1);
781 Variable var_length(this, MachineType::PointerRepresentation(), int_zero); 781 Variable var_length(this, MachineType::PointerRepresentation(), int_zero);
782 Variable var_flags(this, MachineType::PointerRepresentation()); 782 Variable var_flags(this, MachineType::PointerRepresentation());
783 783
784 Node* const is_dotall_enabled = IsDotAllEnabled(isolate);
785
784 // First, count the number of characters we will need and check which flags 786 // First, count the number of characters we will need and check which flags
785 // are set. 787 // are set.
786 788
787 if (is_fastpath) { 789 if (is_fastpath) {
788 // Refer to JSRegExp's flag property on the fast-path. 790 // Refer to JSRegExp's flag property on the fast-path.
789 Node* const flags_smi = LoadObjectField(regexp, JSRegExp::kFlagsOffset); 791 Node* const flags_smi = LoadObjectField(regexp, JSRegExp::kFlagsOffset);
790 Node* const flags_intptr = SmiUntag(flags_smi); 792 Node* const flags_intptr = SmiUntag(flags_smi);
791 var_flags.Bind(flags_intptr); 793 var_flags.Bind(flags_intptr);
792 794
793 #define CASE_FOR_FLAG(FLAG) \ 795 #define CASE_FOR_FLAG(FLAG) \
794 do { \ 796 do { \
795 Label next(this); \ 797 Label next(this); \
796 GotoIfNot(IsSetWord(flags_intptr, FLAG), &next); \ 798 GotoIfNot(IsSetWord(flags_intptr, FLAG), &next); \
797 var_length.Bind(IntPtrAdd(var_length.value(), int_one)); \ 799 var_length.Bind(IntPtrAdd(var_length.value(), int_one)); \
798 Goto(&next); \ 800 Goto(&next); \
799 Bind(&next); \ 801 Bind(&next); \
800 } while (false) 802 } while (false)
801 803
802 CASE_FOR_FLAG(JSRegExp::kGlobal); 804 CASE_FOR_FLAG(JSRegExp::kGlobal);
803 CASE_FOR_FLAG(JSRegExp::kIgnoreCase); 805 CASE_FOR_FLAG(JSRegExp::kIgnoreCase);
804 CASE_FOR_FLAG(JSRegExp::kMultiline); 806 CASE_FOR_FLAG(JSRegExp::kMultiline);
807 {
808 Label next(this);
809 GotoIfNot(is_dotall_enabled, &next);
810 CASE_FOR_FLAG(JSRegExp::kDotAll);
811 Goto(&next);
812 Bind(&next);
813 }
805 CASE_FOR_FLAG(JSRegExp::kUnicode); 814 CASE_FOR_FLAG(JSRegExp::kUnicode);
806 CASE_FOR_FLAG(JSRegExp::kSticky); 815 CASE_FOR_FLAG(JSRegExp::kSticky);
807 #undef CASE_FOR_FLAG 816 #undef CASE_FOR_FLAG
808 } else { 817 } else {
809 DCHECK(!is_fastpath); 818 DCHECK(!is_fastpath);
810 819
811 // Fall back to GetProperty stub on the slow-path. 820 // Fall back to GetProperty stub on the slow-path.
812 var_flags.Bind(int_zero); 821 var_flags.Bind(int_zero);
813 822
814 #define CASE_FOR_FLAG(NAME, FLAG) \ 823 #define CASE_FOR_FLAG(NAME, FLAG) \
815 do { \ 824 do { \
816 Label next(this); \ 825 Label next(this); \
817 Node* const flag = GetProperty( \ 826 Node* const flag = GetProperty( \
818 context, regexp, isolate->factory()->InternalizeUtf8String(NAME)); \ 827 context, regexp, isolate->factory()->InternalizeUtf8String(NAME)); \
819 Label if_isflagset(this); \ 828 Label if_isflagset(this); \
820 BranchIfToBooleanIsTrue(flag, &if_isflagset, &next); \ 829 BranchIfToBooleanIsTrue(flag, &if_isflagset, &next); \
821 Bind(&if_isflagset); \ 830 Bind(&if_isflagset); \
822 var_length.Bind(IntPtrAdd(var_length.value(), int_one)); \ 831 var_length.Bind(IntPtrAdd(var_length.value(), int_one)); \
823 var_flags.Bind(WordOr(var_flags.value(), IntPtrConstant(FLAG))); \ 832 var_flags.Bind(WordOr(var_flags.value(), IntPtrConstant(FLAG))); \
824 Goto(&next); \ 833 Goto(&next); \
825 Bind(&next); \ 834 Bind(&next); \
826 } while (false) 835 } while (false)
827 836
828 CASE_FOR_FLAG("global", JSRegExp::kGlobal); 837 CASE_FOR_FLAG("global", JSRegExp::kGlobal);
829 CASE_FOR_FLAG("ignoreCase", JSRegExp::kIgnoreCase); 838 CASE_FOR_FLAG("ignoreCase", JSRegExp::kIgnoreCase);
830 CASE_FOR_FLAG("multiline", JSRegExp::kMultiline); 839 CASE_FOR_FLAG("multiline", JSRegExp::kMultiline);
840 {
841 Label next(this);
842 GotoIfNot(is_dotall_enabled, &next);
843 CASE_FOR_FLAG("dotAll", JSRegExp::kDotAll);
844 Goto(&next);
845 Bind(&next);
846 }
831 CASE_FOR_FLAG("unicode", JSRegExp::kUnicode); 847 CASE_FOR_FLAG("unicode", JSRegExp::kUnicode);
832 CASE_FOR_FLAG("sticky", JSRegExp::kSticky); 848 CASE_FOR_FLAG("sticky", JSRegExp::kSticky);
833 #undef CASE_FOR_FLAG 849 #undef CASE_FOR_FLAG
834 } 850 }
835 851
836 // Allocate a string of the required length and fill it with the corresponding 852 // Allocate a string of the required length and fill it with the corresponding
837 // char for each set flag. 853 // char for each set flag.
838 854
839 { 855 {
840 Node* const result = AllocateSeqOneByteString(context, var_length.value()); 856 Node* const result = AllocateSeqOneByteString(context, var_length.value());
(...skipping 11 matching lines...) Expand all
852 StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \ 868 StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \
853 var_offset.value(), value); \ 869 var_offset.value(), value); \
854 var_offset.Bind(IntPtrAdd(var_offset.value(), int_one)); \ 870 var_offset.Bind(IntPtrAdd(var_offset.value(), int_one)); \
855 Goto(&next); \ 871 Goto(&next); \
856 Bind(&next); \ 872 Bind(&next); \
857 } while (false) 873 } while (false)
858 874
859 CASE_FOR_FLAG(JSRegExp::kGlobal, 'g'); 875 CASE_FOR_FLAG(JSRegExp::kGlobal, 'g');
860 CASE_FOR_FLAG(JSRegExp::kIgnoreCase, 'i'); 876 CASE_FOR_FLAG(JSRegExp::kIgnoreCase, 'i');
861 CASE_FOR_FLAG(JSRegExp::kMultiline, 'm'); 877 CASE_FOR_FLAG(JSRegExp::kMultiline, 'm');
878 {
879 Label next(this);
880 GotoIfNot(is_dotall_enabled, &next);
881 CASE_FOR_FLAG(JSRegExp::kDotAll, 's');
882 Goto(&next);
883 Bind(&next);
884 }
862 CASE_FOR_FLAG(JSRegExp::kUnicode, 'u'); 885 CASE_FOR_FLAG(JSRegExp::kUnicode, 'u');
863 CASE_FOR_FLAG(JSRegExp::kSticky, 'y'); 886 CASE_FOR_FLAG(JSRegExp::kSticky, 'y');
864 #undef CASE_FOR_FLAG 887 #undef CASE_FOR_FLAG
865 888
866 return result; 889 return result;
867 } 890 }
868 } 891 }
869 892
870 // ES#sec-isregexp IsRegExp ( argument ) 893 // ES#sec-isregexp IsRegExp ( argument )
871 Node* RegExpBuiltinsAssembler::IsRegExp(Node* const context, 894 Node* RegExpBuiltinsAssembler::IsRegExp(Node* const context,
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 switch (flag) { 1227 switch (flag) {
1205 case JSRegExp::kGlobal: 1228 case JSRegExp::kGlobal:
1206 name = factory->global_string(); 1229 name = factory->global_string();
1207 break; 1230 break;
1208 case JSRegExp::kIgnoreCase: 1231 case JSRegExp::kIgnoreCase:
1209 name = factory->ignoreCase_string(); 1232 name = factory->ignoreCase_string();
1210 break; 1233 break;
1211 case JSRegExp::kMultiline: 1234 case JSRegExp::kMultiline:
1212 name = factory->multiline_string(); 1235 name = factory->multiline_string();
1213 break; 1236 break;
1237 case JSRegExp::kDotAll:
1238 UNREACHABLE(); // Never called for dotAll.
1239 break;
1214 case JSRegExp::kSticky: 1240 case JSRegExp::kSticky:
1215 name = factory->sticky_string(); 1241 name = factory->sticky_string();
1216 break; 1242 break;
1217 case JSRegExp::kUnicode: 1243 case JSRegExp::kUnicode:
1218 name = factory->unicode_string(); 1244 name = factory->unicode_string();
1219 break; 1245 break;
1220 default: 1246 default:
1221 UNREACHABLE(); 1247 UNREACHABLE();
1222 } 1248 }
1223 1249
(...skipping 20 matching lines...) Expand all
1244 1270
1245 Node* RegExpBuiltinsAssembler::FlagGetter(Node* const context, 1271 Node* RegExpBuiltinsAssembler::FlagGetter(Node* const context,
1246 Node* const regexp, 1272 Node* const regexp,
1247 JSRegExp::Flag flag, 1273 JSRegExp::Flag flag,
1248 bool is_fastpath) { 1274 bool is_fastpath) {
1249 return is_fastpath ? FastFlagGetter(regexp, flag) 1275 return is_fastpath ? FastFlagGetter(regexp, flag)
1250 : SlowFlagGetter(context, regexp, flag); 1276 : SlowFlagGetter(context, regexp, flag);
1251 } 1277 }
1252 1278
1253 void RegExpBuiltinsAssembler::FlagGetter(Node* context, Node* receiver, 1279 void RegExpBuiltinsAssembler::FlagGetter(Node* context, Node* receiver,
1254 JSRegExp::Flag flag, 1280 JSRegExp::Flag flag, int counter,
1255 v8::Isolate::UseCounterFeature counter,
1256 const char* method_name) { 1281 const char* method_name) {
1257 Isolate* isolate = this->isolate(); 1282 Isolate* isolate = this->isolate();
1258 1283
1259 // Check whether we have an unmodified regexp instance. 1284 // Check whether we have an unmodified regexp instance.
1260 Label if_isunmodifiedjsregexp(this), 1285 Label if_isunmodifiedjsregexp(this),
1261 if_isnotunmodifiedjsregexp(this, Label::kDeferred); 1286 if_isnotunmodifiedjsregexp(this, Label::kDeferred);
1262 1287
1263 GotoIf(TaggedIsSmi(receiver), &if_isnotunmodifiedjsregexp); 1288 GotoIf(TaggedIsSmi(receiver), &if_isnotunmodifiedjsregexp);
1264 1289
1265 Node* const receiver_map = LoadMap(receiver); 1290 Node* const receiver_map = LoadMap(receiver);
(...skipping 17 matching lines...) Expand all
1283 Node* const initial_map = 1308 Node* const initial_map =
1284 LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); 1309 LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset);
1285 Node* const initial_prototype = LoadMapPrototype(initial_map); 1310 Node* const initial_prototype = LoadMapPrototype(initial_map);
1286 1311
1287 Label if_isprototype(this), if_isnotprototype(this); 1312 Label if_isprototype(this), if_isnotprototype(this);
1288 Branch(WordEqual(receiver, initial_prototype), &if_isprototype, 1313 Branch(WordEqual(receiver, initial_prototype), &if_isprototype,
1289 &if_isnotprototype); 1314 &if_isnotprototype);
1290 1315
1291 Bind(&if_isprototype); 1316 Bind(&if_isprototype);
1292 { 1317 {
1293 Node* const counter_smi = SmiConstant(Smi::FromInt(counter)); 1318 if (counter != -1) {
1294 CallRuntime(Runtime::kIncrementUseCounter, context, counter_smi); 1319 Node* const counter_smi = SmiConstant(Smi::FromInt(counter));
1320 CallRuntime(Runtime::kIncrementUseCounter, context, counter_smi);
1321 }
1295 Return(UndefinedConstant()); 1322 Return(UndefinedConstant());
1296 } 1323 }
1297 1324
1298 Bind(&if_isnotprototype); 1325 Bind(&if_isnotprototype);
1299 { 1326 {
1300 Node* const message_id = 1327 Node* const message_id =
1301 SmiConstant(Smi::FromInt(MessageTemplate::kRegExpNonRegExp)); 1328 SmiConstant(Smi::FromInt(MessageTemplate::kRegExpNonRegExp));
1302 Node* const method_name_str = HeapConstant( 1329 Node* const method_name_str = HeapConstant(
1303 isolate->factory()->NewStringFromAsciiChecked(method_name)); 1330 isolate->factory()->NewStringFromAsciiChecked(method_name));
1304 CallRuntime(Runtime::kThrowTypeError, context, message_id, 1331 CallRuntime(Runtime::kThrowTypeError, context, message_id,
(...skipping 26 matching lines...) Expand all
1331 // ES6 21.2.5.7. 1358 // ES6 21.2.5.7.
1332 // ES #sec-get-regexp.prototype.multiline 1359 // ES #sec-get-regexp.prototype.multiline
1333 TF_BUILTIN(RegExpPrototypeMultilineGetter, RegExpBuiltinsAssembler) { 1360 TF_BUILTIN(RegExpPrototypeMultilineGetter, RegExpBuiltinsAssembler) {
1334 Node* context = Parameter(Descriptor::kContext); 1361 Node* context = Parameter(Descriptor::kContext);
1335 Node* receiver = Parameter(Descriptor::kReceiver); 1362 Node* receiver = Parameter(Descriptor::kReceiver);
1336 FlagGetter(context, receiver, JSRegExp::kMultiline, 1363 FlagGetter(context, receiver, JSRegExp::kMultiline,
1337 v8::Isolate::kRegExpPrototypeOldFlagGetter, 1364 v8::Isolate::kRegExpPrototypeOldFlagGetter,
1338 "RegExp.prototype.multiline"); 1365 "RegExp.prototype.multiline");
1339 } 1366 }
1340 1367
1368 Node* RegExpBuiltinsAssembler::IsDotAllEnabled(Isolate* isolate) {
1369 Node* flag_ptr = ExternalConstant(
1370 ExternalReference::address_of_regexp_dotall_flag(isolate));
1371 Node* flag_value = Load(MachineType::IntPtr(), flag_ptr);
1372 return WordNotEqual(flag_value, IntPtrConstant(0));
1373 }
1374
1375 // ES #sec-get-regexp.prototype.dotAll
1376 TF_BUILTIN(RegExpPrototypeDotAllGetter, RegExpBuiltinsAssembler) {
1377 Node* context = Parameter(Descriptor::kContext);
1378 Node* receiver = Parameter(Descriptor::kReceiver);
1379 static const int kNoCounter = -1;
1380 CSA_ASSERT(this, IsDotAllEnabled(isolate()));
1381 FlagGetter(context, receiver, JSRegExp::kDotAll, kNoCounter,
1382 "RegExp.prototype.dotAll");
1383 }
1384
1341 // ES6 21.2.5.12. 1385 // ES6 21.2.5.12.
1342 // ES #sec-get-regexp.prototype.sticky 1386 // ES #sec-get-regexp.prototype.sticky
1343 TF_BUILTIN(RegExpPrototypeStickyGetter, RegExpBuiltinsAssembler) { 1387 TF_BUILTIN(RegExpPrototypeStickyGetter, RegExpBuiltinsAssembler) {
1344 Node* context = Parameter(Descriptor::kContext); 1388 Node* context = Parameter(Descriptor::kContext);
1345 Node* receiver = Parameter(Descriptor::kReceiver); 1389 Node* receiver = Parameter(Descriptor::kReceiver);
1346 FlagGetter(context, receiver, JSRegExp::kSticky, 1390 FlagGetter(context, receiver, JSRegExp::kSticky,
1347 v8::Isolate::kRegExpPrototypeStickyGetter, 1391 v8::Isolate::kRegExpPrototypeStickyGetter,
1348 "RegExp.prototype.sticky"); 1392 "RegExp.prototype.sticky");
1349 } 1393 }
1350 1394
(...skipping 1330 matching lines...) Expand 10 before | Expand all | Expand 10 after
2681 Bind(&if_matched); 2725 Bind(&if_matched);
2682 { 2726 {
2683 Node* result = 2727 Node* result =
2684 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); 2728 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string);
2685 Return(result); 2729 Return(result);
2686 } 2730 }
2687 } 2731 }
2688 2732
2689 } // namespace internal 2733 } // namespace internal
2690 } // namespace v8 2734 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-regexp-gen.h ('k') | src/external-reference-table.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698