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

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

Issue 2438683005: [regexp] Move RegExp.prototype[@@search] to TF (Closed)
Patch Set: Rebase Created 4 years, 1 month 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/code-stub-assembler.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/regexp/regexp-utils.h" 10 #include "src/regexp/regexp-utils.h"
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 isolate, regexp, RegExpInitialize(isolate, regexp, pattern, flags)); 163 isolate, regexp, RegExpInitialize(isolate, regexp, pattern, flags));
164 164
165 // Return undefined for compatibility with JSC. 165 // Return undefined for compatibility with JSC.
166 // See http://crbug.com/585775 for web compat details. 166 // See http://crbug.com/585775 for web compat details.
167 167
168 return isolate->heap()->undefined_value(); 168 return isolate->heap()->undefined_value();
169 } 169 }
170 170
171 namespace { 171 namespace {
172 172
173 compiler::Node* FastLoadLastIndex(CodeStubAssembler* a, compiler::Node* context,
174 compiler::Node* regexp) {
175 // Load the in-object field.
176 static const int field_offset =
177 JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize;
178 return a->LoadObjectField(regexp, field_offset);
179 }
180
181 compiler::Node* SlowLoadLastIndex(CodeStubAssembler* a, compiler::Node* context,
182 compiler::Node* regexp) {
183 // Load through the GetProperty stub.
184 typedef compiler::Node Node;
185
186 Node* const name =
187 a->HeapConstant(a->isolate()->factory()->lastIndex_string());
188 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
189 return a->CallStub(getproperty_callable, context, regexp, name);
190 }
191
173 compiler::Node* LoadLastIndex(CodeStubAssembler* a, compiler::Node* context, 192 compiler::Node* LoadLastIndex(CodeStubAssembler* a, compiler::Node* context,
174 compiler::Node* has_initialmap, 193 compiler::Node* has_initialmap,
175 compiler::Node* regexp) { 194 compiler::Node* regexp) {
176 typedef CodeStubAssembler::Variable Variable; 195 typedef CodeStubAssembler::Variable Variable;
177 typedef CodeStubAssembler::Label Label; 196 typedef CodeStubAssembler::Label Label;
178 typedef compiler::Node Node;
179 197
180 Variable var_value(a, MachineRepresentation::kTagged); 198 Variable var_value(a, MachineRepresentation::kTagged);
181 199
182 Label out(a), if_unmodified(a), if_modified(a, Label::kDeferred); 200 Label out(a), if_unmodified(a), if_modified(a);
183 a->Branch(has_initialmap, &if_unmodified, &if_modified); 201 a->Branch(has_initialmap, &if_unmodified, &if_modified);
184 202
185 a->Bind(&if_unmodified); 203 a->Bind(&if_unmodified);
186 { 204 {
187 // Load the in-object field. 205 var_value.Bind(FastLoadLastIndex(a, context, regexp));
188 static const int field_offset =
189 JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize;
190 var_value.Bind(a->LoadObjectField(regexp, field_offset));
191 a->Goto(&out); 206 a->Goto(&out);
192 } 207 }
193 208
194 a->Bind(&if_modified); 209 a->Bind(&if_modified);
195 { 210 {
196 // Load through the GetProperty stub. 211 var_value.Bind(SlowLoadLastIndex(a, context, regexp));
197 Node* const name =
198 a->HeapConstant(a->isolate()->factory()->lastIndex_string());
199 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
200 var_value.Bind(a->CallStub(getproperty_callable, context, regexp, name));
201 a->Goto(&out); 212 a->Goto(&out);
202 } 213 }
203 214
204 a->Bind(&out); 215 a->Bind(&out);
205 return var_value.value(); 216 return var_value.value();
206 } 217 }
207 218
208 // The fast-path of StoreLastIndex when regexp is guaranteed to be an unmodified 219 // The fast-path of StoreLastIndex when regexp is guaranteed to be an unmodified
209 // JSRegExp instance. 220 // JSRegExp instance.
210 void FastStoreLastIndex(CodeStubAssembler* a, compiler::Node* context, 221 void FastStoreLastIndex(CodeStubAssembler* a, compiler::Node* context,
211 compiler::Node* regexp, compiler::Node* value) { 222 compiler::Node* regexp, compiler::Node* value) {
212 // Store the in-object field. 223 // Store the in-object field.
213 static const int field_offset = 224 static const int field_offset =
214 JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; 225 JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize;
215 a->StoreObjectField(regexp, field_offset, value); 226 a->StoreObjectField(regexp, field_offset, value);
216 } 227 }
217 228
229 void SlowStoreLastIndex(CodeStubAssembler* a, compiler::Node* context,
230 compiler::Node* regexp, compiler::Node* value) {
231 // Store through runtime.
232 // TODO(ishell): Use SetPropertyStub here once available.
233 typedef compiler::Node Node;
234
235 Node* const name =
236 a->HeapConstant(a->isolate()->factory()->lastIndex_string());
237 Node* const language_mode = a->SmiConstant(Smi::FromInt(STRICT));
238 a->CallRuntime(Runtime::kSetProperty, context, regexp, name, value,
239 language_mode);
240 }
241
218 void StoreLastIndex(CodeStubAssembler* a, compiler::Node* context, 242 void StoreLastIndex(CodeStubAssembler* a, compiler::Node* context,
219 compiler::Node* has_initialmap, compiler::Node* regexp, 243 compiler::Node* has_initialmap, compiler::Node* regexp,
220 compiler::Node* value) { 244 compiler::Node* value) {
221 typedef CodeStubAssembler::Label Label; 245 typedef CodeStubAssembler::Label Label;
222 typedef compiler::Node Node;
223 246
224 Label out(a), if_unmodified(a), if_modified(a, Label::kDeferred); 247 Label out(a), if_unmodified(a), if_modified(a);
225 a->Branch(has_initialmap, &if_unmodified, &if_modified); 248 a->Branch(has_initialmap, &if_unmodified, &if_modified);
226 249
227 a->Bind(&if_unmodified); 250 a->Bind(&if_unmodified);
228 { 251 {
229 FastStoreLastIndex(a, context, regexp, value); 252 FastStoreLastIndex(a, context, regexp, value);
230 a->Goto(&out); 253 a->Goto(&out);
231 } 254 }
232 255
233 a->Bind(&if_modified); 256 a->Bind(&if_modified);
234 { 257 {
235 // Store through runtime. 258 SlowStoreLastIndex(a, context, regexp, value);
236 // TODO(ishell): Use SetPropertyStub here once available.
237 Node* const name =
238 a->HeapConstant(a->isolate()->factory()->lastIndex_string());
239 Node* const language_mode = a->SmiConstant(Smi::FromInt(STRICT));
240 a->CallRuntime(Runtime::kSetProperty, context, regexp, name, value,
241 language_mode);
242 a->Goto(&out); 259 a->Goto(&out);
243 } 260 }
244 261
245 a->Bind(&out); 262 a->Bind(&out);
246 } 263 }
247 264
248 compiler::Node* ConstructNewResultFromMatchInfo(Isolate* isolate, 265 compiler::Node* ConstructNewResultFromMatchInfo(Isolate* isolate,
249 CodeStubAssembler* a, 266 CodeStubAssembler* a,
250 compiler::Node* context, 267 compiler::Node* context,
251 compiler::Node* match_info, 268 compiler::Node* match_info,
(...skipping 883 matching lines...) Expand 10 before | Expand all | Expand 10 after
1135 if (match->length() == 0) { 1152 if (match->length() == 0) {
1136 RETURN_FAILURE_ON_EXCEPTION(isolate, RegExpUtils::SetAdvancedStringIndex( 1153 RETURN_FAILURE_ON_EXCEPTION(isolate, RegExpUtils::SetAdvancedStringIndex(
1137 isolate, recv, string, unicode)); 1154 isolate, recv, string, unicode));
1138 } 1155 }
1139 } 1156 }
1140 1157
1141 elems->Shrink(n); 1158 elems->Shrink(n);
1142 return *isolate->factory()->NewJSArrayWithElements(elems); 1159 return *isolate->factory()->NewJSArrayWithElements(elems);
1143 } 1160 }
1144 1161
1162 namespace {
1163
1164 void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a,
1165 compiler::Node* const receiver,
1166 compiler::Node* const string,
1167 compiler::Node* const context,
1168 bool is_fastpath) {
1169 typedef CodeStubAssembler::Label Label;
1170 typedef compiler::Node Node;
1171
1172 Isolate* const isolate = a->isolate();
1173
1174 Node* const smi_zero = a->SmiConstant(Smi::kZero);
1175
1176 // Grab the initial value of last index.
1177 Node* const previous_last_index =
1178 is_fastpath ? FastLoadLastIndex(a, context, receiver)
1179 : SlowLoadLastIndex(a, context, receiver);
1180
1181 // Ensure last index is 0.
1182 if (is_fastpath) {
1183 FastStoreLastIndex(a, context, receiver, smi_zero);
1184 } else {
1185 Label next(a);
1186 a->GotoIf(a->SameValue(previous_last_index, smi_zero, context), &next);
1187
1188 SlowStoreLastIndex(a, context, receiver, smi_zero);
1189 a->Goto(&next);
1190 a->Bind(&next);
1191 }
1192
1193 // Call exec.
1194 Node* const match_indices =
1195 is_fastpath ? RegExpPrototypeExecInternal(a, context, receiver, string)
1196 : RegExpExec(a, context, receiver, string);
1197
1198 // Reset last index if necessary.
1199 if (is_fastpath) {
1200 FastStoreLastIndex(a, context, receiver, previous_last_index);
1201 } else {
1202 Label next(a);
1203 Node* const current_last_index = SlowLoadLastIndex(a, context, receiver);
1204
1205 a->GotoIf(a->SameValue(current_last_index, previous_last_index, context),
1206 &next);
1207
1208 SlowStoreLastIndex(a, context, receiver, previous_last_index);
1209 a->Goto(&next);
1210 a->Bind(&next);
1211 }
1212
1213 // Return -1 if no match was found.
1214 {
1215 Label next(a);
1216 a->GotoUnless(a->WordEqual(match_indices, a->NullConstant()), &next);
1217 a->Return(a->SmiConstant(-1));
1218 a->Bind(&next);
1219 }
1220
1221 // Return the index of the match.
1222 {
1223 Label fast_result(a), slow_result(a, Label::kDeferred);
1224
1225 Node* const native_context = a->LoadNativeContext(context);
1226 Node* const initial_regexp_result_map =
1227 a->LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX);
1228 Node* const match_indices_map = a->LoadMap(match_indices);
1229
1230 a->Branch(a->WordEqual(match_indices_map, initial_regexp_result_map),
1231 &fast_result, &slow_result);
1232
1233 a->Bind(&fast_result);
1234 {
1235 Node* const index =
1236 a->LoadObjectField(match_indices, JSRegExpResult::kIndexOffset,
1237 MachineType::AnyTagged());
1238 a->Return(index);
1239 }
1240
1241 a->Bind(&slow_result);
1242 {
1243 Node* const name = a->HeapConstant(isolate->factory()->index_string());
1244 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
1245 Node* const index =
1246 a->CallStub(getproperty_callable, context, match_indices, name);
1247 a->Return(index);
1248 }
1249 }
1250 }
1251
1252 } // namespace
1253
1145 // ES#sec-regexp.prototype-@@search 1254 // ES#sec-regexp.prototype-@@search
1146 // RegExp.prototype [ @@search ] ( string ) 1255 // RegExp.prototype [ @@search ] ( string )
1147 BUILTIN(RegExpPrototypeSearch) { 1256 void Builtins::Generate_RegExpPrototypeSearch(CodeStubAssembler* a) {
1148 HandleScope scope(isolate); 1257 typedef CodeStubAssembler::Label Label;
1149 CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.@@search"); 1258 typedef compiler::Node Node;
1150 1259
1151 Handle<Object> string_obj = args.atOrUndefined(isolate, 1); 1260 Isolate* const isolate = a->isolate();
1152 1261
1153 Handle<String> string; 1262 Node* const maybe_receiver = a->Parameter(0);
1154 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string, 1263 Node* const maybe_string = a->Parameter(1);
1155 Object::ToString(isolate, string_obj)); 1264 Node* const context = a->Parameter(4);
1156 1265
1157 Handle<Object> previous_last_index_obj; 1266 // Ensure {maybe_receiver} is a JSReceiver.
1158 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, previous_last_index_obj, 1267 Node* const map =
1159 RegExpUtils::GetLastIndex(isolate, recv)); 1268 ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver,
1269 MessageTemplate::kIncompatibleMethodReceiver,
1270 "RegExp.prototype.@@search");
1271 Node* const receiver = maybe_receiver;
1160 1272
1161 if (!previous_last_index_obj->SameValue(Smi::kZero)) { 1273 // Convert {maybe_string} to a String.
1162 RETURN_FAILURE_ON_EXCEPTION(isolate, 1274 Node* const string = a->ToString(context, maybe_string);
1163 RegExpUtils::SetLastIndex(isolate, recv, 0));
1164 }
1165 1275
1166 Handle<Object> result; 1276 Label fast_path(a), slow_path(a);
1167 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1277 BranchIfFastPath(a, context, map, &fast_path, &slow_path);
1168 isolate, result,
1169 RegExpUtils::RegExpExec(isolate, recv, string,
1170 isolate->factory()->undefined_value()));
1171 1278
1172 Handle<Object> current_last_index_obj; 1279 a->Bind(&fast_path);
1173 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, current_last_index_obj, 1280 Generate_RegExpPrototypeSearchBody(a, receiver, string, context, true);
1174 RegExpUtils::GetLastIndex(isolate, recv));
1175 1281
1176 const bool is_last_index_unchanged = 1282 a->Bind(&slow_path);
1177 current_last_index_obj->SameValue(*previous_last_index_obj); 1283 Generate_RegExpPrototypeSearchBody(a, receiver, string, context, false);
1178 if (!is_last_index_unchanged) {
1179 if (previous_last_index_obj->IsSmi()) {
1180 RETURN_FAILURE_ON_EXCEPTION(
1181 isolate,
1182 RegExpUtils::SetLastIndex(
1183 isolate, recv, Smi::cast(*previous_last_index_obj)->value()));
1184 } else {
1185 RETURN_FAILURE_ON_EXCEPTION(
1186 isolate,
1187 Object::SetProperty(recv, isolate->factory()->lastIndex_string(),
1188 previous_last_index_obj, STRICT));
1189 }
1190 }
1191
1192 if (result->IsNull(isolate)) return Smi::FromInt(-1);
1193
1194 RETURN_RESULT_OR_FAILURE(
1195 isolate, Object::GetProperty(result, isolate->factory()->index_string()));
1196 } 1284 }
1197 1285
1198 namespace { 1286 namespace {
1199 1287
1200 MUST_USE_RESULT MaybeHandle<Object> ToUint32(Isolate* isolate, 1288 MUST_USE_RESULT MaybeHandle<Object> ToUint32(Isolate* isolate,
1201 Handle<Object> object, 1289 Handle<Object> object,
1202 uint32_t* out) { 1290 uint32_t* out) {
1203 if (object->IsUndefined(isolate)) { 1291 if (object->IsUndefined(isolate)) {
1204 *out = kMaxUInt32; 1292 *out = kMaxUInt32;
1205 return object; 1293 return object;
(...skipping 802 matching lines...) Expand 10 before | Expand all | Expand 10 after
2008 a->Bind(&if_matched); 2096 a->Bind(&if_matched);
2009 { 2097 {
2010 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, 2098 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context,
2011 match_indices, string); 2099 match_indices, string);
2012 a->Return(result); 2100 a->Return(result);
2013 } 2101 }
2014 } 2102 }
2015 2103
2016 } // namespace internal 2104 } // namespace internal
2017 } // namespace v8 2105 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698