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

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

Issue 2384613004: [regexp] Port RegExpConstructor to C++ (Closed)
Patch Set: TODOs and a minor optimization Created 4 years, 2 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-utils.h" 5 #include "src/builtins/builtins-utils.h"
6 #include "src/builtins/builtins.h" 6 #include "src/builtins/builtins.h"
7 7
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/regexp/jsregexp.h" 9 #include "src/regexp/jsregexp.h"
10 #include "src/string-builder.h"
10 11
11 namespace v8 { 12 namespace v8 {
12 namespace internal { 13 namespace internal {
13 14
15 // -----------------------------------------------------------------------------
16 // ES6 section 21.2 RegExp Objects
17
18 namespace {
19
20 // ES#sec-isregexp IsRegExp ( argument )
21 Maybe<bool> IsRegExp(Isolate* isolate, Handle<Object> object) {
22 if (!object->IsJSReceiver()) return Just(false);
23
24 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
25
26 if (isolate->regexp_function()->initial_map() == receiver->map()) {
27 // Fast-path for unmodified JSRegExp instances.
28 return Just(true);
29 }
30
31 Handle<Object> match;
32 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
33 isolate, match,
34 JSObject::GetProperty(receiver, isolate->factory()->match_symbol()),
35 Nothing<bool>());
36
37 if (!match->IsUndefined(isolate)) return Just(match->BooleanValue());
38 return Just(object->IsJSRegExp());
39 }
40
41 Handle<String> PatternFlags(Isolate* isolate, Handle<JSRegExp> regexp) {
42 IncrementalStringBuilder builder(isolate);
Yang 2016/10/05 07:40:34 Using the IncrementalStringBuilder is a bit overki
jgruber 2016/10/05 08:37:03 Good point, done. We could improve this even more
43 const JSRegExp::Flags flags = regexp->GetFlags();
44
45 if ((flags & JSRegExp::kGlobal) != 0) builder.AppendCharacter('g');
46 if ((flags & JSRegExp::kIgnoreCase) != 0) builder.AppendCharacter('i');
47 if ((flags & JSRegExp::kMultiline) != 0) builder.AppendCharacter('m');
48 if ((flags & JSRegExp::kUnicode) != 0) builder.AppendCharacter('u');
49 if ((flags & JSRegExp::kSticky) != 0) builder.AppendCharacter('y');
50
51 return builder.Finish().ToHandleChecked();
52 }
53
54 // ES#sec-regexpinitialize
55 // Runtime Semantics: RegExpInitialize ( obj, pattern, flags )
56 MaybeHandle<JSRegExp> RegExpInitialize(Isolate* isolate,
57 Handle<JSRegExp> regexp,
58 Handle<Object> pattern,
59 Handle<Object> flags) {
60 Handle<String> pattern_string;
61 if (pattern->IsUndefined(isolate)) {
62 pattern_string = isolate->factory()->empty_string();
63 } else {
64 ASSIGN_RETURN_ON_EXCEPTION(isolate, pattern_string,
65 Object::ToString(isolate, pattern), JSRegExp);
66 }
67
68 Handle<String> flags_string;
69 if (flags->IsUndefined(isolate)) {
70 flags_string = isolate->factory()->empty_string();
71 } else {
72 ASSIGN_RETURN_ON_EXCEPTION(isolate, flags_string,
73 Object::ToString(isolate, flags), JSRegExp);
74 }
75
76 // TODO(jgruber): We could avoid the flags back and forth conversions.
77 RETURN_RESULT(isolate,
78 JSRegExp::Initialize(regexp, pattern_string, flags_string),
79 JSRegExp);
80 }
81
82 } // namespace
83
84 // ES#sec-regexp-pattern-flags
85 // RegExp ( pattern, flags )
86 BUILTIN(RegExpConstructor) {
87 HandleScope scope(isolate);
88
89 Handle<HeapObject> new_target = args.new_target();
90 Handle<Object> pattern = args.atOrUndefined(isolate, 1);
91 Handle<Object> flags = args.atOrUndefined(isolate, 2);
92
93 Handle<JSFunction> target = isolate->regexp_function();
94
95 bool pattern_is_regexp;
96 {
97 Maybe<bool> maybe_pattern_is_regexp = IsRegExp(isolate, pattern);
98 if (maybe_pattern_is_regexp.IsNothing()) {
99 DCHECK(isolate->has_pending_exception());
100 return isolate->heap()->exception();
101 }
102 pattern_is_regexp = maybe_pattern_is_regexp.FromJust();
103 }
104
105 if (new_target->IsUndefined(isolate)) {
106 new_target = target;
107
108 // ES6 section 21.2.3.1 step 3.b
109 if (pattern_is_regexp && flags->IsUndefined(isolate)) {
110 Handle<Object> pattern_constructor;
111 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
112 isolate, pattern_constructor,
113 Object::GetProperty(pattern,
114 isolate->factory()->constructor_string()));
115
116 if (pattern_constructor.is_identical_to(new_target)) {
117 return *pattern;
118 }
119 }
120 }
121
122 if (pattern->IsJSRegExp()) {
123 Handle<JSRegExp> regexp_pattern = Handle<JSRegExp>::cast(pattern);
124
125 if (flags->IsUndefined(isolate)) {
126 flags = PatternFlags(isolate, regexp_pattern);
127 }
128 pattern = handle(regexp_pattern->source(), isolate);
129 } else if (pattern_is_regexp) {
130 Handle<Object> pattern_source;
131 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
132 isolate, pattern_source,
133 Object::GetProperty(pattern, isolate->factory()->source_string()));
134
135 if (flags->IsUndefined(isolate)) {
136 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
137 isolate, flags,
138 Object::GetProperty(pattern, isolate->factory()->flags_string()));
139 }
140 pattern = pattern_source;
141 }
142
143 Handle<JSReceiver> new_target_receiver = Handle<JSReceiver>::cast(new_target);
144
145 // TODO(jgruber): Fast-path for target == new_target == unmodified JSRegExp.
146
147 Handle<JSObject> object;
148 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
149 isolate, object, JSObject::New(target, new_target_receiver));
150 Handle<JSRegExp> regexp = Handle<JSRegExp>::cast(object);
151
152 RETURN_RESULT_OR_FAILURE(isolate,
153 RegExpInitialize(isolate, regexp, pattern, flags));
154 }
155
14 namespace { 156 namespace {
15 157
16 compiler::Node* LoadLastIndex(CodeStubAssembler* a, compiler::Node* context, 158 compiler::Node* LoadLastIndex(CodeStubAssembler* a, compiler::Node* context,
17 compiler::Node* has_initialmap, 159 compiler::Node* has_initialmap,
18 compiler::Node* regexp) { 160 compiler::Node* regexp) {
19 typedef CodeStubAssembler::Variable Variable; 161 typedef CodeStubAssembler::Variable Variable;
20 typedef CodeStubAssembler::Label Label; 162 typedef CodeStubAssembler::Label Label;
21 typedef compiler::Node Node; 163 typedef compiler::Node Node;
22 164
23 Variable var_value(a, MachineRepresentation::kTagged); 165 Variable var_value(a, MachineRepresentation::kTagged);
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 { 430 {
289 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, 431 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context,
290 match_elements, string); 432 match_elements, string);
291 a->Return(result); 433 a->Return(result);
292 } 434 }
293 } 435 }
294 } 436 }
295 437
296 } // namespace internal 438 } // namespace internal
297 } // namespace v8 439 } // 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