OLD | NEW |
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 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 a->Bind(&next_iter); | 316 a->Bind(&next_iter); |
317 var_from_cursor.Bind(a->IntPtrAdd(from_cursor, a->IntPtrConstant(2))); | 317 var_from_cursor.Bind(a->IntPtrAdd(from_cursor, a->IntPtrConstant(2))); |
318 var_to_cursor.Bind(a->IntPtrAdd(to_cursor, a->IntPtrConstant(1))); | 318 var_to_cursor.Bind(a->IntPtrAdd(to_cursor, a->IntPtrConstant(1))); |
319 a->Branch(a->UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out); | 319 a->Branch(a->UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out); |
320 } | 320 } |
321 | 321 |
322 a->Bind(&out); | 322 a->Bind(&out); |
323 return result; | 323 return result; |
324 } | 324 } |
325 | 325 |
326 } // namespace | |
327 | |
328 // ES#sec-regexp.prototype.exec | 326 // ES#sec-regexp.prototype.exec |
329 // RegExp.prototype.exec ( string ) | 327 // RegExp.prototype.exec ( string ) |
330 void Builtins::Generate_RegExpPrototypeExec(CodeStubAssembler* a) { | 328 compiler::Node* RegExpPrototypeExecInternal(CodeStubAssembler* a, |
| 329 compiler::Node* context, |
| 330 compiler::Node* maybe_receiver, |
| 331 compiler::Node* maybe_string) { |
331 typedef CodeStubAssembler::Variable Variable; | 332 typedef CodeStubAssembler::Variable Variable; |
332 typedef CodeStubAssembler::Label Label; | 333 typedef CodeStubAssembler::Label Label; |
333 typedef compiler::Node Node; | 334 typedef compiler::Node Node; |
334 | 335 |
335 Isolate* const isolate = a->isolate(); | 336 Isolate* const isolate = a->isolate(); |
336 | 337 |
337 Node* const receiver = a->Parameter(0); | |
338 Node* const maybe_string = a->Parameter(1); | |
339 Node* const context = a->Parameter(4); | |
340 | |
341 Node* const null = a->NullConstant(); | 338 Node* const null = a->NullConstant(); |
342 Node* const int_zero = a->IntPtrConstant(0); | 339 Node* const int_zero = a->IntPtrConstant(0); |
343 Node* const smi_zero = a->SmiConstant(Smi::kZero); | 340 Node* const smi_zero = a->SmiConstant(Smi::kZero); |
344 | 341 |
345 // Ensure {receiver} is a JSRegExp. | 342 Variable var_result(a, MachineRepresentation::kTagged); |
| 343 Label out(a); |
| 344 |
| 345 // Ensure {maybe_receiver} is a JSRegExp. |
346 Node* const regexp_map = a->ThrowIfNotInstanceType( | 346 Node* const regexp_map = a->ThrowIfNotInstanceType( |
347 context, receiver, JS_REGEXP_TYPE, "RegExp.prototype.exec"); | 347 context, maybe_receiver, JS_REGEXP_TYPE, "RegExp.prototype.exec"); |
348 Node* const regexp = receiver; | 348 Node* const regexp = maybe_receiver; |
349 | 349 |
350 // Check whether the regexp instance is unmodified. | 350 // Check whether the regexp instance is unmodified. |
351 Node* const native_context = a->LoadNativeContext(context); | 351 Node* const native_context = a->LoadNativeContext(context); |
352 Node* const regexp_fun = | 352 Node* const regexp_fun = |
353 a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); | 353 a->LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); |
354 Node* const initial_map = | 354 Node* const initial_map = |
355 a->LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); | 355 a->LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset); |
356 Node* const has_initialmap = a->WordEqual(regexp_map, initial_map); | 356 Node* const has_initialmap = a->WordEqual(regexp_map, initial_map); |
357 | 357 |
358 // Convert {maybe_string} to a string. | 358 // Convert {maybe_string} to a string. |
(...skipping 28 matching lines...) Expand all Loading... |
387 var_lastindex.Bind(lastindex); | 387 var_lastindex.Bind(lastindex); |
388 | 388 |
389 Label if_isoob(a, Label::kDeferred); | 389 Label if_isoob(a, Label::kDeferred); |
390 a->GotoUnless(a->TaggedIsSmi(lastindex), &if_isoob); | 390 a->GotoUnless(a->TaggedIsSmi(lastindex), &if_isoob); |
391 a->GotoUnless(a->SmiLessThanOrEqual(lastindex, string_length), &if_isoob); | 391 a->GotoUnless(a->SmiLessThanOrEqual(lastindex, string_length), &if_isoob); |
392 a->Goto(&run_exec); | 392 a->Goto(&run_exec); |
393 | 393 |
394 a->Bind(&if_isoob); | 394 a->Bind(&if_isoob); |
395 { | 395 { |
396 StoreLastIndex(a, context, has_initialmap, regexp, smi_zero); | 396 StoreLastIndex(a, context, has_initialmap, regexp, smi_zero); |
397 a->Return(null); | 397 var_result.Bind(null); |
| 398 a->Goto(&out); |
398 } | 399 } |
399 } | 400 } |
400 | 401 |
401 a->Bind(&if_dontupdate); | 402 a->Bind(&if_dontupdate); |
402 { | 403 { |
403 var_lastindex.Bind(smi_zero); | 404 var_lastindex.Bind(smi_zero); |
404 a->Goto(&run_exec); | 405 a->Goto(&run_exec); |
405 } | 406 } |
406 } | 407 } |
407 | 408 |
(...skipping 14 matching lines...) Expand all Loading... |
422 // Return early if exec failed, possibly updating last index. | 423 // Return early if exec failed, possibly updating last index. |
423 a->GotoUnless(a->WordEqual(match_indices, null), &successful_match); | 424 a->GotoUnless(a->WordEqual(match_indices, null), &successful_match); |
424 | 425 |
425 Label return_null(a); | 426 Label return_null(a); |
426 a->GotoUnless(should_update_last_index, &return_null); | 427 a->GotoUnless(should_update_last_index, &return_null); |
427 | 428 |
428 StoreLastIndex(a, context, has_initialmap, regexp, smi_zero); | 429 StoreLastIndex(a, context, has_initialmap, regexp, smi_zero); |
429 a->Goto(&return_null); | 430 a->Goto(&return_null); |
430 | 431 |
431 a->Bind(&return_null); | 432 a->Bind(&return_null); |
432 a->Return(null); | 433 var_result.Bind(null); |
| 434 a->Goto(&out); |
433 } | 435 } |
434 | 436 |
435 Label construct_result(a); | 437 Label construct_result(a); |
436 a->Bind(&successful_match); | 438 a->Bind(&successful_match); |
437 { | 439 { |
438 a->GotoUnless(should_update_last_index, &construct_result); | 440 a->GotoUnless(should_update_last_index, &construct_result); |
439 | 441 |
440 // Update the new last index from {match_indices}. | 442 // Update the new last index from {match_indices}. |
441 Node* const new_lastindex = a->LoadFixedArrayElement( | 443 Node* const new_lastindex = a->LoadFixedArrayElement( |
442 match_indices, | 444 match_indices, |
443 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1)); | 445 a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1)); |
444 | 446 |
445 StoreLastIndex(a, context, has_initialmap, regexp, new_lastindex); | 447 StoreLastIndex(a, context, has_initialmap, regexp, new_lastindex); |
446 a->Goto(&construct_result); | 448 a->Goto(&construct_result); |
447 | 449 |
448 a->Bind(&construct_result); | 450 a->Bind(&construct_result); |
449 { | 451 { |
450 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, | 452 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, |
451 match_indices, string); | 453 match_indices, string); |
452 a->Return(result); | 454 var_result.Bind(result); |
| 455 a->Goto(&out); |
453 } | 456 } |
454 } | 457 } |
| 458 |
| 459 a->Bind(&out); |
| 460 return var_result.value(); |
| 461 } |
| 462 |
| 463 } // namespace |
| 464 |
| 465 // ES#sec-regexp.prototype.exec |
| 466 // RegExp.prototype.exec ( string ) |
| 467 void Builtins::Generate_RegExpPrototypeExec(CodeStubAssembler* a) { |
| 468 typedef compiler::Node Node; |
| 469 |
| 470 Node* const maybe_receiver = a->Parameter(0); |
| 471 Node* const maybe_string = a->Parameter(1); |
| 472 Node* const context = a->Parameter(4); |
| 473 |
| 474 Node* const result = |
| 475 RegExpPrototypeExecInternal(a, context, maybe_receiver, maybe_string); |
| 476 a->Return(result); |
455 } | 477 } |
456 | 478 |
457 namespace { | 479 namespace { |
458 | 480 |
459 compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate, | 481 compiler::Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate, |
460 compiler::Node* context, | 482 compiler::Node* context, |
461 compiler::Node* value, | 483 compiler::Node* value, |
462 MessageTemplate::Template msg_template, | 484 MessageTemplate::Template msg_template, |
463 char const* method_name) { | 485 char const* method_name) { |
464 typedef compiler::Node Node; | 486 typedef compiler::Node Node; |
(...skipping 1442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1907 a->Bind(&if_matched); | 1929 a->Bind(&if_matched); |
1908 { | 1930 { |
1909 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, | 1931 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, |
1910 match_indices, string); | 1932 match_indices, string); |
1911 a->Return(result); | 1933 a->Return(result); |
1912 } | 1934 } |
1913 } | 1935 } |
1914 | 1936 |
1915 } // namespace internal | 1937 } // namespace internal |
1916 } // namespace v8 | 1938 } // namespace v8 |
OLD | NEW |