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

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

Issue 2307853002: [regexp] Port RegExpExec (Closed)
Patch Set: Remove unused function Created 4 years, 3 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/heap-symbols.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 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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.h" 5 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7 7
8 #include "src/regexp/jsregexp.h"
8 #include "src/string-builder.h" 9 #include "src/string-builder.h"
9 10
10 namespace v8 { 11 namespace v8 {
11 namespace internal { 12 namespace internal {
12 13
13 // ----------------------------------------------------------------------------- 14 // -----------------------------------------------------------------------------
14 // ES6 section 21.2 RegExp Objects 15 // ES6 section 21.2 RegExp Objects
15 16
16 namespace { 17 namespace {
17 18
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 315
315 // Constants for accessing RegExpLastMatchInfo. 316 // Constants for accessing RegExpLastMatchInfo.
316 // TODO(jgruber): Currently, RegExpLastMatchInfo is still a JSObject maintained 317 // TODO(jgruber): Currently, RegExpLastMatchInfo is still a JSObject maintained
317 // and accessed from JS. This is a crutch until all RegExp logic is ported, then 318 // and accessed from JS. This is a crutch until all RegExp logic is ported, then
318 // we can take care of RegExpLastMatchInfo. 319 // we can take care of RegExpLastMatchInfo.
319 const int kNumberOfCapturesIndex = 0; 320 const int kNumberOfCapturesIndex = 0;
320 const int kLastSubjectIndex = 1; 321 const int kLastSubjectIndex = 1;
321 const int kLastInputIndex = 2; 322 const int kLastInputIndex = 2;
322 const int kFirstCaptureIndex = 3; 323 const int kFirstCaptureIndex = 3;
323 324
324 Handle<Object> GetLastMatchField(Isolate* isolate, int index) { 325 Handle<JSObject> GetLastMatchInfo(Isolate* isolate) {
325 Handle<JSFunction> global_regexp = isolate->regexp_function(); 326 Handle<JSFunction> global_regexp = isolate->regexp_function();
326 Handle<Object> last_match_info_obj = JSReceiver::GetDataProperty( 327 Handle<Object> last_match_info_obj = JSReceiver::GetDataProperty(
327 global_regexp, isolate->factory()->regexp_last_match_info_symbol()); 328 global_regexp, isolate->factory()->regexp_last_match_info_symbol());
328 329
329 Handle<JSReceiver> last_match_info = 330 return Handle<JSObject>::cast(last_match_info_obj);
330 Handle<JSReceiver>::cast(last_match_info_obj); 331 }
332
333 Handle<Object> GetLastMatchField(Isolate* isolate, int index) {
334 Handle<JSObject> last_match_info = GetLastMatchInfo(isolate);
331 return JSReceiver::GetElement(isolate, last_match_info, index) 335 return JSReceiver::GetElement(isolate, last_match_info, index)
332 .ToHandleChecked(); 336 .ToHandleChecked();
333 } 337 }
334 338
335 void SetLastMatchField(Isolate* isolate, int index, Handle<Object> value) { 339 void SetLastMatchField(Isolate* isolate, int index, Handle<Object> value) {
336 Handle<JSFunction> global_regexp = isolate->regexp_function(); 340 Handle<JSFunction> global_regexp = isolate->regexp_function();
337 Handle<Object> last_match_info_obj = JSReceiver::GetDataProperty( 341 Handle<Object> last_match_info_obj = JSReceiver::GetDataProperty(
338 global_regexp, isolate->factory()->regexp_last_match_info_symbol()); 342 global_regexp, isolate->factory()->regexp_last_match_info_symbol());
339 343
340 Handle<JSReceiver> last_match_info = 344 Handle<JSReceiver> last_match_info =
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 } 456 }
453 457
454 BUILTIN(RegExpPrototypeRightContextGetter) { 458 BUILTIN(RegExpPrototypeRightContextGetter) {
455 HandleScope scope(isolate); 459 HandleScope scope(isolate);
456 const int start_index = GetLastMatchCapture(isolate, 1); 460 const int start_index = GetLastMatchCapture(isolate, 1);
457 Handle<String> last_subject = GetLastMatchSubject(isolate); 461 Handle<String> last_subject = GetLastMatchSubject(isolate);
458 const int len = last_subject->length(); 462 const int len = last_subject->length();
459 return *isolate->factory()->NewSubString(last_subject, start_index, len); 463 return *isolate->factory()->NewSubString(last_subject, start_index, len);
460 } 464 }
461 465
466 namespace {
467
468 MaybeHandle<Object> SetLastIndex(Isolate* isolate, Handle<JSRegExp> regexp,
469 int value) {
470 return Object::SetProperty(regexp, isolate->factory()->lastIndex_string(),
471 handle(Smi::FromInt(value), isolate), SLOPPY);
472 }
473
474 Handle<JSArray> ConstructResult(Isolate* isolate, int size, int index,
475 Handle<String> input) {
476 Handle<FixedArray> elements = isolate->factory()->NewFixedArray(size);
477 Handle<Map> regexp_map(isolate->native_context()->regexp_result_map());
478 Handle<JSObject> object =
479 isolate->factory()->NewJSObjectFromMap(regexp_map, NOT_TENURED);
480 Handle<JSArray> array = Handle<JSArray>::cast(object);
481 array->set_elements(*elements);
482 array->set_length(Smi::FromInt(size));
483 // Write in-object properties after the length of the array.
484 array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex,
485 Smi::FromInt(index));
486 array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, *input);
487 return array;
488 }
489
490 Handle<Object> ReturnNewResultFromMatchInfo(Isolate* isolate,
491 Handle<Object> match_info,
492 Handle<String> string) {
493 const int num_captures = GetLastMatchNumberOfCaptures(isolate);
494 DCHECK_EQ(0, num_captures % 2);
495
496 const int num_results = num_captures / 2;
497 int start = GetLastMatchCapture(isolate, 0);
498 int end = GetLastMatchCapture(isolate, 1);
499
500 // Calculate the substring of the first match before creating the result array
501 // to avoid an unnecessary write barrier storing the first result.
502 Handle<String> first = isolate->factory()->NewSubString(string, start, end);
503 Handle<JSArray> result = ConstructResult(isolate, num_results, start, string);
504
505 Handle<FixedArray> elems =
506 handle(FixedArray::cast(result->elements()), isolate);
507 elems->set(0, *first);
508
509 for (int i = 1; i < num_results; i++) {
510 start = GetLastMatchCapture(isolate, i * 2);
511 if (start != -1) {
512 end = GetLastMatchCapture(isolate, i * 2 + 1);
513 Handle<String> capture =
514 isolate->factory()->NewSubString(string, start, end);
515 elems->set(i, *capture);
516 }
517 }
518
519 return result;
520 }
521
522 MaybeHandle<Object> RegExpExecJS(Isolate* isolate, Handle<JSRegExp> regexp,
523 Handle<String> string) {
524 Handle<Object> last_index_obj;
525 ASSIGN_RETURN_ON_EXCEPTION(
526 isolate, last_index_obj,
527 Object::GetProperty(regexp, isolate->factory()->lastIndex_string()),
528 Object);
529
530 // Conversion is required by the ES2015 specification (RegExpBuiltinExec
531 // algorithm, step 4) even if the value is discarded for non-global RegExps.
532 ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
533 Object::ToLength(isolate, last_index_obj), Object);
534
535 int last_index = Handle<Smi>::cast(last_index_obj)->value();
536
537 const int flags = regexp->GetFlags();
538 const bool global = (flags & JSRegExp::kGlobal) != 0;
539 const bool sticky = (flags & JSRegExp::kSticky) != 0;
540 const bool update_last_index = (global || sticky);
541
542 if (update_last_index) {
543 if (last_index > string->length()) {
544 RETURN_ON_EXCEPTION(isolate, SetLastIndex(isolate, regexp, 0), Object);
545 return isolate->factory()->null_value();
546 }
547 } else {
548 last_index = 0;
549 }
550
551 Handle<JSObject> last_match_info = GetLastMatchInfo(isolate);
552
553 // matchIndices is either null or the RegExpLastMatchInfo array.
554 // TODO(littledan): Whether a RegExp is sticky is compiled into the RegExp
555 // itself, but ES2015 allows monkey-patching this property to differ from
556 // the internal flags. If it differs, recompile a different RegExp?
557 // TODO(jgruber): The result of Exec does not need to be a JSArray.
558 Handle<Object> match_indices;
559 ASSIGN_RETURN_ON_EXCEPTION(
560 isolate, match_indices,
561 RegExpImpl::Exec(regexp, string, last_index, last_match_info), Object);
562
563 if (match_indices->IsNull(isolate)) {
564 RETURN_ON_EXCEPTION(isolate, SetLastIndex(isolate, regexp, 0), Object);
565 return isolate->factory()->null_value();
566 }
567
568 // Successful match.
569 if (update_last_index) {
570 last_index = GetLastMatchCapture(isolate, 1);
571 RETURN_ON_EXCEPTION(isolate, SetLastIndex(isolate, regexp, last_index),
572 Object);
573 }
574
575 return ReturnNewResultFromMatchInfo(isolate, match_indices, string);
576 }
577
578 } // namespace
579
580 // ES#sec-regexp.prototype.exec
581 // RegExp.prototype.exec ( string )
582 BUILTIN(RegExpPrototypeExec) {
583 HandleScope scope(isolate);
584 CHECK_RECEIVER(JSRegExp, regexp, "RegExp.prototype.exec");
585
586 Handle<Object> string_obj = args.atOrUndefined(isolate, 1);
587
588 Handle<String> string;
589 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string,
590 Object::ToString(isolate, string_obj));
591
592 RETURN_RESULT_OR_FAILURE(isolate, RegExpExecJS(isolate, regexp, string));
593 }
594
462 } // namespace internal 595 } // namespace internal
463 } // namespace v8 596 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/heap-symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698