| OLD | NEW |
| 1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 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-regexp-gen.h" | 5 #include "src/builtins/builtins-regexp-gen.h" |
| 6 | 6 |
| 7 #include "src/builtins/builtins-constructor-gen.h" | 7 #include "src/builtins/builtins-constructor-gen.h" |
| 8 #include "src/builtins/builtins-utils-gen.h" | 8 #include "src/builtins/builtins-utils-gen.h" |
| 9 #include "src/builtins/builtins.h" | 9 #include "src/builtins/builtins.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 2277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2288 Node* const context = Parameter(Descriptor::kContext); | 2288 Node* const context = Parameter(Descriptor::kContext); |
| 2289 | 2289 |
| 2290 CSA_ASSERT(this, IsFastRegExp(context, regexp)); | 2290 CSA_ASSERT(this, IsFastRegExp(context, regexp)); |
| 2291 CSA_ASSERT(this, IsString(string)); | 2291 CSA_ASSERT(this, IsString(string)); |
| 2292 | 2292 |
| 2293 // TODO(jgruber): Even if map checks send us to the fast path, we still need | 2293 // TODO(jgruber): Even if map checks send us to the fast path, we still need |
| 2294 // to verify the constructor property and jump to the slow path if it has | 2294 // to verify the constructor property and jump to the slow path if it has |
| 2295 // been changed. | 2295 // been changed. |
| 2296 | 2296 |
| 2297 // Convert {maybe_limit} to a uint32, capping at the maximal smi value. | 2297 // Convert {maybe_limit} to a uint32, capping at the maximal smi value. |
| 2298 Variable var_limit(this, MachineRepresentation::kTagged); | 2298 Variable var_limit(this, MachineRepresentation::kTagged, maybe_limit); |
| 2299 Label if_limitissmimax(this), limit_done(this); | 2299 Label if_limitissmimax(this), limit_done(this), runtime(this); |
| 2300 | 2300 |
| 2301 GotoIf(IsUndefined(maybe_limit), &if_limitissmimax); | 2301 GotoIf(IsUndefined(maybe_limit), &if_limitissmimax); |
| 2302 GotoIf(TaggedIsPositiveSmi(maybe_limit), &limit_done); |
| 2302 | 2303 |
| 2304 Node* const limit = ToUint32(context, maybe_limit); |
| 2303 { | 2305 { |
| 2304 Node* const limit = ToUint32(context, maybe_limit); | 2306 // ToUint32(limit) could potentially change the shape of the RegExp |
| 2307 // object. Recheck that we are still on the fast path and bail to runtime |
| 2308 // otherwise. |
| 2309 { |
| 2310 Label next(this); |
| 2311 BranchIfFastRegExp(context, regexp, LoadMap(regexp), &next, &runtime); |
| 2312 Bind(&next); |
| 2313 } |
| 2314 |
| 2305 GotoIfNot(TaggedIsSmi(limit), &if_limitissmimax); | 2315 GotoIfNot(TaggedIsSmi(limit), &if_limitissmimax); |
| 2306 | 2316 |
| 2307 var_limit.Bind(limit); | 2317 var_limit.Bind(limit); |
| 2308 Goto(&limit_done); | 2318 Goto(&limit_done); |
| 2309 } | 2319 } |
| 2310 | 2320 |
| 2311 BIND(&if_limitissmimax); | 2321 BIND(&if_limitissmimax); |
| 2312 { | 2322 { |
| 2313 // TODO(jgruber): In this case, we can probably avoid generation of limit | 2323 // TODO(jgruber): In this case, we can probably avoid generation of limit |
| 2314 // checks in Generate_RegExpPrototypeSplitBody. | 2324 // checks in Generate_RegExpPrototypeSplitBody. |
| 2315 var_limit.Bind(SmiConstant(Smi::kMaxValue)); | 2325 var_limit.Bind(SmiConstant(Smi::kMaxValue)); |
| 2316 Goto(&limit_done); | 2326 Goto(&limit_done); |
| 2317 } | 2327 } |
| 2318 | 2328 |
| 2319 BIND(&limit_done); | 2329 BIND(&limit_done); |
| 2320 { | 2330 { |
| 2321 Node* const limit = var_limit.value(); | 2331 Node* const limit = var_limit.value(); |
| 2322 RegExpPrototypeSplitBody(context, regexp, string, limit); | 2332 RegExpPrototypeSplitBody(context, regexp, string, limit); |
| 2323 } | 2333 } |
| 2334 |
| 2335 Bind(&runtime); |
| 2336 { |
| 2337 // The runtime call passes in limit to ensure the second ToUint32(limit) |
| 2338 // call is not observable. |
| 2339 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(limit))); |
| 2340 Return(CallRuntime(Runtime::kRegExpSplit, context, regexp, string, limit)); |
| 2341 } |
| 2324 } | 2342 } |
| 2325 | 2343 |
| 2326 // ES#sec-regexp.prototype-@@split | 2344 // ES#sec-regexp.prototype-@@split |
| 2327 // RegExp.prototype [ @@split ] ( string, limit ) | 2345 // RegExp.prototype [ @@split ] ( string, limit ) |
| 2328 TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { | 2346 TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { |
| 2329 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); | 2347 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); |
| 2330 Node* const maybe_string = Parameter(Descriptor::kString); | 2348 Node* const maybe_string = Parameter(Descriptor::kString); |
| 2331 Node* const maybe_limit = Parameter(Descriptor::kLimit); | 2349 Node* const maybe_limit = Parameter(Descriptor::kLimit); |
| 2332 Node* const context = Parameter(Descriptor::kContext); | 2350 Node* const context = Parameter(Descriptor::kContext); |
| 2333 | 2351 |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2685 GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); | 2703 GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); |
| 2686 Branch(IsCallableMap(LoadMap(replace_value)), &if_iscallable, | 2704 Branch(IsCallableMap(LoadMap(replace_value)), &if_iscallable, |
| 2687 &checkreplacestring); | 2705 &checkreplacestring); |
| 2688 | 2706 |
| 2689 // 3. Does ToString({replace_value}) contain '$'? | 2707 // 3. Does ToString({replace_value}) contain '$'? |
| 2690 BIND(&checkreplacestring); | 2708 BIND(&checkreplacestring); |
| 2691 { | 2709 { |
| 2692 Node* const replace_string = | 2710 Node* const replace_string = |
| 2693 CallBuiltin(Builtins::kToString, context, replace_value); | 2711 CallBuiltin(Builtins::kToString, context, replace_value); |
| 2694 | 2712 |
| 2713 // ToString(replaceValue) could potentially change the shape of the RegExp |
| 2714 // object. Recheck that we are still on the fast path and bail to runtime |
| 2715 // otherwise. |
| 2716 { |
| 2717 Label next(this); |
| 2718 BranchIfFastRegExp(context, regexp, LoadMap(regexp), &next, &runtime); |
| 2719 Bind(&next); |
| 2720 } |
| 2721 |
| 2695 Node* const dollar_string = HeapConstant( | 2722 Node* const dollar_string = HeapConstant( |
| 2696 isolate()->factory()->LookupSingleCharacterStringFromCode('$')); | 2723 isolate()->factory()->LookupSingleCharacterStringFromCode('$')); |
| 2697 Node* const dollar_ix = | 2724 Node* const dollar_ix = |
| 2698 CallBuiltin(Builtins::kStringIndexOf, context, replace_string, | 2725 CallBuiltin(Builtins::kStringIndexOf, context, replace_string, |
| 2699 dollar_string, SmiConstant(0)); | 2726 dollar_string, SmiConstant(0)); |
| 2700 GotoIfNot(SmiEqual(dollar_ix, SmiConstant(-1)), &runtime); | 2727 GotoIfNot(SmiEqual(dollar_ix, SmiConstant(-1)), &runtime); |
| 2701 | 2728 |
| 2702 Return( | 2729 Return( |
| 2703 ReplaceSimpleStringFastPath(context, regexp, string, replace_string)); | 2730 ReplaceSimpleStringFastPath(context, regexp, string, replace_string)); |
| 2704 } | 2731 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2804 BIND(&if_matched); | 2831 BIND(&if_matched); |
| 2805 { | 2832 { |
| 2806 Node* result = | 2833 Node* result = |
| 2807 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); | 2834 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); |
| 2808 Return(result); | 2835 Return(result); |
| 2809 } | 2836 } |
| 2810 } | 2837 } |
| 2811 | 2838 |
| 2812 } // namespace internal | 2839 } // namespace internal |
| 2813 } // namespace v8 | 2840 } // namespace v8 |
| OLD | NEW |