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

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

Issue 2524363002: [regexp] Add file-level typedefs to builtins-regexp.cc (Closed)
Patch Set: Created 4 years 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 | « no previous file | no next file » | 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"
11 #include "src/string-builder.h" 11 #include "src/string-builder.h"
12 12
13 namespace v8 { 13 namespace v8 {
14 namespace internal { 14 namespace internal {
15 15
16 typedef compiler::Node Node;
17 typedef CodeStubAssembler::Label CLabel;
18 typedef CodeStubAssembler::Variable CVariable;
19 typedef compiler::CodeAssemblerState CodeAssemblerState;
20
16 // ----------------------------------------------------------------------------- 21 // -----------------------------------------------------------------------------
17 // ES6 section 21.2 RegExp Objects 22 // ES6 section 21.2 RegExp Objects
18 23
19 namespace { 24 namespace {
20 25
21 Handle<String> PatternFlags(Isolate* isolate, Handle<JSRegExp> regexp) { 26 Handle<String> PatternFlags(Isolate* isolate, Handle<JSRegExp> regexp) {
22 static const int kMaxFlagsLength = 5 + 1; // 5 flags and '\0'; 27 static const int kMaxFlagsLength = 5 + 1; // 5 flags and '\0';
23 char flags_string[kMaxFlagsLength]; 28 char flags_string[kMaxFlagsLength];
24 int i = 0; 29 int i = 0;
25 30
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 isolate, regexp, RegExpInitialize(isolate, regexp, pattern, flags)); 168 isolate, regexp, RegExpInitialize(isolate, regexp, pattern, flags));
164 169
165 // Return undefined for compatibility with JSC. 170 // Return undefined for compatibility with JSC.
166 // See http://crbug.com/585775 for web compat details. 171 // See http://crbug.com/585775 for web compat details.
167 172
168 return isolate->heap()->undefined_value(); 173 return isolate->heap()->undefined_value();
169 } 174 }
170 175
171 namespace { 176 namespace {
172 177
173 compiler::Node* FastLoadLastIndex(CodeStubAssembler* a, compiler::Node* context, 178 Node* FastLoadLastIndex(CodeStubAssembler* a, Node* context, Node* regexp) {
174 compiler::Node* regexp) {
175 // Load the in-object field. 179 // Load the in-object field.
176 static const int field_offset = 180 static const int field_offset =
177 JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; 181 JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize;
178 return a->LoadObjectField(regexp, field_offset); 182 return a->LoadObjectField(regexp, field_offset);
179 } 183 }
180 184
181 compiler::Node* SlowLoadLastIndex(CodeStubAssembler* a, compiler::Node* context, 185 Node* SlowLoadLastIndex(CodeStubAssembler* a, Node* context, Node* regexp) {
182 compiler::Node* regexp) {
183 // Load through the GetProperty stub. 186 // Load through the GetProperty stub.
184 typedef compiler::Node Node;
185
186 Node* const name = 187 Node* const name =
187 a->HeapConstant(a->isolate()->factory()->lastIndex_string()); 188 a->HeapConstant(a->isolate()->factory()->lastIndex_string());
188 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); 189 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
189 return a->CallStub(getproperty_callable, context, regexp, name); 190 return a->CallStub(getproperty_callable, context, regexp, name);
190 } 191 }
191 192
192 compiler::Node* LoadLastIndex(CodeStubAssembler* a, compiler::Node* context, 193 Node* LoadLastIndex(CodeStubAssembler* a, Node* context, Node* has_initialmap,
193 compiler::Node* has_initialmap, 194 Node* regexp) {
194 compiler::Node* regexp) { 195 CVariable var_value(a, MachineRepresentation::kTagged);
195 typedef CodeStubAssembler::Variable Variable;
196 typedef CodeStubAssembler::Label Label;
197 196
198 Variable var_value(a, MachineRepresentation::kTagged); 197 CLabel out(a), if_unmodified(a), if_modified(a);
199
200 Label out(a), if_unmodified(a), if_modified(a);
201 a->Branch(has_initialmap, &if_unmodified, &if_modified); 198 a->Branch(has_initialmap, &if_unmodified, &if_modified);
202 199
203 a->Bind(&if_unmodified); 200 a->Bind(&if_unmodified);
204 { 201 {
205 var_value.Bind(FastLoadLastIndex(a, context, regexp)); 202 var_value.Bind(FastLoadLastIndex(a, context, regexp));
206 a->Goto(&out); 203 a->Goto(&out);
207 } 204 }
208 205
209 a->Bind(&if_modified); 206 a->Bind(&if_modified);
210 { 207 {
211 var_value.Bind(SlowLoadLastIndex(a, context, regexp)); 208 var_value.Bind(SlowLoadLastIndex(a, context, regexp));
212 a->Goto(&out); 209 a->Goto(&out);
213 } 210 }
214 211
215 a->Bind(&out); 212 a->Bind(&out);
216 return var_value.value(); 213 return var_value.value();
217 } 214 }
218 215
219 // The fast-path of StoreLastIndex when regexp is guaranteed to be an unmodified 216 // The fast-path of StoreLastIndex when regexp is guaranteed to be an unmodified
220 // JSRegExp instance. 217 // JSRegExp instance.
221 void FastStoreLastIndex(CodeStubAssembler* a, compiler::Node* context, 218 void FastStoreLastIndex(CodeStubAssembler* a, Node* context, Node* regexp,
222 compiler::Node* regexp, compiler::Node* value) { 219 Node* value) {
223 // Store the in-object field. 220 // Store the in-object field.
224 static const int field_offset = 221 static const int field_offset =
225 JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; 222 JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize;
226 a->StoreObjectField(regexp, field_offset, value); 223 a->StoreObjectField(regexp, field_offset, value);
227 } 224 }
228 225
229 void SlowStoreLastIndex(CodeStubAssembler* a, compiler::Node* context, 226 void SlowStoreLastIndex(CodeStubAssembler* a, Node* context, Node* regexp,
230 compiler::Node* regexp, compiler::Node* value) { 227 Node* value) {
231 // Store through runtime. 228 // Store through runtime.
232 // TODO(ishell): Use SetPropertyStub here once available. 229 // TODO(ishell): Use SetPropertyStub here once available.
233 typedef compiler::Node Node;
234
235 Node* const name = 230 Node* const name =
236 a->HeapConstant(a->isolate()->factory()->lastIndex_string()); 231 a->HeapConstant(a->isolate()->factory()->lastIndex_string());
237 Node* const language_mode = a->SmiConstant(Smi::FromInt(STRICT)); 232 Node* const language_mode = a->SmiConstant(Smi::FromInt(STRICT));
238 a->CallRuntime(Runtime::kSetProperty, context, regexp, name, value, 233 a->CallRuntime(Runtime::kSetProperty, context, regexp, name, value,
239 language_mode); 234 language_mode);
240 } 235 }
241 236
242 void StoreLastIndex(CodeStubAssembler* a, compiler::Node* context, 237 void StoreLastIndex(CodeStubAssembler* a, Node* context, Node* has_initialmap,
243 compiler::Node* has_initialmap, compiler::Node* regexp, 238 Node* regexp, Node* value) {
244 compiler::Node* value) { 239 CLabel out(a), if_unmodified(a), if_modified(a);
245 typedef CodeStubAssembler::Label Label;
246
247 Label out(a), if_unmodified(a), if_modified(a);
248 a->Branch(has_initialmap, &if_unmodified, &if_modified); 240 a->Branch(has_initialmap, &if_unmodified, &if_modified);
249 241
250 a->Bind(&if_unmodified); 242 a->Bind(&if_unmodified);
251 { 243 {
252 FastStoreLastIndex(a, context, regexp, value); 244 FastStoreLastIndex(a, context, regexp, value);
253 a->Goto(&out); 245 a->Goto(&out);
254 } 246 }
255 247
256 a->Bind(&if_modified); 248 a->Bind(&if_modified);
257 { 249 {
258 SlowStoreLastIndex(a, context, regexp, value); 250 SlowStoreLastIndex(a, context, regexp, value);
259 a->Goto(&out); 251 a->Goto(&out);
260 } 252 }
261 253
262 a->Bind(&out); 254 a->Bind(&out);
263 } 255 }
264 256
265 compiler::Node* ConstructNewResultFromMatchInfo(Isolate* isolate, 257 Node* ConstructNewResultFromMatchInfo(Isolate* isolate, CodeStubAssembler* a,
266 CodeStubAssembler* a, 258 Node* context, Node* match_info,
267 compiler::Node* context, 259 Node* string) {
268 compiler::Node* match_info, 260 CLabel out(a);
269 compiler::Node* string) {
270 typedef CodeStubAssembler::Variable Variable;
271 typedef CodeStubAssembler::Label Label;
272 typedef compiler::Node Node;
273
274 Label out(a);
275 261
276 CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; 262 CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
277 Node* const num_indices = a->SmiUntag(a->LoadFixedArrayElement( 263 Node* const num_indices = a->SmiUntag(a->LoadFixedArrayElement(
278 match_info, a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, 264 match_info, a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0,
279 mode)); 265 mode));
280 Node* const num_results = a->SmiTag(a->WordShr(num_indices, 1)); 266 Node* const num_results = a->SmiTag(a->WordShr(num_indices, 1));
281 Node* const start = a->LoadFixedArrayElement( 267 Node* const start = a->LoadFixedArrayElement(
282 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), 0, 268 match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), 0,
283 mode); 269 mode);
284 Node* const end = a->LoadFixedArrayElement( 270 Node* const end = a->LoadFixedArrayElement(
(...skipping 10 matching lines...) Expand all
295 281
296 a->StoreFixedArrayElement(result_elements, a->IntPtrConstant(0), first, 282 a->StoreFixedArrayElement(result_elements, a->IntPtrConstant(0), first,
297 SKIP_WRITE_BARRIER); 283 SKIP_WRITE_BARRIER);
298 284
299 a->GotoIf(a->SmiEqual(num_results, a->SmiConstant(Smi::FromInt(1))), &out); 285 a->GotoIf(a->SmiEqual(num_results, a->SmiConstant(Smi::FromInt(1))), &out);
300 286
301 // Store all remaining captures. 287 // Store all remaining captures.
302 Node* const limit = a->IntPtrAdd( 288 Node* const limit = a->IntPtrAdd(
303 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), num_indices); 289 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), num_indices);
304 290
305 Variable var_from_cursor(a, MachineType::PointerRepresentation()); 291 CVariable var_from_cursor(a, MachineType::PointerRepresentation());
306 Variable var_to_cursor(a, MachineType::PointerRepresentation()); 292 CVariable var_to_cursor(a, MachineType::PointerRepresentation());
307 293
308 var_from_cursor.Bind( 294 var_from_cursor.Bind(
309 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2)); 295 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2));
310 var_to_cursor.Bind(a->IntPtrConstant(1)); 296 var_to_cursor.Bind(a->IntPtrConstant(1));
311 297
312 Variable* vars[] = {&var_from_cursor, &var_to_cursor}; 298 CVariable* vars[] = {&var_from_cursor, &var_to_cursor};
313 Label loop(a, 2, vars); 299 CLabel loop(a, 2, vars);
314 300
315 a->Goto(&loop); 301 a->Goto(&loop);
316 a->Bind(&loop); 302 a->Bind(&loop);
317 { 303 {
318 Node* const from_cursor = var_from_cursor.value(); 304 Node* const from_cursor = var_from_cursor.value();
319 Node* const to_cursor = var_to_cursor.value(); 305 Node* const to_cursor = var_to_cursor.value();
320 Node* const start = a->LoadFixedArrayElement(match_info, from_cursor); 306 Node* const start = a->LoadFixedArrayElement(match_info, from_cursor);
321 307
322 Label next_iter(a); 308 CLabel next_iter(a);
323 a->GotoIf(a->SmiEqual(start, a->SmiConstant(Smi::FromInt(-1))), &next_iter); 309 a->GotoIf(a->SmiEqual(start, a->SmiConstant(Smi::FromInt(-1))), &next_iter);
324 310
325 Node* const from_cursor_plus1 = 311 Node* const from_cursor_plus1 =
326 a->IntPtrAdd(from_cursor, a->IntPtrConstant(1)); 312 a->IntPtrAdd(from_cursor, a->IntPtrConstant(1));
327 Node* const end = a->LoadFixedArrayElement(match_info, from_cursor_plus1); 313 Node* const end = a->LoadFixedArrayElement(match_info, from_cursor_plus1);
328 314
329 Node* const capture = a->SubString(context, string, start, end); 315 Node* const capture = a->SubString(context, string, start, end);
330 a->StoreFixedArrayElement(result_elements, to_cursor, capture); 316 a->StoreFixedArrayElement(result_elements, to_cursor, capture);
331 a->Goto(&next_iter); 317 a->Goto(&next_iter);
332 318
333 a->Bind(&next_iter); 319 a->Bind(&next_iter);
334 var_from_cursor.Bind(a->IntPtrAdd(from_cursor, a->IntPtrConstant(2))); 320 var_from_cursor.Bind(a->IntPtrAdd(from_cursor, a->IntPtrConstant(2)));
335 var_to_cursor.Bind(a->IntPtrAdd(to_cursor, a->IntPtrConstant(1))); 321 var_to_cursor.Bind(a->IntPtrAdd(to_cursor, a->IntPtrConstant(1)));
336 a->Branch(a->UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out); 322 a->Branch(a->UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out);
337 } 323 }
338 324
339 a->Bind(&out); 325 a->Bind(&out);
340 return result; 326 return result;
341 } 327 }
342 328
343 // ES#sec-regexp.prototype.exec 329 // ES#sec-regexp.prototype.exec
344 // RegExp.prototype.exec ( string ) 330 // RegExp.prototype.exec ( string )
345 compiler::Node* RegExpPrototypeExecInternal(CodeStubAssembler* a, 331 Node* RegExpPrototypeExecInternal(CodeStubAssembler* a, Node* context,
346 compiler::Node* context, 332 Node* maybe_receiver, Node* maybe_string) {
347 compiler::Node* maybe_receiver,
348 compiler::Node* maybe_string) {
349 typedef CodeStubAssembler::Variable Variable;
350 typedef CodeStubAssembler::Label Label;
351 typedef compiler::Node Node;
352
353 Isolate* const isolate = a->isolate(); 333 Isolate* const isolate = a->isolate();
354 334
355 Node* const null = a->NullConstant(); 335 Node* const null = a->NullConstant();
356 Node* const int_zero = a->IntPtrConstant(0); 336 Node* const int_zero = a->IntPtrConstant(0);
357 Node* const smi_zero = a->SmiConstant(Smi::kZero); 337 Node* const smi_zero = a->SmiConstant(Smi::kZero);
358 338
359 Variable var_result(a, MachineRepresentation::kTagged); 339 CVariable var_result(a, MachineRepresentation::kTagged);
360 Label out(a); 340 CLabel out(a);
361 341
362 // Ensure {maybe_receiver} is a JSRegExp. 342 // Ensure {maybe_receiver} is a JSRegExp.
363 Node* const regexp_map = a->ThrowIfNotInstanceType( 343 Node* const regexp_map = a->ThrowIfNotInstanceType(
364 context, maybe_receiver, JS_REGEXP_TYPE, "RegExp.prototype.exec"); 344 context, maybe_receiver, JS_REGEXP_TYPE, "RegExp.prototype.exec");
365 Node* const regexp = maybe_receiver; 345 Node* const regexp = maybe_receiver;
366 346
367 // Check whether the regexp instance is unmodified. 347 // Check whether the regexp instance is unmodified.
368 Node* const native_context = a->LoadNativeContext(context); 348 Node* const native_context = a->LoadNativeContext(context);
369 Node* const regexp_fun = 349 Node* const regexp_fun =
370 a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); 350 a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX);
371 Node* const initial_map = 351 Node* const initial_map =
372 a->LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); 352 a->LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset);
373 Node* const has_initialmap = a->WordEqual(regexp_map, initial_map); 353 Node* const has_initialmap = a->WordEqual(regexp_map, initial_map);
374 354
375 // Convert {maybe_string} to a string. 355 // Convert {maybe_string} to a string.
376 Callable tostring_callable = CodeFactory::ToString(isolate); 356 Callable tostring_callable = CodeFactory::ToString(isolate);
377 Node* const string = a->CallStub(tostring_callable, context, maybe_string); 357 Node* const string = a->CallStub(tostring_callable, context, maybe_string);
378 Node* const string_length = a->LoadStringLength(string); 358 Node* const string_length = a->LoadStringLength(string);
379 359
380 // Check whether the regexp is global or sticky, which determines whether we 360 // Check whether the regexp is global or sticky, which determines whether we
381 // update last index later on. 361 // update last index later on.
382 Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset); 362 Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset);
383 Node* const is_global_or_sticky = 363 Node* const is_global_or_sticky =
384 a->WordAnd(a->SmiUntag(flags), 364 a->WordAnd(a->SmiUntag(flags),
385 a->IntPtrConstant(JSRegExp::kGlobal | JSRegExp::kSticky)); 365 a->IntPtrConstant(JSRegExp::kGlobal | JSRegExp::kSticky));
386 Node* const should_update_last_index = 366 Node* const should_update_last_index =
387 a->WordNotEqual(is_global_or_sticky, int_zero); 367 a->WordNotEqual(is_global_or_sticky, int_zero);
388 368
389 // Grab and possibly update last index. 369 // Grab and possibly update last index.
390 Label run_exec(a); 370 CLabel run_exec(a);
391 Variable var_lastindex(a, MachineRepresentation::kTagged); 371 CVariable var_lastindex(a, MachineRepresentation::kTagged);
392 { 372 {
393 Label if_doupdate(a), if_dontupdate(a); 373 CLabel if_doupdate(a), if_dontupdate(a);
394 a->Branch(should_update_last_index, &if_doupdate, &if_dontupdate); 374 a->Branch(should_update_last_index, &if_doupdate, &if_dontupdate);
395 375
396 a->Bind(&if_doupdate); 376 a->Bind(&if_doupdate);
397 { 377 {
398 Node* const regexp_lastindex = 378 Node* const regexp_lastindex =
399 LoadLastIndex(a, context, has_initialmap, regexp); 379 LoadLastIndex(a, context, has_initialmap, regexp);
400 380
401 Callable tolength_callable = CodeFactory::ToLength(isolate); 381 Callable tolength_callable = CodeFactory::ToLength(isolate);
402 Node* const lastindex = 382 Node* const lastindex =
403 a->CallStub(tolength_callable, context, regexp_lastindex); 383 a->CallStub(tolength_callable, context, regexp_lastindex);
404 var_lastindex.Bind(lastindex); 384 var_lastindex.Bind(lastindex);
405 385
406 Label if_isoob(a, Label::kDeferred); 386 CLabel if_isoob(a, CLabel::kDeferred);
407 a->GotoUnless(a->TaggedIsSmi(lastindex), &if_isoob); 387 a->GotoUnless(a->TaggedIsSmi(lastindex), &if_isoob);
408 a->GotoUnless(a->SmiLessThanOrEqual(lastindex, string_length), &if_isoob); 388 a->GotoUnless(a->SmiLessThanOrEqual(lastindex, string_length), &if_isoob);
409 a->Goto(&run_exec); 389 a->Goto(&run_exec);
410 390
411 a->Bind(&if_isoob); 391 a->Bind(&if_isoob);
412 { 392 {
413 StoreLastIndex(a, context, has_initialmap, regexp, smi_zero); 393 StoreLastIndex(a, context, has_initialmap, regexp, smi_zero);
414 var_result.Bind(null); 394 var_result.Bind(null);
415 a->Goto(&out); 395 a->Goto(&out);
416 } 396 }
417 } 397 }
418 398
419 a->Bind(&if_dontupdate); 399 a->Bind(&if_dontupdate);
420 { 400 {
421 var_lastindex.Bind(smi_zero); 401 var_lastindex.Bind(smi_zero);
422 a->Goto(&run_exec); 402 a->Goto(&run_exec);
423 } 403 }
424 } 404 }
425 405
426 Node* match_indices; 406 Node* match_indices;
427 Label successful_match(a); 407 CLabel successful_match(a);
428 a->Bind(&run_exec); 408 a->Bind(&run_exec);
429 { 409 {
430 // Get last match info from the context. 410 // Get last match info from the context.
431 Node* const last_match_info = a->LoadContextElement( 411 Node* const last_match_info = a->LoadContextElement(
432 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 412 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
433 413
434 // Call the exec stub. 414 // Call the exec stub.
435 Callable exec_callable = CodeFactory::RegExpExec(isolate); 415 Callable exec_callable = CodeFactory::RegExpExec(isolate);
436 match_indices = a->CallStub(exec_callable, context, regexp, string, 416 match_indices = a->CallStub(exec_callable, context, regexp, string,
437 var_lastindex.value(), last_match_info); 417 var_lastindex.value(), last_match_info);
438 418
439 // {match_indices} is either null or the RegExpMatchInfo array. 419 // {match_indices} is either null or the RegExpMatchInfo array.
440 // Return early if exec failed, possibly updating last index. 420 // Return early if exec failed, possibly updating last index.
441 a->GotoUnless(a->WordEqual(match_indices, null), &successful_match); 421 a->GotoUnless(a->WordEqual(match_indices, null), &successful_match);
442 422
443 Label return_null(a); 423 CLabel return_null(a);
444 a->GotoUnless(should_update_last_index, &return_null); 424 a->GotoUnless(should_update_last_index, &return_null);
445 425
446 StoreLastIndex(a, context, has_initialmap, regexp, smi_zero); 426 StoreLastIndex(a, context, has_initialmap, regexp, smi_zero);
447 a->Goto(&return_null); 427 a->Goto(&return_null);
448 428
449 a->Bind(&return_null); 429 a->Bind(&return_null);
450 var_result.Bind(null); 430 var_result.Bind(null);
451 a->Goto(&out); 431 a->Goto(&out);
452 } 432 }
453 433
454 Label construct_result(a); 434 CLabel construct_result(a);
455 a->Bind(&successful_match); 435 a->Bind(&successful_match);
456 { 436 {
457 a->GotoUnless(should_update_last_index, &construct_result); 437 a->GotoUnless(should_update_last_index, &construct_result);
458 438
459 // Update the new last index from {match_indices}. 439 // Update the new last index from {match_indices}.
460 Node* const new_lastindex = a->LoadFixedArrayElement( 440 Node* const new_lastindex = a->LoadFixedArrayElement(
461 match_indices, 441 match_indices,
462 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1)); 442 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1));
463 443
464 StoreLastIndex(a, context, has_initialmap, regexp, new_lastindex); 444 StoreLastIndex(a, context, has_initialmap, regexp, new_lastindex);
465 a->Goto(&construct_result); 445 a->Goto(&construct_result);
466 446
467 a->Bind(&construct_result); 447 a->Bind(&construct_result);
468 { 448 {
469 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, 449 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context,
470 match_indices, string); 450 match_indices, string);
471 var_result.Bind(result); 451 var_result.Bind(result);
472 a->Goto(&out); 452 a->Goto(&out);
473 } 453 }
474 } 454 }
475 455
476 a->Bind(&out); 456 a->Bind(&out);
477 return var_result.value(); 457 return var_result.value();
478 } 458 }
479 459
480 } // namespace 460 } // namespace
481 461
482 // ES#sec-regexp.prototype.exec 462 // ES#sec-regexp.prototype.exec
483 // RegExp.prototype.exec ( string ) 463 // RegExp.prototype.exec ( string )
484 void Builtins::Generate_RegExpPrototypeExec( 464 void Builtins::Generate_RegExpPrototypeExec(CodeAssemblerState* state) {
485 compiler::CodeAssemblerState* state) {
486 typedef compiler::Node Node;
487 CodeStubAssembler a(state); 465 CodeStubAssembler a(state);
488 466
489 Node* const maybe_receiver = a.Parameter(0); 467 Node* const maybe_receiver = a.Parameter(0);
490 Node* const maybe_string = a.Parameter(1); 468 Node* const maybe_string = a.Parameter(1);
491 Node* const context = a.Parameter(4); 469 Node* const context = a.Parameter(4);
492 470
493 Node* const result = 471 Node* const result =
494 RegExpPrototypeExecInternal(&a, context, maybe_receiver, maybe_string); 472 RegExpPrototypeExecInternal(&a, context, maybe_receiver, maybe_string);
495 a.Return(result); 473 a.Return(result);
496 } 474 }
497 475
498 namespace { 476 namespace {
499 477
500 compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate, 478 Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate,
501 compiler::Node* context, 479 Node* context, Node* value,
502 compiler::Node* value, 480 MessageTemplate::Template msg_template,
503 MessageTemplate::Template msg_template, 481 char const* method_name) {
504 char const* method_name) { 482 CLabel out(a), throw_exception(a, CLabel::kDeferred);
505 typedef compiler::Node Node; 483 CVariable var_value_map(a, MachineRepresentation::kTagged);
506 typedef CodeStubAssembler::Label Label;
507 typedef CodeStubAssembler::Variable Variable;
508
509 Label out(a), throw_exception(a, Label::kDeferred);
510 Variable var_value_map(a, MachineRepresentation::kTagged);
511 484
512 a->GotoIf(a->TaggedIsSmi(value), &throw_exception); 485 a->GotoIf(a->TaggedIsSmi(value), &throw_exception);
513 486
514 // Load the instance type of the {value}. 487 // Load the instance type of the {value}.
515 var_value_map.Bind(a->LoadMap(value)); 488 var_value_map.Bind(a->LoadMap(value));
516 Node* const value_instance_type = 489 Node* const value_instance_type =
517 a->LoadMapInstanceType(var_value_map.value()); 490 a->LoadMapInstanceType(var_value_map.value());
518 491
519 a->Branch(a->IsJSReceiverInstanceType(value_instance_type), &out, 492 a->Branch(a->IsJSReceiverInstanceType(value_instance_type), &out,
520 &throw_exception); 493 &throw_exception);
(...skipping 11 matching lines...) Expand all
532 a->CallRuntime(Runtime::kThrowTypeError, context, message_id, 505 a->CallRuntime(Runtime::kThrowTypeError, context, message_id,
533 method_name_str, value_str); 506 method_name_str, value_str);
534 var_value_map.Bind(a->UndefinedConstant()); 507 var_value_map.Bind(a->UndefinedConstant());
535 a->Goto(&out); // Never reached. 508 a->Goto(&out); // Never reached.
536 } 509 }
537 510
538 a->Bind(&out); 511 a->Bind(&out);
539 return var_value_map.value(); 512 return var_value_map.value();
540 } 513 }
541 514
542 compiler::Node* IsInitialRegExpMap(CodeStubAssembler* a, 515 Node* IsInitialRegExpMap(CodeStubAssembler* a, Node* context, Node* map) {
543 compiler::Node* context,
544 compiler::Node* map) {
545 typedef compiler::Node Node;
546
547 Node* const native_context = a->LoadNativeContext(context); 516 Node* const native_context = a->LoadNativeContext(context);
548 Node* const regexp_fun = 517 Node* const regexp_fun =
549 a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); 518 a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX);
550 Node* const initial_map = 519 Node* const initial_map =
551 a->LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); 520 a->LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset);
552 Node* const has_initialmap = a->WordEqual(map, initial_map); 521 Node* const has_initialmap = a->WordEqual(map, initial_map);
553 522
554 return has_initialmap; 523 return has_initialmap;
555 } 524 }
556 525
557 // RegExp fast path implementations rely on unmodified JSRegExp instances. 526 // RegExp fast path implementations rely on unmodified JSRegExp instances.
558 // We use a fairly coarse granularity for this and simply check whether both 527 // We use a fairly coarse granularity for this and simply check whether both
559 // the regexp itself is unmodified (i.e. its map has not changed) and its 528 // the regexp itself is unmodified (i.e. its map has not changed) and its
560 // prototype is unmodified. 529 // prototype is unmodified.
561 void BranchIfFastPath(CodeStubAssembler* a, compiler::Node* context, 530 void BranchIfFastPath(CodeStubAssembler* a, Node* context, Node* map,
562 compiler::Node* map, 531 CLabel* if_isunmodified, CLabel* if_ismodified) {
563 CodeStubAssembler::Label* if_isunmodified,
564 CodeStubAssembler::Label* if_ismodified) {
565 typedef compiler::Node Node;
566
567 Node* const native_context = a->LoadNativeContext(context); 532 Node* const native_context = a->LoadNativeContext(context);
568 Node* const regexp_fun = 533 Node* const regexp_fun =
569 a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); 534 a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX);
570 Node* const initial_map = 535 Node* const initial_map =
571 a->LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); 536 a->LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset);
572 Node* const has_initialmap = a->WordEqual(map, initial_map); 537 Node* const has_initialmap = a->WordEqual(map, initial_map);
573 538
574 a->GotoUnless(has_initialmap, if_ismodified); 539 a->GotoUnless(has_initialmap, if_ismodified);
575 540
576 Node* const initial_proto_initial_map = a->LoadContextElement( 541 Node* const initial_proto_initial_map = a->LoadContextElement(
577 native_context, Context::REGEXP_PROTOTYPE_MAP_INDEX); 542 native_context, Context::REGEXP_PROTOTYPE_MAP_INDEX);
578 Node* const proto_map = a->LoadMap(a->LoadMapPrototype(map)); 543 Node* const proto_map = a->LoadMap(a->LoadMapPrototype(map));
579 Node* const proto_has_initialmap = 544 Node* const proto_has_initialmap =
580 a->WordEqual(proto_map, initial_proto_initial_map); 545 a->WordEqual(proto_map, initial_proto_initial_map);
581 546
582 // TODO(ishell): Update this check once map changes for constant field 547 // TODO(ishell): Update this check once map changes for constant field
583 // tracking are landing. 548 // tracking are landing.
584 549
585 a->Branch(proto_has_initialmap, if_isunmodified, if_ismodified); 550 a->Branch(proto_has_initialmap, if_isunmodified, if_ismodified);
586 } 551 }
587 552
588 } // namespace 553 } // namespace
589 554
590 void Builtins::Generate_RegExpPrototypeFlagsGetter( 555 void Builtins::Generate_RegExpPrototypeFlagsGetter(CodeAssemblerState* state) {
591 compiler::CodeAssemblerState* state) {
592 typedef CodeStubAssembler::Variable Variable;
593 typedef CodeStubAssembler::Label Label;
594 typedef compiler::Node Node;
595 CodeStubAssembler a(state); 556 CodeStubAssembler a(state);
596 557
597 Node* const receiver = a.Parameter(0); 558 Node* const receiver = a.Parameter(0);
598 Node* const context = a.Parameter(3); 559 Node* const context = a.Parameter(3);
599 560
600 Isolate* isolate = a.isolate(); 561 Isolate* isolate = a.isolate();
601 Node* const int_zero = a.IntPtrConstant(0); 562 Node* const int_zero = a.IntPtrConstant(0);
602 Node* const int_one = a.IntPtrConstant(1); 563 Node* const int_one = a.IntPtrConstant(1);
603 564
604 Node* const map = ThrowIfNotJSReceiver(&a, isolate, context, receiver, 565 Node* const map = ThrowIfNotJSReceiver(&a, isolate, context, receiver,
605 MessageTemplate::kRegExpNonObject, 566 MessageTemplate::kRegExpNonObject,
606 "RegExp.prototype.flags"); 567 "RegExp.prototype.flags");
607 568
608 Variable var_length(&a, MachineType::PointerRepresentation()); 569 CVariable var_length(&a, MachineType::PointerRepresentation());
609 Variable var_flags(&a, MachineType::PointerRepresentation()); 570 CVariable var_flags(&a, MachineType::PointerRepresentation());
610 571
611 // First, count the number of characters we will need and check which flags 572 // First, count the number of characters we will need and check which flags
612 // are set. 573 // are set.
613 574
614 var_length.Bind(int_zero); 575 var_length.Bind(int_zero);
615 576
616 Label if_isunmodifiedjsregexp(&a), 577 CLabel if_isunmodifiedjsregexp(&a),
617 if_isnotunmodifiedjsregexp(&a, Label::kDeferred); 578 if_isnotunmodifiedjsregexp(&a, CLabel::kDeferred);
618 a.Branch(IsInitialRegExpMap(&a, context, map), &if_isunmodifiedjsregexp, 579 a.Branch(IsInitialRegExpMap(&a, context, map), &if_isunmodifiedjsregexp,
619 &if_isnotunmodifiedjsregexp); 580 &if_isnotunmodifiedjsregexp);
620 581
621 Label construct_string(&a); 582 CLabel construct_string(&a);
622 a.Bind(&if_isunmodifiedjsregexp); 583 a.Bind(&if_isunmodifiedjsregexp);
623 { 584 {
624 // Refer to JSRegExp's flag property on the fast-path. 585 // Refer to JSRegExp's flag property on the fast-path.
625 Node* const flags_smi = a.LoadObjectField(receiver, JSRegExp::kFlagsOffset); 586 Node* const flags_smi = a.LoadObjectField(receiver, JSRegExp::kFlagsOffset);
626 Node* const flags_intptr = a.SmiUntag(flags_smi); 587 Node* const flags_intptr = a.SmiUntag(flags_smi);
627 var_flags.Bind(flags_intptr); 588 var_flags.Bind(flags_intptr);
628 589
629 Label label_global(&a), label_ignorecase(&a), label_multiline(&a), 590 CLabel label_global(&a), label_ignorecase(&a), label_multiline(&a),
630 label_unicode(&a), label_sticky(&a); 591 label_unicode(&a), label_sticky(&a);
631 592
632 #define CASE_FOR_FLAG(FLAG, LABEL, NEXT_LABEL) \ 593 #define CASE_FOR_FLAG(FLAG, LABEL, NEXT_LABEL) \
633 do { \ 594 do { \
634 a.Bind(&LABEL); \ 595 a.Bind(&LABEL); \
635 Node* const mask = a.IntPtrConstant(FLAG); \ 596 Node* const mask = a.IntPtrConstant(FLAG); \
636 a.GotoIf(a.WordEqual(a.WordAnd(flags_intptr, mask), int_zero), \ 597 a.GotoIf(a.WordEqual(a.WordAnd(flags_intptr, mask), int_zero), \
637 &NEXT_LABEL); \ 598 &NEXT_LABEL); \
638 var_length.Bind(a.IntPtrAdd(var_length.value(), int_one)); \ 599 var_length.Bind(a.IntPtrAdd(var_length.value(), int_one)); \
639 a.Goto(&NEXT_LABEL); \ 600 a.Goto(&NEXT_LABEL); \
640 } while (false) 601 } while (false)
641 602
642 a.Goto(&label_global); 603 a.Goto(&label_global);
643 CASE_FOR_FLAG(JSRegExp::kGlobal, label_global, label_ignorecase); 604 CASE_FOR_FLAG(JSRegExp::kGlobal, label_global, label_ignorecase);
644 CASE_FOR_FLAG(JSRegExp::kIgnoreCase, label_ignorecase, label_multiline); 605 CASE_FOR_FLAG(JSRegExp::kIgnoreCase, label_ignorecase, label_multiline);
645 CASE_FOR_FLAG(JSRegExp::kMultiline, label_multiline, label_unicode); 606 CASE_FOR_FLAG(JSRegExp::kMultiline, label_multiline, label_unicode);
646 CASE_FOR_FLAG(JSRegExp::kUnicode, label_unicode, label_sticky); 607 CASE_FOR_FLAG(JSRegExp::kUnicode, label_unicode, label_sticky);
647 CASE_FOR_FLAG(JSRegExp::kSticky, label_sticky, construct_string); 608 CASE_FOR_FLAG(JSRegExp::kSticky, label_sticky, construct_string);
648 #undef CASE_FOR_FLAG 609 #undef CASE_FOR_FLAG
649 } 610 }
650 611
651 a.Bind(&if_isnotunmodifiedjsregexp); 612 a.Bind(&if_isnotunmodifiedjsregexp);
652 { 613 {
653 // Fall back to GetProperty stub on the slow-path. 614 // Fall back to GetProperty stub on the slow-path.
654 var_flags.Bind(int_zero); 615 var_flags.Bind(int_zero);
655 616
656 Callable getproperty_callable = CodeFactory::GetProperty(a.isolate()); 617 Callable getproperty_callable = CodeFactory::GetProperty(a.isolate());
657 Label label_global(&a), label_ignorecase(&a), label_multiline(&a), 618 CLabel label_global(&a), label_ignorecase(&a), label_multiline(&a),
658 label_unicode(&a), label_sticky(&a); 619 label_unicode(&a), label_sticky(&a);
659 620
660 #define CASE_FOR_FLAG(NAME, FLAG, LABEL, NEXT_LABEL) \ 621 #define CASE_FOR_FLAG(NAME, FLAG, LABEL, NEXT_LABEL) \
661 do { \ 622 do { \
662 a.Bind(&LABEL); \ 623 a.Bind(&LABEL); \
663 Node* const name = \ 624 Node* const name = \
664 a.HeapConstant(isolate->factory()->NewStringFromAsciiChecked(NAME)); \ 625 a.HeapConstant(isolate->factory()->NewStringFromAsciiChecked(NAME)); \
665 Node* const flag = \ 626 Node* const flag = \
666 a.CallStub(getproperty_callable, context, receiver, name); \ 627 a.CallStub(getproperty_callable, context, receiver, name); \
667 Label if_isflagset(&a); \ 628 CLabel if_isflagset(&a); \
668 a.BranchIfToBooleanIsTrue(flag, &if_isflagset, &NEXT_LABEL); \ 629 a.BranchIfToBooleanIsTrue(flag, &if_isflagset, &NEXT_LABEL); \
669 a.Bind(&if_isflagset); \ 630 a.Bind(&if_isflagset); \
670 var_length.Bind(a.IntPtrAdd(var_length.value(), int_one)); \ 631 var_length.Bind(a.IntPtrAdd(var_length.value(), int_one)); \
671 var_flags.Bind(a.WordOr(var_flags.value(), a.IntPtrConstant(FLAG))); \ 632 var_flags.Bind(a.WordOr(var_flags.value(), a.IntPtrConstant(FLAG))); \
672 a.Goto(&NEXT_LABEL); \ 633 a.Goto(&NEXT_LABEL); \
673 } while (false) 634 } while (false)
674 635
675 a.Goto(&label_global); 636 a.Goto(&label_global);
676 CASE_FOR_FLAG("global", JSRegExp::kGlobal, label_global, label_ignorecase); 637 CASE_FOR_FLAG("global", JSRegExp::kGlobal, label_global, label_ignorecase);
677 CASE_FOR_FLAG("ignoreCase", JSRegExp::kIgnoreCase, label_ignorecase, 638 CASE_FOR_FLAG("ignoreCase", JSRegExp::kIgnoreCase, label_ignorecase,
678 label_multiline); 639 label_multiline);
679 CASE_FOR_FLAG("multiline", JSRegExp::kMultiline, label_multiline, 640 CASE_FOR_FLAG("multiline", JSRegExp::kMultiline, label_multiline,
680 label_unicode); 641 label_unicode);
681 CASE_FOR_FLAG("unicode", JSRegExp::kUnicode, label_unicode, label_sticky); 642 CASE_FOR_FLAG("unicode", JSRegExp::kUnicode, label_unicode, label_sticky);
682 CASE_FOR_FLAG("sticky", JSRegExp::kSticky, label_sticky, construct_string); 643 CASE_FOR_FLAG("sticky", JSRegExp::kSticky, label_sticky, construct_string);
683 #undef CASE_FOR_FLAG 644 #undef CASE_FOR_FLAG
684 } 645 }
685 646
686 // Allocate a string of the required length and fill it with the corresponding 647 // Allocate a string of the required length and fill it with the corresponding
687 // char for each set flag. 648 // char for each set flag.
688 649
689 a.Bind(&construct_string); 650 a.Bind(&construct_string);
690 { 651 {
691 Node* const result = 652 Node* const result =
692 a.AllocateSeqOneByteString(context, var_length.value()); 653 a.AllocateSeqOneByteString(context, var_length.value());
693 Node* const flags_intptr = var_flags.value(); 654 Node* const flags_intptr = var_flags.value();
694 655
695 Variable var_offset(&a, MachineType::PointerRepresentation()); 656 CVariable var_offset(&a, MachineType::PointerRepresentation());
696 var_offset.Bind( 657 var_offset.Bind(
697 a.IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag)); 658 a.IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag));
698 659
699 Label label_global(&a), label_ignorecase(&a), label_multiline(&a), 660 CLabel label_global(&a), label_ignorecase(&a), label_multiline(&a),
700 label_unicode(&a), label_sticky(&a), out(&a); 661 label_unicode(&a), label_sticky(&a), out(&a);
701 662
702 #define CASE_FOR_FLAG(FLAG, CHAR, LABEL, NEXT_LABEL) \ 663 #define CASE_FOR_FLAG(FLAG, CHAR, LABEL, NEXT_LABEL) \
703 do { \ 664 do { \
704 a.Bind(&LABEL); \ 665 a.Bind(&LABEL); \
705 Node* const mask = a.IntPtrConstant(FLAG); \ 666 Node* const mask = a.IntPtrConstant(FLAG); \
706 a.GotoIf(a.WordEqual(a.WordAnd(flags_intptr, mask), int_zero), \ 667 a.GotoIf(a.WordEqual(a.WordAnd(flags_intptr, mask), int_zero), \
707 &NEXT_LABEL); \ 668 &NEXT_LABEL); \
708 Node* const value = a.IntPtrConstant(CHAR); \ 669 Node* const value = a.IntPtrConstant(CHAR); \
709 a.StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \ 670 a.StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 747
787 // ES6 21.2.4.2. 748 // ES6 21.2.4.2.
788 BUILTIN(RegExpPrototypeSpeciesGetter) { 749 BUILTIN(RegExpPrototypeSpeciesGetter) {
789 HandleScope scope(isolate); 750 HandleScope scope(isolate);
790 return *args.receiver(); 751 return *args.receiver();
791 } 752 }
792 753
793 namespace { 754 namespace {
794 755
795 // Fast-path implementation for flag checks on an unmodified JSRegExp instance. 756 // Fast-path implementation for flag checks on an unmodified JSRegExp instance.
796 compiler::Node* FastFlagGetter(CodeStubAssembler* a, 757 Node* FastFlagGetter(CodeStubAssembler* a, Node* const regexp,
797 compiler::Node* const regexp, 758 JSRegExp::Flag flag) {
798 JSRegExp::Flag flag) {
799 typedef compiler::Node Node;
800
801 Node* const smi_zero = a->SmiConstant(Smi::kZero); 759 Node* const smi_zero = a->SmiConstant(Smi::kZero);
802 Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset); 760 Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset);
803 Node* const mask = a->SmiConstant(Smi::FromInt(flag)); 761 Node* const mask = a->SmiConstant(Smi::FromInt(flag));
804 Node* const is_flag_set = a->WordNotEqual(a->WordAnd(flags, mask), smi_zero); 762 Node* const is_flag_set = a->WordNotEqual(a->WordAnd(flags, mask), smi_zero);
805 763
806 return is_flag_set; 764 return is_flag_set;
807 } 765 }
808 766
809 void Generate_FlagGetter(CodeStubAssembler* a, JSRegExp::Flag flag, 767 void Generate_FlagGetter(CodeStubAssembler* a, JSRegExp::Flag flag,
810 v8::Isolate::UseCounterFeature counter, 768 v8::Isolate::UseCounterFeature counter,
811 const char* method_name) { 769 const char* method_name) {
812 typedef CodeStubAssembler::Label Label;
813 typedef compiler::Node Node;
814
815 Node* const receiver = a->Parameter(0); 770 Node* const receiver = a->Parameter(0);
816 Node* const context = a->Parameter(3); 771 Node* const context = a->Parameter(3);
817 772
818 Isolate* isolate = a->isolate(); 773 Isolate* isolate = a->isolate();
819 774
820 // Check whether we have an unmodified regexp instance. 775 // Check whether we have an unmodified regexp instance.
821 Label if_isunmodifiedjsregexp(a), 776 CLabel if_isunmodifiedjsregexp(a),
822 if_isnotunmodifiedjsregexp(a, Label::kDeferred); 777 if_isnotunmodifiedjsregexp(a, CLabel::kDeferred);
823 778
824 a->GotoIf(a->TaggedIsSmi(receiver), &if_isnotunmodifiedjsregexp); 779 a->GotoIf(a->TaggedIsSmi(receiver), &if_isnotunmodifiedjsregexp);
825 780
826 Node* const receiver_map = a->LoadMap(receiver); 781 Node* const receiver_map = a->LoadMap(receiver);
827 Node* const instance_type = a->LoadMapInstanceType(receiver_map); 782 Node* const instance_type = a->LoadMapInstanceType(receiver_map);
828 783
829 a->Branch(a->Word32Equal(instance_type, a->Int32Constant(JS_REGEXP_TYPE)), 784 a->Branch(a->Word32Equal(instance_type, a->Int32Constant(JS_REGEXP_TYPE)),
830 &if_isunmodifiedjsregexp, &if_isnotunmodifiedjsregexp); 785 &if_isunmodifiedjsregexp, &if_isnotunmodifiedjsregexp);
831 786
832 a->Bind(&if_isunmodifiedjsregexp); 787 a->Bind(&if_isunmodifiedjsregexp);
833 { 788 {
834 // Refer to JSRegExp's flag property on the fast-path. 789 // Refer to JSRegExp's flag property on the fast-path.
835 Node* const is_flag_set = FastFlagGetter(a, receiver, flag); 790 Node* const is_flag_set = FastFlagGetter(a, receiver, flag);
836 a->Return(a->Select(is_flag_set, a->TrueConstant(), a->FalseConstant())); 791 a->Return(a->Select(is_flag_set, a->TrueConstant(), a->FalseConstant()));
837 } 792 }
838 793
839 a->Bind(&if_isnotunmodifiedjsregexp); 794 a->Bind(&if_isnotunmodifiedjsregexp);
840 { 795 {
841 Node* const native_context = a->LoadNativeContext(context); 796 Node* const native_context = a->LoadNativeContext(context);
842 Node* const regexp_fun = 797 Node* const regexp_fun =
843 a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); 798 a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX);
844 Node* const initial_map = a->LoadObjectField( 799 Node* const initial_map = a->LoadObjectField(
845 regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); 800 regexp_fun, JSFunction::kPrototypeOrInitialMapOffset);
846 Node* const initial_prototype = a->LoadMapPrototype(initial_map); 801 Node* const initial_prototype = a->LoadMapPrototype(initial_map);
847 802
848 Label if_isprototype(a), if_isnotprototype(a); 803 CLabel if_isprototype(a), if_isnotprototype(a);
849 a->Branch(a->WordEqual(receiver, initial_prototype), &if_isprototype, 804 a->Branch(a->WordEqual(receiver, initial_prototype), &if_isprototype,
850 &if_isnotprototype); 805 &if_isnotprototype);
851 806
852 a->Bind(&if_isprototype); 807 a->Bind(&if_isprototype);
853 { 808 {
854 Node* const counter_smi = a->SmiConstant(Smi::FromInt(counter)); 809 Node* const counter_smi = a->SmiConstant(Smi::FromInt(counter));
855 a->CallRuntime(Runtime::kIncrementUseCounter, context, counter_smi); 810 a->CallRuntime(Runtime::kIncrementUseCounter, context, counter_smi);
856 a->Return(a->UndefinedConstant()); 811 a->Return(a->UndefinedConstant());
857 } 812 }
858 813
859 a->Bind(&if_isnotprototype); 814 a->Bind(&if_isnotprototype);
860 { 815 {
861 Node* const message_id = 816 Node* const message_id =
862 a->SmiConstant(Smi::FromInt(MessageTemplate::kRegExpNonRegExp)); 817 a->SmiConstant(Smi::FromInt(MessageTemplate::kRegExpNonRegExp));
863 Node* const method_name_str = a->HeapConstant( 818 Node* const method_name_str = a->HeapConstant(
864 isolate->factory()->NewStringFromAsciiChecked(method_name)); 819 isolate->factory()->NewStringFromAsciiChecked(method_name));
865 a->CallRuntime(Runtime::kThrowTypeError, context, message_id, 820 a->CallRuntime(Runtime::kThrowTypeError, context, message_id,
866 method_name_str); 821 method_name_str);
867 a->Return(a->UndefinedConstant()); // Never reached. 822 a->Return(a->UndefinedConstant()); // Never reached.
868 } 823 }
869 } 824 }
870 } 825 }
871 826
872 } // namespace 827 } // namespace
873 828
874 // ES6 21.2.5.4. 829 // ES6 21.2.5.4.
875 void Builtins::Generate_RegExpPrototypeGlobalGetter( 830 void Builtins::Generate_RegExpPrototypeGlobalGetter(CodeAssemblerState* state) {
876 compiler::CodeAssemblerState* state) {
877 CodeStubAssembler a(state); 831 CodeStubAssembler a(state);
878 Generate_FlagGetter(&a, JSRegExp::kGlobal, 832 Generate_FlagGetter(&a, JSRegExp::kGlobal,
879 v8::Isolate::kRegExpPrototypeOldFlagGetter, 833 v8::Isolate::kRegExpPrototypeOldFlagGetter,
880 "RegExp.prototype.global"); 834 "RegExp.prototype.global");
881 } 835 }
882 836
883 // ES6 21.2.5.5. 837 // ES6 21.2.5.5.
884 void Builtins::Generate_RegExpPrototypeIgnoreCaseGetter( 838 void Builtins::Generate_RegExpPrototypeIgnoreCaseGetter(
885 compiler::CodeAssemblerState* state) { 839 CodeAssemblerState* state) {
886 CodeStubAssembler a(state); 840 CodeStubAssembler a(state);
887 Generate_FlagGetter(&a, JSRegExp::kIgnoreCase, 841 Generate_FlagGetter(&a, JSRegExp::kIgnoreCase,
888 v8::Isolate::kRegExpPrototypeOldFlagGetter, 842 v8::Isolate::kRegExpPrototypeOldFlagGetter,
889 "RegExp.prototype.ignoreCase"); 843 "RegExp.prototype.ignoreCase");
890 } 844 }
891 845
892 // ES6 21.2.5.7. 846 // ES6 21.2.5.7.
893 void Builtins::Generate_RegExpPrototypeMultilineGetter( 847 void Builtins::Generate_RegExpPrototypeMultilineGetter(
894 compiler::CodeAssemblerState* state) { 848 CodeAssemblerState* state) {
895 CodeStubAssembler a(state); 849 CodeStubAssembler a(state);
896 Generate_FlagGetter(&a, JSRegExp::kMultiline, 850 Generate_FlagGetter(&a, JSRegExp::kMultiline,
897 v8::Isolate::kRegExpPrototypeOldFlagGetter, 851 v8::Isolate::kRegExpPrototypeOldFlagGetter,
898 "RegExp.prototype.multiline"); 852 "RegExp.prototype.multiline");
899 } 853 }
900 854
901 // ES6 21.2.5.12. 855 // ES6 21.2.5.12.
902 void Builtins::Generate_RegExpPrototypeStickyGetter( 856 void Builtins::Generate_RegExpPrototypeStickyGetter(CodeAssemblerState* state) {
903 compiler::CodeAssemblerState* state) {
904 CodeStubAssembler a(state); 857 CodeStubAssembler a(state);
905 Generate_FlagGetter(&a, JSRegExp::kSticky, 858 Generate_FlagGetter(&a, JSRegExp::kSticky,
906 v8::Isolate::kRegExpPrototypeStickyGetter, 859 v8::Isolate::kRegExpPrototypeStickyGetter,
907 "RegExp.prototype.sticky"); 860 "RegExp.prototype.sticky");
908 } 861 }
909 862
910 // ES6 21.2.5.15. 863 // ES6 21.2.5.15.
911 void Builtins::Generate_RegExpPrototypeUnicodeGetter( 864 void Builtins::Generate_RegExpPrototypeUnicodeGetter(
912 compiler::CodeAssemblerState* state) { 865 CodeAssemblerState* state) {
913 CodeStubAssembler a(state); 866 CodeStubAssembler a(state);
914 Generate_FlagGetter(&a, JSRegExp::kUnicode, 867 Generate_FlagGetter(&a, JSRegExp::kUnicode,
915 v8::Isolate::kRegExpPrototypeUnicodeGetter, 868 v8::Isolate::kRegExpPrototypeUnicodeGetter,
916 "RegExp.prototype.unicode"); 869 "RegExp.prototype.unicode");
917 } 870 }
918 871
919 // The properties $1..$9 are the first nine capturing substrings of the last 872 // The properties $1..$9 are the first nine capturing substrings of the last
920 // successful match, or ''. The function RegExpMakeCaptureGetter will be 873 // successful match, or ''. The function RegExpMakeCaptureGetter will be
921 // called with indices from 1 to 9. 874 // called with indices from 1 to 9.
922 #define DEFINE_CAPTURE_GETTER(i) \ 875 #define DEFINE_CAPTURE_GETTER(i) \
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
995 Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info(); 948 Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info();
996 const int start_index = match_info->Capture(1); 949 const int start_index = match_info->Capture(1);
997 Handle<String> last_subject(match_info->LastSubject()); 950 Handle<String> last_subject(match_info->LastSubject());
998 const int len = last_subject->length(); 951 const int len = last_subject->length();
999 return *isolate->factory()->NewSubString(last_subject, start_index, len); 952 return *isolate->factory()->NewSubString(last_subject, start_index, len);
1000 } 953 }
1001 954
1002 namespace { 955 namespace {
1003 956
1004 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) 957 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
1005 compiler::Node* RegExpExec(CodeStubAssembler* a, compiler::Node* context, 958 Node* RegExpExec(CodeStubAssembler* a, Node* context, Node* recv,
1006 compiler::Node* recv, compiler::Node* string) { 959 Node* string) {
1007 typedef CodeStubAssembler::Variable Variable;
1008 typedef CodeStubAssembler::Label Label;
1009 typedef compiler::Node Node;
1010
1011 Isolate* isolate = a->isolate(); 960 Isolate* isolate = a->isolate();
1012 961
1013 Node* const null = a->NullConstant(); 962 Node* const null = a->NullConstant();
1014 963
1015 Variable var_result(a, MachineRepresentation::kTagged); 964 CVariable var_result(a, MachineRepresentation::kTagged);
1016 Label out(a), call_builtin_exec(a), slow_path(a, Label::kDeferred); 965 CLabel out(a), call_builtin_exec(a), slow_path(a, CLabel::kDeferred);
1017 966
1018 Node* const map = a->LoadMap(recv); 967 Node* const map = a->LoadMap(recv);
1019 BranchIfFastPath(a, context, map, &call_builtin_exec, &slow_path); 968 BranchIfFastPath(a, context, map, &call_builtin_exec, &slow_path);
1020 969
1021 a->Bind(&call_builtin_exec); 970 a->Bind(&call_builtin_exec);
1022 { 971 {
1023 Node* const result = RegExpPrototypeExecInternal(a, context, recv, string); 972 Node* const result = RegExpPrototypeExecInternal(a, context, recv, string);
1024 var_result.Bind(result); 973 var_result.Bind(result);
1025 a->Goto(&out); 974 a->Goto(&out);
1026 } 975 }
1027 976
1028 a->Bind(&slow_path); 977 a->Bind(&slow_path);
1029 { 978 {
1030 // Take the slow path of fetching the exec property, calling it, and 979 // Take the slow path of fetching the exec property, calling it, and
1031 // verifying its return value. 980 // verifying its return value.
1032 981
1033 // Get the exec property. 982 // Get the exec property.
1034 Node* const name = a->HeapConstant(isolate->factory()->exec_string()); 983 Node* const name = a->HeapConstant(isolate->factory()->exec_string());
1035 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); 984 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
1036 Node* const exec = a->CallStub(getproperty_callable, context, recv, name); 985 Node* const exec = a->CallStub(getproperty_callable, context, recv, name);
1037 986
1038 // Is {exec} callable? 987 // Is {exec} callable?
1039 Label if_iscallable(a), if_isnotcallable(a); 988 CLabel if_iscallable(a), if_isnotcallable(a);
1040 989
1041 a->GotoIf(a->TaggedIsSmi(exec), &if_isnotcallable); 990 a->GotoIf(a->TaggedIsSmi(exec), &if_isnotcallable);
1042 991
1043 Node* const exec_map = a->LoadMap(exec); 992 Node* const exec_map = a->LoadMap(exec);
1044 a->Branch(a->IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable); 993 a->Branch(a->IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable);
1045 994
1046 a->Bind(&if_iscallable); 995 a->Bind(&if_iscallable);
1047 { 996 {
1048 Callable call_callable = CodeFactory::Call(isolate); 997 Callable call_callable = CodeFactory::Call(isolate);
1049 Node* const result = 998 Node* const result =
(...skipping 17 matching lines...) Expand all
1067 } 1016 }
1068 1017
1069 a->Bind(&out); 1018 a->Bind(&out);
1070 return var_result.value(); 1019 return var_result.value();
1071 } 1020 }
1072 1021
1073 } // namespace 1022 } // namespace
1074 1023
1075 // ES#sec-regexp.prototype.test 1024 // ES#sec-regexp.prototype.test
1076 // RegExp.prototype.test ( S ) 1025 // RegExp.prototype.test ( S )
1077 void Builtins::Generate_RegExpPrototypeTest( 1026 void Builtins::Generate_RegExpPrototypeTest(CodeAssemblerState* state) {
1078 compiler::CodeAssemblerState* state) {
1079 typedef compiler::Node Node;
1080 CodeStubAssembler a(state); 1027 CodeStubAssembler a(state);
1081 1028
1082 Isolate* const isolate = a.isolate(); 1029 Isolate* const isolate = a.isolate();
1083 1030
1084 Node* const maybe_receiver = a.Parameter(0); 1031 Node* const maybe_receiver = a.Parameter(0);
1085 Node* const maybe_string = a.Parameter(1); 1032 Node* const maybe_string = a.Parameter(1);
1086 Node* const context = a.Parameter(4); 1033 Node* const context = a.Parameter(4);
1087 1034
1088 // Ensure {maybe_receiver} is a JSReceiver. 1035 // Ensure {maybe_receiver} is a JSReceiver.
1089 ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver, 1036 ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver,
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1170 } 1117 }
1171 } 1118 }
1172 1119
1173 elems->Shrink(n); 1120 elems->Shrink(n);
1174 return *isolate->factory()->NewJSArrayWithElements(elems); 1121 return *isolate->factory()->NewJSArrayWithElements(elems);
1175 } 1122 }
1176 1123
1177 namespace { 1124 namespace {
1178 1125
1179 void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a, 1126 void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a,
1180 compiler::Node* const receiver, 1127 Node* const receiver,
1181 compiler::Node* const string, 1128 Node* const string, Node* const context,
1182 compiler::Node* const context,
1183 bool is_fastpath) { 1129 bool is_fastpath) {
1184 typedef CodeStubAssembler::Label Label;
1185 typedef compiler::Node Node;
1186
1187 Isolate* const isolate = a->isolate(); 1130 Isolate* const isolate = a->isolate();
1188 1131
1189 Node* const smi_zero = a->SmiConstant(Smi::kZero); 1132 Node* const smi_zero = a->SmiConstant(Smi::kZero);
1190 1133
1191 // Grab the initial value of last index. 1134 // Grab the initial value of last index.
1192 Node* const previous_last_index = 1135 Node* const previous_last_index =
1193 is_fastpath ? FastLoadLastIndex(a, context, receiver) 1136 is_fastpath ? FastLoadLastIndex(a, context, receiver)
1194 : SlowLoadLastIndex(a, context, receiver); 1137 : SlowLoadLastIndex(a, context, receiver);
1195 1138
1196 // Ensure last index is 0. 1139 // Ensure last index is 0.
1197 if (is_fastpath) { 1140 if (is_fastpath) {
1198 FastStoreLastIndex(a, context, receiver, smi_zero); 1141 FastStoreLastIndex(a, context, receiver, smi_zero);
1199 } else { 1142 } else {
1200 Label next(a); 1143 CLabel next(a);
1201 a->GotoIf(a->SameValue(previous_last_index, smi_zero, context), &next); 1144 a->GotoIf(a->SameValue(previous_last_index, smi_zero, context), &next);
1202 1145
1203 SlowStoreLastIndex(a, context, receiver, smi_zero); 1146 SlowStoreLastIndex(a, context, receiver, smi_zero);
1204 a->Goto(&next); 1147 a->Goto(&next);
1205 a->Bind(&next); 1148 a->Bind(&next);
1206 } 1149 }
1207 1150
1208 // Call exec. 1151 // Call exec.
1209 Node* const match_indices = 1152 Node* const match_indices =
1210 is_fastpath ? RegExpPrototypeExecInternal(a, context, receiver, string) 1153 is_fastpath ? RegExpPrototypeExecInternal(a, context, receiver, string)
1211 : RegExpExec(a, context, receiver, string); 1154 : RegExpExec(a, context, receiver, string);
1212 1155
1213 // Reset last index if necessary. 1156 // Reset last index if necessary.
1214 if (is_fastpath) { 1157 if (is_fastpath) {
1215 FastStoreLastIndex(a, context, receiver, previous_last_index); 1158 FastStoreLastIndex(a, context, receiver, previous_last_index);
1216 } else { 1159 } else {
1217 Label next(a); 1160 CLabel next(a);
1218 Node* const current_last_index = SlowLoadLastIndex(a, context, receiver); 1161 Node* const current_last_index = SlowLoadLastIndex(a, context, receiver);
1219 1162
1220 a->GotoIf(a->SameValue(current_last_index, previous_last_index, context), 1163 a->GotoIf(a->SameValue(current_last_index, previous_last_index, context),
1221 &next); 1164 &next);
1222 1165
1223 SlowStoreLastIndex(a, context, receiver, previous_last_index); 1166 SlowStoreLastIndex(a, context, receiver, previous_last_index);
1224 a->Goto(&next); 1167 a->Goto(&next);
1225 a->Bind(&next); 1168 a->Bind(&next);
1226 } 1169 }
1227 1170
1228 // Return -1 if no match was found. 1171 // Return -1 if no match was found.
1229 { 1172 {
1230 Label next(a); 1173 CLabel next(a);
1231 a->GotoUnless(a->WordEqual(match_indices, a->NullConstant()), &next); 1174 a->GotoUnless(a->WordEqual(match_indices, a->NullConstant()), &next);
1232 a->Return(a->SmiConstant(-1)); 1175 a->Return(a->SmiConstant(-1));
1233 a->Bind(&next); 1176 a->Bind(&next);
1234 } 1177 }
1235 1178
1236 // Return the index of the match. 1179 // Return the index of the match.
1237 { 1180 {
1238 Label fast_result(a), slow_result(a, Label::kDeferred); 1181 CLabel fast_result(a), slow_result(a, CLabel::kDeferred);
1239 1182
1240 Node* const native_context = a->LoadNativeContext(context); 1183 Node* const native_context = a->LoadNativeContext(context);
1241 Node* const initial_regexp_result_map = 1184 Node* const initial_regexp_result_map =
1242 a->LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX); 1185 a->LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX);
1243 Node* const match_indices_map = a->LoadMap(match_indices); 1186 Node* const match_indices_map = a->LoadMap(match_indices);
1244 1187
1245 a->Branch(a->WordEqual(match_indices_map, initial_regexp_result_map), 1188 a->Branch(a->WordEqual(match_indices_map, initial_regexp_result_map),
1246 &fast_result, &slow_result); 1189 &fast_result, &slow_result);
1247 1190
1248 a->Bind(&fast_result); 1191 a->Bind(&fast_result);
(...skipping 12 matching lines...) Expand all
1261 a->CallStub(getproperty_callable, context, match_indices, name); 1204 a->CallStub(getproperty_callable, context, match_indices, name);
1262 a->Return(index); 1205 a->Return(index);
1263 } 1206 }
1264 } 1207 }
1265 } 1208 }
1266 1209
1267 } // namespace 1210 } // namespace
1268 1211
1269 // ES#sec-regexp.prototype-@@search 1212 // ES#sec-regexp.prototype-@@search
1270 // RegExp.prototype [ @@search ] ( string ) 1213 // RegExp.prototype [ @@search ] ( string )
1271 void Builtins::Generate_RegExpPrototypeSearch( 1214 void Builtins::Generate_RegExpPrototypeSearch(CodeAssemblerState* state) {
1272 compiler::CodeAssemblerState* state) {
1273 typedef CodeStubAssembler::Label Label;
1274 typedef compiler::Node Node;
1275 CodeStubAssembler a(state); 1215 CodeStubAssembler a(state);
1276 1216
1277 Isolate* const isolate = a.isolate(); 1217 Isolate* const isolate = a.isolate();
1278 1218
1279 Node* const maybe_receiver = a.Parameter(0); 1219 Node* const maybe_receiver = a.Parameter(0);
1280 Node* const maybe_string = a.Parameter(1); 1220 Node* const maybe_string = a.Parameter(1);
1281 Node* const context = a.Parameter(4); 1221 Node* const context = a.Parameter(4);
1282 1222
1283 // Ensure {maybe_receiver} is a JSReceiver. 1223 // Ensure {maybe_receiver} is a JSReceiver.
1284 Node* const map = 1224 Node* const map =
1285 ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver, 1225 ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver,
1286 MessageTemplate::kIncompatibleMethodReceiver, 1226 MessageTemplate::kIncompatibleMethodReceiver,
1287 "RegExp.prototype.@@search"); 1227 "RegExp.prototype.@@search");
1288 Node* const receiver = maybe_receiver; 1228 Node* const receiver = maybe_receiver;
1289 1229
1290 // Convert {maybe_string} to a String. 1230 // Convert {maybe_string} to a String.
1291 Node* const string = a.ToString(context, maybe_string); 1231 Node* const string = a.ToString(context, maybe_string);
1292 1232
1293 Label fast_path(&a), slow_path(&a); 1233 CLabel fast_path(&a), slow_path(&a);
1294 BranchIfFastPath(&a, context, map, &fast_path, &slow_path); 1234 BranchIfFastPath(&a, context, map, &fast_path, &slow_path);
1295 1235
1296 a.Bind(&fast_path); 1236 a.Bind(&fast_path);
1297 Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, true); 1237 Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, true);
1298 1238
1299 a.Bind(&slow_path); 1239 a.Bind(&slow_path);
1300 Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, false); 1240 Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, false);
1301 } 1241 }
1302 1242
1303 namespace { 1243 namespace {
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
1639 Handle<String> substr = 1579 Handle<String> substr =
1640 factory->NewSubString(string, prev_string_index, length); 1580 factory->NewSubString(string, prev_string_index, length);
1641 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); 1581 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1642 } 1582 }
1643 1583
1644 return *NewJSArrayWithElements(isolate, elems, num_elems); 1584 return *NewJSArrayWithElements(isolate, elems, num_elems);
1645 } 1585 }
1646 1586
1647 namespace { 1587 namespace {
1648 1588
1649 compiler::Node* ReplaceGlobalCallableFastPath( 1589 Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context,
1650 CodeStubAssembler* a, compiler::Node* context, compiler::Node* regexp, 1590 Node* regexp, Node* subject_string,
1651 compiler::Node* subject_string, compiler::Node* replace_callable) { 1591 Node* replace_callable) {
1652 // The fast path is reached only if {receiver} is a global unmodified 1592 // The fast path is reached only if {receiver} is a global unmodified
1653 // JSRegExp instance and {replace_callable} is callable. 1593 // JSRegExp instance and {replace_callable} is callable.
1654 1594
1655 typedef CodeStubAssembler::Variable Variable;
1656 typedef CodeStubAssembler::Label Label;
1657 typedef compiler::Node Node;
1658
1659 Isolate* const isolate = a->isolate(); 1595 Isolate* const isolate = a->isolate();
1660 1596
1661 Node* const null = a->NullConstant(); 1597 Node* const null = a->NullConstant();
1662 Node* const undefined = a->UndefinedConstant(); 1598 Node* const undefined = a->UndefinedConstant();
1663 Node* const int_zero = a->IntPtrConstant(0); 1599 Node* const int_zero = a->IntPtrConstant(0);
1664 Node* const int_one = a->IntPtrConstant(1); 1600 Node* const int_one = a->IntPtrConstant(1);
1665 Node* const smi_zero = a->SmiConstant(Smi::kZero); 1601 Node* const smi_zero = a->SmiConstant(Smi::kZero);
1666 1602
1667 Node* const native_context = a->LoadNativeContext(context); 1603 Node* const native_context = a->LoadNativeContext(context);
1668 1604
1669 Label out(a); 1605 CLabel out(a);
1670 Variable var_result(a, MachineRepresentation::kTagged); 1606 CVariable var_result(a, MachineRepresentation::kTagged);
1671 1607
1672 // Set last index to 0. 1608 // Set last index to 0.
1673 FastStoreLastIndex(a, context, regexp, smi_zero); 1609 FastStoreLastIndex(a, context, regexp, smi_zero);
1674 1610
1675 // Allocate {result_array}. 1611 // Allocate {result_array}.
1676 Node* result_array; 1612 Node* result_array;
1677 { 1613 {
1678 ElementsKind kind = FAST_ELEMENTS; 1614 ElementsKind kind = FAST_ELEMENTS;
1679 Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context); 1615 Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context);
1680 Node* const capacity = a->IntPtrConstant(16); 1616 Node* const capacity = a->IntPtrConstant(16);
(...skipping 26 matching lines...) Expand all
1707 1643
1708 Node* const res_length = a->LoadJSArrayLength(res); 1644 Node* const res_length = a->LoadJSArrayLength(res);
1709 Node* const res_elems = a->LoadElements(res); 1645 Node* const res_elems = a->LoadElements(res);
1710 CSA_ASSERT(a, a->HasInstanceType(res_elems, FIXED_ARRAY_TYPE)); 1646 CSA_ASSERT(a, a->HasInstanceType(res_elems, FIXED_ARRAY_TYPE));
1711 1647
1712 CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; 1648 CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
1713 Node* const num_capture_registers = a->LoadFixedArrayElement( 1649 Node* const num_capture_registers = a->LoadFixedArrayElement(
1714 last_match_info, 1650 last_match_info,
1715 a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode); 1651 a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode);
1716 1652
1717 Label if_hasexplicitcaptures(a), if_noexplicitcaptures(a), create_result(a); 1653 CLabel if_hasexplicitcaptures(a), if_noexplicitcaptures(a), create_result(a);
1718 a->Branch(a->SmiEqual(num_capture_registers, a->SmiConstant(Smi::FromInt(2))), 1654 a->Branch(a->SmiEqual(num_capture_registers, a->SmiConstant(Smi::FromInt(2))),
1719 &if_noexplicitcaptures, &if_hasexplicitcaptures); 1655 &if_noexplicitcaptures, &if_hasexplicitcaptures);
1720 1656
1721 a->Bind(&if_noexplicitcaptures); 1657 a->Bind(&if_noexplicitcaptures);
1722 { 1658 {
1723 // If the number of captures is two then there are no explicit captures in 1659 // If the number of captures is two then there are no explicit captures in
1724 // the regexp, just the implicit capture that captures the whole match. In 1660 // the regexp, just the implicit capture that captures the whole match. In
1725 // this case we can simplify quite a bit and end up with something faster. 1661 // this case we can simplify quite a bit and end up with something faster.
1726 // The builder will consist of some integers that indicate slices of the 1662 // The builder will consist of some integers that indicate slices of the
1727 // input string and some replacements that were returned from the replace 1663 // input string and some replacements that were returned from the replace
1728 // function. 1664 // function.
1729 1665
1730 Variable var_match_start(a, MachineRepresentation::kTagged); 1666 CVariable var_match_start(a, MachineRepresentation::kTagged);
1731 var_match_start.Bind(smi_zero); 1667 var_match_start.Bind(smi_zero);
1732 1668
1733 Node* const end = a->SmiUntag(res_length); 1669 Node* const end = a->SmiUntag(res_length);
1734 Variable var_i(a, MachineType::PointerRepresentation()); 1670 CVariable var_i(a, MachineType::PointerRepresentation());
1735 var_i.Bind(int_zero); 1671 var_i.Bind(int_zero);
1736 1672
1737 Variable* vars[] = {&var_i, &var_match_start}; 1673 CVariable* vars[] = {&var_i, &var_match_start};
1738 Label loop(a, 2, vars); 1674 CLabel loop(a, 2, vars);
1739 a->Goto(&loop); 1675 a->Goto(&loop);
1740 a->Bind(&loop); 1676 a->Bind(&loop);
1741 { 1677 {
1742 Node* const i = var_i.value(); 1678 Node* const i = var_i.value();
1743 a->GotoUnless(a->IntPtrLessThan(i, end), &create_result); 1679 a->GotoUnless(a->IntPtrLessThan(i, end), &create_result);
1744 1680
1745 CodeStubAssembler::ParameterMode mode = 1681 CodeStubAssembler::ParameterMode mode =
1746 CodeStubAssembler::INTPTR_PARAMETERS; 1682 CodeStubAssembler::INTPTR_PARAMETERS;
1747 Node* const elem = a->LoadFixedArrayElement(res_elems, i, 0, mode); 1683 Node* const elem = a->LoadFixedArrayElement(res_elems, i, 0, mode);
1748 1684
1749 Label if_issmi(a), if_isstring(a), loop_epilogue(a); 1685 CLabel if_issmi(a), if_isstring(a), loop_epilogue(a);
1750 a->Branch(a->TaggedIsSmi(elem), &if_issmi, &if_isstring); 1686 a->Branch(a->TaggedIsSmi(elem), &if_issmi, &if_isstring);
1751 1687
1752 a->Bind(&if_issmi); 1688 a->Bind(&if_issmi);
1753 { 1689 {
1754 // Integers represent slices of the original string. 1690 // Integers represent slices of the original string.
1755 Label if_isnegativeorzero(a), if_ispositive(a); 1691 CLabel if_isnegativeorzero(a), if_ispositive(a);
1756 a->BranchIfSmiLessThanOrEqual(elem, smi_zero, &if_isnegativeorzero, 1692 a->BranchIfSmiLessThanOrEqual(elem, smi_zero, &if_isnegativeorzero,
1757 &if_ispositive); 1693 &if_ispositive);
1758 1694
1759 a->Bind(&if_ispositive); 1695 a->Bind(&if_ispositive);
1760 { 1696 {
1761 Node* const int_elem = a->SmiUntag(elem); 1697 Node* const int_elem = a->SmiUntag(elem);
1762 Node* const new_match_start = 1698 Node* const new_match_start =
1763 a->IntPtrAdd(a->WordShr(int_elem, a->IntPtrConstant(11)), 1699 a->IntPtrAdd(a->WordShr(int_elem, a->IntPtrConstant(11)),
1764 a->WordAnd(int_elem, a->IntPtrConstant(0x7ff))); 1700 a->WordAnd(int_elem, a->IntPtrConstant(0x7ff)));
1765 var_match_start.Bind(a->SmiTag(new_match_start)); 1701 var_match_start.Bind(a->SmiTag(new_match_start));
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1817 Node* const to = a->SmiUntag(res_length); 1753 Node* const to = a->SmiUntag(res_length);
1818 const int increment = 1; 1754 const int increment = 1;
1819 1755
1820 a->BuildFastLoop( 1756 a->BuildFastLoop(
1821 MachineType::PointerRepresentation(), from, to, 1757 MachineType::PointerRepresentation(), from, to,
1822 [res_elems, isolate, native_context, context, undefined, 1758 [res_elems, isolate, native_context, context, undefined,
1823 replace_callable, mode](CodeStubAssembler* a, Node* index) { 1759 replace_callable, mode](CodeStubAssembler* a, Node* index) {
1824 Node* const elem = 1760 Node* const elem =
1825 a->LoadFixedArrayElement(res_elems, index, 0, mode); 1761 a->LoadFixedArrayElement(res_elems, index, 0, mode);
1826 1762
1827 Label do_continue(a); 1763 CLabel do_continue(a);
1828 a->GotoIf(a->TaggedIsSmi(elem), &do_continue); 1764 a->GotoIf(a->TaggedIsSmi(elem), &do_continue);
1829 1765
1830 // elem must be an Array. 1766 // elem must be an Array.
1831 // Use the apply argument as backing for global RegExp properties. 1767 // Use the apply argument as backing for global RegExp properties.
1832 1768
1833 CSA_ASSERT(a, a->HasInstanceType(elem, JS_ARRAY_TYPE)); 1769 CSA_ASSERT(a, a->HasInstanceType(elem, JS_ARRAY_TYPE));
1834 1770
1835 // TODO(jgruber): Remove indirection through Call->ReflectApply. 1771 // TODO(jgruber): Remove indirection through Call->ReflectApply.
1836 Callable call_callable = CodeFactory::Call(isolate); 1772 Callable call_callable = CodeFactory::Call(isolate);
1837 Node* const reflect_apply = a->LoadContextElement( 1773 Node* const reflect_apply = a->LoadContextElement(
(...skipping 23 matching lines...) Expand all
1861 Node* const result = a->CallRuntime(Runtime::kStringBuilderConcat, context, 1797 Node* const result = a->CallRuntime(Runtime::kStringBuilderConcat, context,
1862 res, res_length, subject_string); 1798 res, res_length, subject_string);
1863 var_result.Bind(result); 1799 var_result.Bind(result);
1864 a->Goto(&out); 1800 a->Goto(&out);
1865 } 1801 }
1866 1802
1867 a->Bind(&out); 1803 a->Bind(&out);
1868 return var_result.value(); 1804 return var_result.value();
1869 } 1805 }
1870 1806
1871 compiler::Node* ReplaceSimpleStringFastPath(CodeStubAssembler* a, 1807 Node* ReplaceSimpleStringFastPath(CodeStubAssembler* a, Node* context,
1872 compiler::Node* context, 1808 Node* regexp, Node* subject_string,
1873 compiler::Node* regexp, 1809 Node* replace_string) {
1874 compiler::Node* subject_string,
1875 compiler::Node* replace_string) {
1876 // The fast path is reached only if {receiver} is an unmodified 1810 // The fast path is reached only if {receiver} is an unmodified
1877 // JSRegExp instance, {replace_value} is non-callable, and 1811 // JSRegExp instance, {replace_value} is non-callable, and
1878 // ToString({replace_value}) does not contain '$', i.e. we're doing a simple 1812 // ToString({replace_value}) does not contain '$', i.e. we're doing a simple
1879 // string replacement. 1813 // string replacement.
1880 1814
1881 typedef CodeStubAssembler::Variable Variable;
1882 typedef CodeStubAssembler::Label Label;
1883 typedef compiler::Node Node;
1884
1885 Isolate* const isolate = a->isolate(); 1815 Isolate* const isolate = a->isolate();
1886 1816
1887 Node* const null = a->NullConstant(); 1817 Node* const null = a->NullConstant();
1888 Node* const int_zero = a->IntPtrConstant(0); 1818 Node* const int_zero = a->IntPtrConstant(0);
1889 Node* const smi_zero = a->SmiConstant(Smi::kZero); 1819 Node* const smi_zero = a->SmiConstant(Smi::kZero);
1890 1820
1891 Label out(a); 1821 CLabel out(a);
1892 Variable var_result(a, MachineRepresentation::kTagged); 1822 CVariable var_result(a, MachineRepresentation::kTagged);
1893 1823
1894 // Load the last match info. 1824 // Load the last match info.
1895 Node* const native_context = a->LoadNativeContext(context); 1825 Node* const native_context = a->LoadNativeContext(context);
1896 Node* const last_match_info = a->LoadContextElement( 1826 Node* const last_match_info = a->LoadContextElement(
1897 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 1827 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
1898 1828
1899 // Is {regexp} global? 1829 // Is {regexp} global?
1900 Label if_isglobal(a), if_isnonglobal(a); 1830 CLabel if_isglobal(a), if_isnonglobal(a);
1901 Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset); 1831 Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset);
1902 Node* const is_global = 1832 Node* const is_global =
1903 a->WordAnd(a->SmiUntag(flags), a->IntPtrConstant(JSRegExp::kGlobal)); 1833 a->WordAnd(a->SmiUntag(flags), a->IntPtrConstant(JSRegExp::kGlobal));
1904 a->Branch(a->WordEqual(is_global, int_zero), &if_isnonglobal, &if_isglobal); 1834 a->Branch(a->WordEqual(is_global, int_zero), &if_isnonglobal, &if_isglobal);
1905 1835
1906 a->Bind(&if_isglobal); 1836 a->Bind(&if_isglobal);
1907 { 1837 {
1908 // Hand off global regexps to runtime. 1838 // Hand off global regexps to runtime.
1909 FastStoreLastIndex(a, context, regexp, smi_zero); 1839 FastStoreLastIndex(a, context, regexp, smi_zero);
1910 Node* const result = 1840 Node* const result =
1911 a->CallRuntime(Runtime::kStringReplaceGlobalRegExpWithString, context, 1841 a->CallRuntime(Runtime::kStringReplaceGlobalRegExpWithString, context,
1912 subject_string, regexp, replace_string, last_match_info); 1842 subject_string, regexp, replace_string, last_match_info);
1913 var_result.Bind(result); 1843 var_result.Bind(result);
1914 a->Goto(&out); 1844 a->Goto(&out);
1915 } 1845 }
1916 1846
1917 a->Bind(&if_isnonglobal); 1847 a->Bind(&if_isnonglobal);
1918 { 1848 {
1919 // Run exec, then manually construct the resulting string. 1849 // Run exec, then manually construct the resulting string.
1920 Callable exec_callable = CodeFactory::RegExpExec(isolate); 1850 Callable exec_callable = CodeFactory::RegExpExec(isolate);
1921 Node* const match_indices = 1851 Node* const match_indices =
1922 a->CallStub(exec_callable, context, regexp, subject_string, smi_zero, 1852 a->CallStub(exec_callable, context, regexp, subject_string, smi_zero,
1923 last_match_info); 1853 last_match_info);
1924 1854
1925 Label if_matched(a), if_didnotmatch(a); 1855 CLabel if_matched(a), if_didnotmatch(a);
1926 a->Branch(a->WordEqual(match_indices, null), &if_didnotmatch, &if_matched); 1856 a->Branch(a->WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
1927 1857
1928 a->Bind(&if_didnotmatch); 1858 a->Bind(&if_didnotmatch);
1929 { 1859 {
1930 FastStoreLastIndex(a, context, regexp, smi_zero); 1860 FastStoreLastIndex(a, context, regexp, smi_zero);
1931 var_result.Bind(subject_string); 1861 var_result.Bind(subject_string);
1932 a->Goto(&out); 1862 a->Goto(&out);
1933 } 1863 }
1934 1864
1935 a->Bind(&if_matched); 1865 a->Bind(&if_matched);
1936 { 1866 {
1937 CodeStubAssembler::ParameterMode mode = 1867 CodeStubAssembler::ParameterMode mode =
1938 CodeStubAssembler::INTPTR_PARAMETERS; 1868 CodeStubAssembler::INTPTR_PARAMETERS;
1939 1869
1940 Node* const subject_start = smi_zero; 1870 Node* const subject_start = smi_zero;
1941 Node* const match_start = a->LoadFixedArrayElement( 1871 Node* const match_start = a->LoadFixedArrayElement(
1942 match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), 1872 match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex),
1943 0, mode); 1873 0, mode);
1944 Node* const match_end = a->LoadFixedArrayElement( 1874 Node* const match_end = a->LoadFixedArrayElement(
1945 match_indices, 1875 match_indices,
1946 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode); 1876 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode);
1947 Node* const subject_end = a->LoadStringLength(subject_string); 1877 Node* const subject_end = a->LoadStringLength(subject_string);
1948 1878
1949 Label if_replaceisempty(a), if_replaceisnotempty(a); 1879 CLabel if_replaceisempty(a), if_replaceisnotempty(a);
1950 Node* const replace_length = a->LoadStringLength(replace_string); 1880 Node* const replace_length = a->LoadStringLength(replace_string);
1951 a->Branch(a->SmiEqual(replace_length, smi_zero), &if_replaceisempty, 1881 a->Branch(a->SmiEqual(replace_length, smi_zero), &if_replaceisempty,
1952 &if_replaceisnotempty); 1882 &if_replaceisnotempty);
1953 1883
1954 a->Bind(&if_replaceisempty); 1884 a->Bind(&if_replaceisempty);
1955 { 1885 {
1956 // TODO(jgruber): We could skip many of the checks that using SubString 1886 // TODO(jgruber): We could skip many of the checks that using SubString
1957 // here entails. 1887 // here entails.
1958 1888
1959 Node* const first_part = 1889 Node* const first_part =
(...skipping 24 matching lines...) Expand all
1984 } 1914 }
1985 1915
1986 a->Bind(&out); 1916 a->Bind(&out);
1987 return var_result.value(); 1917 return var_result.value();
1988 } 1918 }
1989 1919
1990 } // namespace 1920 } // namespace
1991 1921
1992 // ES#sec-regexp.prototype-@@replace 1922 // ES#sec-regexp.prototype-@@replace
1993 // RegExp.prototype [ @@replace ] ( string, replaceValue ) 1923 // RegExp.prototype [ @@replace ] ( string, replaceValue )
1994 void Builtins::Generate_RegExpPrototypeReplace( 1924 void Builtins::Generate_RegExpPrototypeReplace(CodeAssemblerState* state) {
1995 compiler::CodeAssemblerState* state) {
1996 typedef CodeStubAssembler::Label Label;
1997 typedef compiler::Node Node;
1998 CodeStubAssembler a(state); 1925 CodeStubAssembler a(state);
1999 1926
2000 Isolate* const isolate = a.isolate(); 1927 Isolate* const isolate = a.isolate();
2001 1928
2002 Node* const maybe_receiver = a.Parameter(0); 1929 Node* const maybe_receiver = a.Parameter(0);
2003 Node* const maybe_string = a.Parameter(1); 1930 Node* const maybe_string = a.Parameter(1);
2004 Node* const replace_value = a.Parameter(2); 1931 Node* const replace_value = a.Parameter(2);
2005 Node* const context = a.Parameter(5); 1932 Node* const context = a.Parameter(5);
2006 1933
2007 Node* const int_zero = a.IntPtrConstant(0); 1934 Node* const int_zero = a.IntPtrConstant(0);
2008 1935
2009 // Ensure {maybe_receiver} is a JSReceiver. 1936 // Ensure {maybe_receiver} is a JSReceiver.
2010 Node* const map = 1937 Node* const map =
2011 ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver, 1938 ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver,
2012 MessageTemplate::kIncompatibleMethodReceiver, 1939 MessageTemplate::kIncompatibleMethodReceiver,
2013 "RegExp.prototype.@@replace"); 1940 "RegExp.prototype.@@replace");
2014 Node* const receiver = maybe_receiver; 1941 Node* const receiver = maybe_receiver;
2015 1942
2016 // Convert {maybe_string} to a String. 1943 // Convert {maybe_string} to a String.
2017 Callable tostring_callable = CodeFactory::ToString(isolate); 1944 Callable tostring_callable = CodeFactory::ToString(isolate);
2018 Node* const string = a.CallStub(tostring_callable, context, maybe_string); 1945 Node* const string = a.CallStub(tostring_callable, context, maybe_string);
2019 1946
2020 // Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance? 1947 // Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance?
2021 Label checkreplacecallable(&a), runtime(&a, Label::kDeferred), fastpath(&a); 1948 CLabel checkreplacecallable(&a), runtime(&a, CLabel::kDeferred), fastpath(&a);
2022 BranchIfFastPath(&a, context, map, &checkreplacecallable, &runtime); 1949 BranchIfFastPath(&a, context, map, &checkreplacecallable, &runtime);
2023 1950
2024 a.Bind(&checkreplacecallable); 1951 a.Bind(&checkreplacecallable);
2025 Node* const regexp = receiver; 1952 Node* const regexp = receiver;
2026 1953
2027 // 2. Is {replace_value} callable? 1954 // 2. Is {replace_value} callable?
2028 Label checkreplacestring(&a), if_iscallable(&a); 1955 CLabel checkreplacestring(&a), if_iscallable(&a);
2029 a.GotoIf(a.TaggedIsSmi(replace_value), &checkreplacestring); 1956 a.GotoIf(a.TaggedIsSmi(replace_value), &checkreplacestring);
2030 1957
2031 Node* const replace_value_map = a.LoadMap(replace_value); 1958 Node* const replace_value_map = a.LoadMap(replace_value);
2032 a.Branch(a.IsCallableMap(replace_value_map), &if_iscallable, 1959 a.Branch(a.IsCallableMap(replace_value_map), &if_iscallable,
2033 &checkreplacestring); 1960 &checkreplacestring);
2034 1961
2035 // 3. Does ToString({replace_value}) contain '$'? 1962 // 3. Does ToString({replace_value}) contain '$'?
2036 a.Bind(&checkreplacestring); 1963 a.Bind(&checkreplacestring);
2037 { 1964 {
2038 Node* const replace_string = 1965 Node* const replace_string =
2039 a.CallStub(tostring_callable, context, replace_value); 1966 a.CallStub(tostring_callable, context, replace_value);
2040 1967
2041 Node* const dollar_char = a.IntPtrConstant('$'); 1968 Node* const dollar_char = a.IntPtrConstant('$');
2042 Node* const smi_minusone = a.SmiConstant(Smi::FromInt(-1)); 1969 Node* const smi_minusone = a.SmiConstant(Smi::FromInt(-1));
2043 a.GotoUnless(a.SmiEqual(a.StringIndexOfChar(context, replace_string, 1970 a.GotoUnless(a.SmiEqual(a.StringIndexOfChar(context, replace_string,
2044 dollar_char, int_zero), 1971 dollar_char, int_zero),
2045 smi_minusone), 1972 smi_minusone),
2046 &runtime); 1973 &runtime);
2047 1974
2048 a.Return(ReplaceSimpleStringFastPath(&a, context, regexp, string, 1975 a.Return(ReplaceSimpleStringFastPath(&a, context, regexp, string,
2049 replace_string)); 1976 replace_string));
2050 } 1977 }
2051 1978
2052 // {regexp} is unmodified and {replace_value} is callable. 1979 // {regexp} is unmodified and {replace_value} is callable.
2053 a.Bind(&if_iscallable); 1980 a.Bind(&if_iscallable);
2054 { 1981 {
2055 Node* const replace_callable = replace_value; 1982 Node* const replace_callable = replace_value;
2056 1983
2057 // Check if the {regexp} is global. 1984 // Check if the {regexp} is global.
2058 Label if_isglobal(&a), if_isnotglobal(&a); 1985 CLabel if_isglobal(&a), if_isnotglobal(&a);
2059 Node* const is_global = FastFlagGetter(&a, regexp, JSRegExp::kGlobal); 1986 Node* const is_global = FastFlagGetter(&a, regexp, JSRegExp::kGlobal);
2060 a.Branch(is_global, &if_isglobal, &if_isnotglobal); 1987 a.Branch(is_global, &if_isglobal, &if_isnotglobal);
2061 1988
2062 a.Bind(&if_isglobal); 1989 a.Bind(&if_isglobal);
2063 { 1990 {
2064 Node* const result = ReplaceGlobalCallableFastPath( 1991 Node* const result = ReplaceGlobalCallableFastPath(
2065 &a, context, regexp, string, replace_callable); 1992 &a, context, regexp, string, replace_callable);
2066 a.Return(result); 1993 a.Return(result);
2067 } 1994 }
2068 1995
2069 a.Bind(&if_isnotglobal); 1996 a.Bind(&if_isnotglobal);
2070 { 1997 {
2071 Node* const result = 1998 Node* const result =
2072 a.CallRuntime(Runtime::kStringReplaceNonGlobalRegExpWithFunction, 1999 a.CallRuntime(Runtime::kStringReplaceNonGlobalRegExpWithFunction,
2073 context, string, regexp, replace_callable); 2000 context, string, regexp, replace_callable);
2074 a.Return(result); 2001 a.Return(result);
2075 } 2002 }
2076 } 2003 }
2077 2004
2078 a.Bind(&runtime); 2005 a.Bind(&runtime);
2079 { 2006 {
2080 Node* const result = a.CallRuntime(Runtime::kRegExpReplace, context, 2007 Node* const result = a.CallRuntime(Runtime::kRegExpReplace, context,
2081 receiver, string, replace_value); 2008 receiver, string, replace_value);
2082 a.Return(result); 2009 a.Return(result);
2083 } 2010 }
2084 } 2011 }
2085 2012
2086 // Simple string matching functionality for internal use which does not modify 2013 // Simple string matching functionality for internal use which does not modify
2087 // the last match info. 2014 // the last match info.
2088 void Builtins::Generate_RegExpInternalMatch( 2015 void Builtins::Generate_RegExpInternalMatch(CodeAssemblerState* state) {
2089 compiler::CodeAssemblerState* state) {
2090 typedef CodeStubAssembler::Label Label;
2091 typedef compiler::Node Node;
2092 CodeStubAssembler a(state); 2016 CodeStubAssembler a(state);
2093 2017
2094 Isolate* const isolate = a.isolate(); 2018 Isolate* const isolate = a.isolate();
2095 2019
2096 Node* const regexp = a.Parameter(1); 2020 Node* const regexp = a.Parameter(1);
2097 Node* const string = a.Parameter(2); 2021 Node* const string = a.Parameter(2);
2098 Node* const context = a.Parameter(5); 2022 Node* const context = a.Parameter(5);
2099 2023
2100 Node* const null = a.NullConstant(); 2024 Node* const null = a.NullConstant();
2101 Node* const smi_zero = a.SmiConstant(Smi::FromInt(0)); 2025 Node* const smi_zero = a.SmiConstant(Smi::FromInt(0));
2102 2026
2103 Node* const native_context = a.LoadNativeContext(context); 2027 Node* const native_context = a.LoadNativeContext(context);
2104 Node* const internal_match_info = a.LoadContextElement( 2028 Node* const internal_match_info = a.LoadContextElement(
2105 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX); 2029 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX);
2106 2030
2107 Callable exec_callable = CodeFactory::RegExpExec(isolate); 2031 Callable exec_callable = CodeFactory::RegExpExec(isolate);
2108 Node* const match_indices = a.CallStub(exec_callable, context, regexp, string, 2032 Node* const match_indices = a.CallStub(exec_callable, context, regexp, string,
2109 smi_zero, internal_match_info); 2033 smi_zero, internal_match_info);
2110 2034
2111 Label if_matched(&a), if_didnotmatch(&a); 2035 CLabel if_matched(&a), if_didnotmatch(&a);
2112 a.Branch(a.WordEqual(match_indices, null), &if_didnotmatch, &if_matched); 2036 a.Branch(a.WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
2113 2037
2114 a.Bind(&if_didnotmatch); 2038 a.Bind(&if_didnotmatch);
2115 a.Return(null); 2039 a.Return(null);
2116 2040
2117 a.Bind(&if_matched); 2041 a.Bind(&if_matched);
2118 { 2042 {
2119 Node* result = ConstructNewResultFromMatchInfo(isolate, &a, context, 2043 Node* result = ConstructNewResultFromMatchInfo(isolate, &a, context,
2120 match_indices, string); 2044 match_indices, string);
2121 a.Return(result); 2045 a.Return(result);
2122 } 2046 }
2123 } 2047 }
2124 2048
2125 } // namespace internal 2049 } // namespace internal
2126 } // namespace v8 2050 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698