| 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 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stub-assembler.h" | 8 #include "src/code-stub-assembler.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 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 var_to_cursor.Bind(IntPtrConstant(1)); | 176 var_to_cursor.Bind(IntPtrConstant(1)); |
| 177 | 177 |
| 178 Variable* vars[] = {&var_from_cursor, &var_to_cursor}; | 178 Variable* vars[] = {&var_from_cursor, &var_to_cursor}; |
| 179 Label loop(this, 2, vars); | 179 Label loop(this, 2, vars); |
| 180 | 180 |
| 181 Goto(&loop); | 181 Goto(&loop); |
| 182 Bind(&loop); | 182 Bind(&loop); |
| 183 { | 183 { |
| 184 Node* const from_cursor = var_from_cursor.value(); | 184 Node* const from_cursor = var_from_cursor.value(); |
| 185 Node* const to_cursor = var_to_cursor.value(); | 185 Node* const to_cursor = var_to_cursor.value(); |
| 186 Node* const start = LoadFixedArrayElement(match_info, from_cursor); | 186 Node* const start = |
| 187 LoadFixedArrayElement(match_info, from_cursor, 0, INTPTR_PARAMETERS); |
| 187 | 188 |
| 188 Label next_iter(this); | 189 Label next_iter(this); |
| 189 GotoIf(SmiEqual(start, SmiConstant(Smi::FromInt(-1))), &next_iter); | 190 GotoIf(SmiEqual(start, SmiConstant(Smi::FromInt(-1))), &next_iter); |
| 190 | 191 |
| 191 Node* const from_cursor_plus1 = IntPtrAdd(from_cursor, IntPtrConstant(1)); | 192 Node* const from_cursor_plus1 = IntPtrAdd(from_cursor, IntPtrConstant(1)); |
| 192 Node* const end = LoadFixedArrayElement(match_info, from_cursor_plus1); | 193 Node* const end = LoadFixedArrayElement(match_info, from_cursor_plus1, 0, |
| 194 INTPTR_PARAMETERS); |
| 193 | 195 |
| 194 Node* const capture = SubString(context, string, start, end); | 196 Node* const capture = SubString(context, string, start, end); |
| 195 StoreFixedArrayElement(result_elements, to_cursor, capture); | 197 StoreFixedArrayElement(result_elements, to_cursor, capture, |
| 198 UPDATE_WRITE_BARRIER, 0, INTPTR_PARAMETERS); |
| 196 Goto(&next_iter); | 199 Goto(&next_iter); |
| 197 | 200 |
| 198 Bind(&next_iter); | 201 Bind(&next_iter); |
| 199 var_from_cursor.Bind(IntPtrAdd(from_cursor, IntPtrConstant(2))); | 202 var_from_cursor.Bind(IntPtrAdd(from_cursor, IntPtrConstant(2))); |
| 200 var_to_cursor.Bind(IntPtrAdd(to_cursor, IntPtrConstant(1))); | 203 var_to_cursor.Bind(IntPtrAdd(to_cursor, IntPtrConstant(1))); |
| 201 Branch(UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out); | 204 Branch(UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out); |
| 202 } | 205 } |
| 203 | 206 |
| 204 Bind(&out); | 207 Bind(&out); |
| 205 return result; | 208 return result; |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 Node* const flags_intptr = var_flags.value(); | 562 Node* const flags_intptr = var_flags.value(); |
| 560 | 563 |
| 561 Variable var_offset(this, MachineType::PointerRepresentation()); | 564 Variable var_offset(this, MachineType::PointerRepresentation()); |
| 562 var_offset.Bind( | 565 var_offset.Bind( |
| 563 IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag)); | 566 IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag)); |
| 564 | 567 |
| 565 #define CASE_FOR_FLAG(FLAG, CHAR) \ | 568 #define CASE_FOR_FLAG(FLAG, CHAR) \ |
| 566 do { \ | 569 do { \ |
| 567 Label next(this); \ | 570 Label next(this); \ |
| 568 GotoUnless(IsSetWord(flags_intptr, FLAG), &next); \ | 571 GotoUnless(IsSetWord(flags_intptr, FLAG), &next); \ |
| 569 Node* const value = IntPtrConstant(CHAR); \ | 572 Node* const value = Int32Constant(CHAR); \ |
| 570 StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \ | 573 StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \ |
| 571 var_offset.value(), value); \ | 574 var_offset.value(), value); \ |
| 572 var_offset.Bind(IntPtrAdd(var_offset.value(), int_one)); \ | 575 var_offset.Bind(IntPtrAdd(var_offset.value(), int_one)); \ |
| 573 Goto(&next); \ | 576 Goto(&next); \ |
| 574 Bind(&next); \ | 577 Bind(&next); \ |
| 575 } while (false) | 578 } while (false) |
| 576 | 579 |
| 577 CASE_FOR_FLAG(JSRegExp::kGlobal, 'g'); | 580 CASE_FOR_FLAG(JSRegExp::kGlobal, 'g'); |
| 578 CASE_FOR_FLAG(JSRegExp::kIgnoreCase, 'i'); | 581 CASE_FOR_FLAG(JSRegExp::kIgnoreCase, 'i'); |
| 579 CASE_FOR_FLAG(JSRegExp::kMultiline, 'm'); | 582 CASE_FOR_FLAG(JSRegExp::kMultiline, 'm'); |
| 580 CASE_FOR_FLAG(JSRegExp::kUnicode, 'u'); | 583 CASE_FOR_FLAG(JSRegExp::kUnicode, 'u'); |
| 581 CASE_FOR_FLAG(JSRegExp::kSticky, 'y'); | 584 CASE_FOR_FLAG(JSRegExp::kSticky, 'y'); |
| 582 #undef CASE_FOR_FLAG | 585 #undef CASE_FOR_FLAG |
| 583 | 586 |
| 584 return result; | 587 return result; |
| 585 } | 588 } |
| 586 } | 589 } |
| 587 | 590 |
| 588 // ES#sec-isregexp IsRegExp ( argument ) | 591 // ES#sec-isregexp IsRegExp ( argument ) |
| 589 Node* RegExpBuiltinsAssembler::IsRegExp(Node* const context, | 592 Node* RegExpBuiltinsAssembler::IsRegExp(Node* const context, |
| 590 Node* const maybe_receiver) { | 593 Node* const maybe_receiver) { |
| 591 Label out(this), if_isregexp(this); | 594 Label out(this), if_isregexp(this); |
| 592 | 595 |
| 593 Variable var_result(this, MachineType::PointerRepresentation()); | 596 Variable var_result(this, MachineRepresentation::kWord32); |
| 594 var_result.Bind(IntPtrConstant(0)); | 597 var_result.Bind(Int32Constant(0)); |
| 595 | 598 |
| 596 GotoIf(TaggedIsSmi(maybe_receiver), &out); | 599 GotoIf(TaggedIsSmi(maybe_receiver), &out); |
| 597 GotoUnless(IsJSReceiver(maybe_receiver), &out); | 600 GotoUnless(IsJSReceiver(maybe_receiver), &out); |
| 598 | 601 |
| 599 Node* const receiver = maybe_receiver; | 602 Node* const receiver = maybe_receiver; |
| 600 | 603 |
| 601 // Check @@match. | 604 // Check @@match. |
| 602 { | 605 { |
| 603 Callable getproperty_callable = CodeFactory::GetProperty(isolate()); | 606 Callable getproperty_callable = CodeFactory::GetProperty(isolate()); |
| 604 Node* const name = HeapConstant(isolate()->factory()->match_symbol()); | 607 Node* const name = HeapConstant(isolate()->factory()->match_symbol()); |
| 605 Node* const value = CallStub(getproperty_callable, context, receiver, name); | 608 Node* const value = CallStub(getproperty_callable, context, receiver, name); |
| 606 | 609 |
| 607 Label match_isundefined(this), match_isnotundefined(this); | 610 Label match_isundefined(this), match_isnotundefined(this); |
| 608 Branch(IsUndefined(value), &match_isundefined, &match_isnotundefined); | 611 Branch(IsUndefined(value), &match_isundefined, &match_isnotundefined); |
| 609 | 612 |
| 610 Bind(&match_isundefined); | 613 Bind(&match_isundefined); |
| 611 Branch(HasInstanceType(receiver, JS_REGEXP_TYPE), &if_isregexp, &out); | 614 Branch(HasInstanceType(receiver, JS_REGEXP_TYPE), &if_isregexp, &out); |
| 612 | 615 |
| 613 Bind(&match_isnotundefined); | 616 Bind(&match_isnotundefined); |
| 614 BranchIfToBooleanIsTrue(value, &if_isregexp, &out); | 617 BranchIfToBooleanIsTrue(value, &if_isregexp, &out); |
| 615 } | 618 } |
| 616 | 619 |
| 617 Bind(&if_isregexp); | 620 Bind(&if_isregexp); |
| 618 var_result.Bind(IntPtrConstant(1)); | 621 var_result.Bind(Int32Constant(1)); |
| 619 Goto(&out); | 622 Goto(&out); |
| 620 | 623 |
| 621 Bind(&out); | 624 Bind(&out); |
| 622 return var_result.value(); | 625 return var_result.value(); |
| 623 } | 626 } |
| 624 | 627 |
| 625 // ES#sec-regexpinitialize | 628 // ES#sec-regexpinitialize |
| 626 // Runtime Semantics: RegExpInitialize ( obj, pattern, flags ) | 629 // Runtime Semantics: RegExpInitialize ( obj, pattern, flags ) |
| 627 Node* RegExpBuiltinsAssembler::RegExpInitialize(Node* const context, | 630 Node* RegExpBuiltinsAssembler::RegExpInitialize(Node* const context, |
| 628 Node* const regexp, | 631 Node* const regexp, |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 955 Node* const receiver = Parameter(0); | 958 Node* const receiver = Parameter(0); |
| 956 Return(receiver); | 959 Return(receiver); |
| 957 } | 960 } |
| 958 | 961 |
| 959 // Fast-path implementation for flag checks on an unmodified JSRegExp instance. | 962 // Fast-path implementation for flag checks on an unmodified JSRegExp instance. |
| 960 Node* RegExpBuiltinsAssembler::FastFlagGetter(Node* const regexp, | 963 Node* RegExpBuiltinsAssembler::FastFlagGetter(Node* const regexp, |
| 961 JSRegExp::Flag flag) { | 964 JSRegExp::Flag flag) { |
| 962 Node* const smi_zero = SmiConstant(Smi::kZero); | 965 Node* const smi_zero = SmiConstant(Smi::kZero); |
| 963 Node* const flags = LoadObjectField(regexp, JSRegExp::kFlagsOffset); | 966 Node* const flags = LoadObjectField(regexp, JSRegExp::kFlagsOffset); |
| 964 Node* const mask = SmiConstant(Smi::FromInt(flag)); | 967 Node* const mask = SmiConstant(Smi::FromInt(flag)); |
| 965 Node* const is_flag_set = WordNotEqual(WordAnd(flags, mask), smi_zero); | 968 Node* const is_flag_set = WordNotEqual(SmiAnd(flags, mask), smi_zero); |
| 966 | 969 |
| 967 return is_flag_set; | 970 return is_flag_set; |
| 968 } | 971 } |
| 969 | 972 |
| 970 // Load through the GetProperty stub. | 973 // Load through the GetProperty stub. |
| 971 Node* RegExpBuiltinsAssembler::SlowFlagGetter(Node* const context, | 974 Node* RegExpBuiltinsAssembler::SlowFlagGetter(Node* const context, |
| 972 Node* const regexp, | 975 Node* const regexp, |
| 973 JSRegExp::Flag flag) { | 976 JSRegExp::Flag flag) { |
| 974 Factory* factory = isolate()->factory(); | 977 Factory* factory = isolate()->factory(); |
| 975 | 978 |
| 976 Label out(this); | 979 Label out(this); |
| 977 Variable var_result(this, MachineType::PointerRepresentation()); | 980 Variable var_result(this, MachineRepresentation::kWord32); |
| 978 | 981 |
| 979 Node* name; | 982 Node* name; |
| 980 | 983 |
| 981 switch (flag) { | 984 switch (flag) { |
| 982 case JSRegExp::kGlobal: | 985 case JSRegExp::kGlobal: |
| 983 name = HeapConstant(factory->global_string()); | 986 name = HeapConstant(factory->global_string()); |
| 984 break; | 987 break; |
| 985 case JSRegExp::kIgnoreCase: | 988 case JSRegExp::kIgnoreCase: |
| 986 name = HeapConstant(factory->ignoreCase_string()); | 989 name = HeapConstant(factory->ignoreCase_string()); |
| 987 break; | 990 break; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 999 } | 1002 } |
| 1000 | 1003 |
| 1001 Callable getproperty_callable = CodeFactory::GetProperty(isolate()); | 1004 Callable getproperty_callable = CodeFactory::GetProperty(isolate()); |
| 1002 Node* const value = CallStub(getproperty_callable, context, regexp, name); | 1005 Node* const value = CallStub(getproperty_callable, context, regexp, name); |
| 1003 | 1006 |
| 1004 Label if_true(this), if_false(this); | 1007 Label if_true(this), if_false(this); |
| 1005 BranchIfToBooleanIsTrue(value, &if_true, &if_false); | 1008 BranchIfToBooleanIsTrue(value, &if_true, &if_false); |
| 1006 | 1009 |
| 1007 Bind(&if_true); | 1010 Bind(&if_true); |
| 1008 { | 1011 { |
| 1009 var_result.Bind(IntPtrConstant(1)); | 1012 var_result.Bind(Int32Constant(1)); |
| 1010 Goto(&out); | 1013 Goto(&out); |
| 1011 } | 1014 } |
| 1012 | 1015 |
| 1013 Bind(&if_false); | 1016 Bind(&if_false); |
| 1014 { | 1017 { |
| 1015 var_result.Bind(IntPtrConstant(0)); | 1018 var_result.Bind(Int32Constant(0)); |
| 1016 Goto(&out); | 1019 Goto(&out); |
| 1017 } | 1020 } |
| 1018 | 1021 |
| 1019 Bind(&out); | 1022 Bind(&out); |
| 1020 return var_result.value(); | 1023 return var_result.value(); |
| 1021 } | 1024 } |
| 1022 | 1025 |
| 1023 Node* RegExpBuiltinsAssembler::FlagGetter(Node* const context, | 1026 Node* RegExpBuiltinsAssembler::FlagGetter(Node* const context, |
| 1024 Node* const regexp, | 1027 Node* const regexp, |
| 1025 JSRegExp::Flag flag, | 1028 JSRegExp::Flag flag, |
| (...skipping 1216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2242 Bind(&if_isstring); | 2245 Bind(&if_isstring); |
| 2243 { | 2246 { |
| 2244 CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(elem))); | 2247 CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(elem))); |
| 2245 | 2248 |
| 2246 Callable call_callable = CodeFactory::Call(isolate); | 2249 Callable call_callable = CodeFactory::Call(isolate); |
| 2247 Node* const replacement_obj = | 2250 Node* const replacement_obj = |
| 2248 CallJS(call_callable, context, replace_callable, undefined, elem, | 2251 CallJS(call_callable, context, replace_callable, undefined, elem, |
| 2249 var_match_start.value(), string); | 2252 var_match_start.value(), string); |
| 2250 | 2253 |
| 2251 Node* const replacement_str = ToString(context, replacement_obj); | 2254 Node* const replacement_str = ToString(context, replacement_obj); |
| 2252 StoreFixedArrayElement(res_elems, i, replacement_str); | 2255 StoreFixedArrayElement(res_elems, i, replacement_str, |
| 2256 UPDATE_WRITE_BARRIER, 0, mode); |
| 2253 | 2257 |
| 2254 Node* const elem_length = LoadStringLength(elem); | 2258 Node* const elem_length = LoadStringLength(elem); |
| 2255 Node* const new_match_start = | 2259 Node* const new_match_start = |
| 2256 SmiAdd(var_match_start.value(), elem_length); | 2260 SmiAdd(var_match_start.value(), elem_length); |
| 2257 var_match_start.Bind(new_match_start); | 2261 var_match_start.Bind(new_match_start); |
| 2258 | 2262 |
| 2259 Goto(&loop_epilogue); | 2263 Goto(&loop_epilogue); |
| 2260 } | 2264 } |
| 2261 | 2265 |
| 2262 Bind(&loop_epilogue); | 2266 Bind(&loop_epilogue); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2432 } | 2436 } |
| 2433 | 2437 |
| 2434 // ES#sec-regexp.prototype-@@replace | 2438 // ES#sec-regexp.prototype-@@replace |
| 2435 // RegExp.prototype [ @@replace ] ( string, replaceValue ) | 2439 // RegExp.prototype [ @@replace ] ( string, replaceValue ) |
| 2436 TF_BUILTIN(RegExpPrototypeReplace, RegExpBuiltinsAssembler) { | 2440 TF_BUILTIN(RegExpPrototypeReplace, RegExpBuiltinsAssembler) { |
| 2437 Node* const maybe_receiver = Parameter(0); | 2441 Node* const maybe_receiver = Parameter(0); |
| 2438 Node* const maybe_string = Parameter(1); | 2442 Node* const maybe_string = Parameter(1); |
| 2439 Node* const replace_value = Parameter(2); | 2443 Node* const replace_value = Parameter(2); |
| 2440 Node* const context = Parameter(5); | 2444 Node* const context = Parameter(5); |
| 2441 | 2445 |
| 2442 Node* const int_zero = IntPtrConstant(0); | |
| 2443 | |
| 2444 // Ensure {maybe_receiver} is a JSReceiver. | 2446 // Ensure {maybe_receiver} is a JSReceiver. |
| 2445 Node* const map = ThrowIfNotJSReceiver( | 2447 Node* const map = ThrowIfNotJSReceiver( |
| 2446 context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, | 2448 context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, |
| 2447 "RegExp.prototype.@@replace"); | 2449 "RegExp.prototype.@@replace"); |
| 2448 Node* const receiver = maybe_receiver; | 2450 Node* const receiver = maybe_receiver; |
| 2449 | 2451 |
| 2450 // Convert {maybe_string} to a String. | 2452 // Convert {maybe_string} to a String. |
| 2451 Callable tostring_callable = CodeFactory::ToString(isolate()); | 2453 Callable tostring_callable = CodeFactory::ToString(isolate()); |
| 2452 Node* const string = CallStub(tostring_callable, context, maybe_string); | 2454 Node* const string = CallStub(tostring_callable, context, maybe_string); |
| 2453 | 2455 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2465 | 2467 |
| 2466 Node* const replace_value_map = LoadMap(replace_value); | 2468 Node* const replace_value_map = LoadMap(replace_value); |
| 2467 Branch(IsCallableMap(replace_value_map), &if_iscallable, &checkreplacestring); | 2469 Branch(IsCallableMap(replace_value_map), &if_iscallable, &checkreplacestring); |
| 2468 | 2470 |
| 2469 // 3. Does ToString({replace_value}) contain '$'? | 2471 // 3. Does ToString({replace_value}) contain '$'? |
| 2470 Bind(&checkreplacestring); | 2472 Bind(&checkreplacestring); |
| 2471 { | 2473 { |
| 2472 Node* const replace_string = | 2474 Node* const replace_string = |
| 2473 CallStub(tostring_callable, context, replace_value); | 2475 CallStub(tostring_callable, context, replace_value); |
| 2474 | 2476 |
| 2475 Node* const dollar_char = IntPtrConstant('$'); | 2477 Node* const dollar_char = Int32Constant('$'); |
| 2476 Node* const smi_minusone = SmiConstant(Smi::FromInt(-1)); | 2478 Node* const smi_minusone = SmiConstant(Smi::FromInt(-1)); |
| 2477 GotoUnless(SmiEqual(StringIndexOfChar(context, replace_string, dollar_char, | 2479 GotoUnless(SmiEqual(StringIndexOfChar(context, replace_string, dollar_char, |
| 2478 int_zero), | 2480 SmiConstant(0)), |
| 2479 smi_minusone), | 2481 smi_minusone), |
| 2480 &runtime); | 2482 &runtime); |
| 2481 | 2483 |
| 2482 Return( | 2484 Return( |
| 2483 ReplaceSimpleStringFastPath(context, regexp, string, replace_string)); | 2485 ReplaceSimpleStringFastPath(context, regexp, string, replace_string)); |
| 2484 } | 2486 } |
| 2485 | 2487 |
| 2486 // {regexp} is unmodified and {replace_value} is callable. | 2488 // {regexp} is unmodified and {replace_value} is callable. |
| 2487 Bind(&if_iscallable); | 2489 Bind(&if_iscallable); |
| 2488 { | 2490 { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2544 Bind(&if_matched); | 2546 Bind(&if_matched); |
| 2545 { | 2547 { |
| 2546 Node* result = | 2548 Node* result = |
| 2547 ConstructNewResultFromMatchInfo(context, match_indices, string); | 2549 ConstructNewResultFromMatchInfo(context, match_indices, string); |
| 2548 Return(result); | 2550 Return(result); |
| 2549 } | 2551 } |
| 2550 } | 2552 } |
| 2551 | 2553 |
| 2552 } // namespace internal | 2554 } // namespace internal |
| 2553 } // namespace v8 | 2555 } // namespace v8 |
| OLD | NEW |