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 2285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2296 | 2296 |
2297 CSA_ASSERT(this, IsFastRegExp(context, regexp)); | 2297 CSA_ASSERT(this, IsFastRegExp(context, regexp)); |
2298 CSA_ASSERT(this, IsString(string)); | 2298 CSA_ASSERT(this, IsString(string)); |
2299 | 2299 |
2300 // TODO(jgruber): Even if map checks send us to the fast path, we still need | 2300 // TODO(jgruber): Even if map checks send us to the fast path, we still need |
2301 // to verify the constructor property and jump to the slow path if it has | 2301 // to verify the constructor property and jump to the slow path if it has |
2302 // been changed. | 2302 // been changed. |
2303 | 2303 |
2304 // Convert {maybe_limit} to a uint32, capping at the maximal smi value. | 2304 // Convert {maybe_limit} to a uint32, capping at the maximal smi value. |
2305 Variable var_limit(this, MachineRepresentation::kTagged); | 2305 Variable var_limit(this, MachineRepresentation::kTagged); |
2306 Label if_limitissmimax(this), limit_done(this); | 2306 Label if_limitissmimax(this), limit_done(this), runtime(this); |
2307 | 2307 |
2308 GotoIf(IsUndefined(maybe_limit), &if_limitissmimax); | 2308 GotoIf(IsUndefined(maybe_limit), &if_limitissmimax); |
2309 | 2309 |
2310 Node* const limit = ToUint32(context, maybe_limit); | |
Camillo Bruni
2017/04/06 14:54:15
future-nit: something like ToUint32(..., &was_fast
jgruber
2017/04/06 15:21:12
Sounds reasonable. I want to keep this CL small an
| |
2310 { | 2311 { |
2311 Node* const limit = ToUint32(context, maybe_limit); | 2312 // ToUint32(limit) could potentially change the shape of the RegExp |
2313 // object. Recheck that we are still on the fast path and bail to runtime | |
2314 // otherwise. | |
2315 { | |
2316 Label next(this); | |
2317 BranchIfFastRegExp(context, regexp, LoadMap(regexp), &next, &runtime); | |
Camillo Bruni
2017/04/06 14:54:15
site-note: You'd probably be better off with a Got
jgruber
2017/04/06 15:21:12
Acknowledged.
| |
2318 Bind(&next); | |
2319 } | |
2320 | |
2312 GotoIfNot(TaggedIsSmi(limit), &if_limitissmimax); | 2321 GotoIfNot(TaggedIsSmi(limit), &if_limitissmimax); |
2313 | 2322 |
2314 var_limit.Bind(limit); | 2323 var_limit.Bind(limit); |
2315 Goto(&limit_done); | 2324 Goto(&limit_done); |
2316 } | 2325 } |
2317 | 2326 |
2318 Bind(&if_limitissmimax); | 2327 Bind(&if_limitissmimax); |
2319 { | 2328 { |
2320 // TODO(jgruber): In this case, we can probably avoid generation of limit | 2329 // TODO(jgruber): In this case, we can probably avoid generation of limit |
2321 // checks in Generate_RegExpPrototypeSplitBody. | 2330 // checks in Generate_RegExpPrototypeSplitBody. |
2322 var_limit.Bind(SmiConstant(Smi::kMaxValue)); | 2331 var_limit.Bind(SmiConstant(Smi::kMaxValue)); |
2323 Goto(&limit_done); | 2332 Goto(&limit_done); |
2324 } | 2333 } |
2325 | 2334 |
2326 Bind(&limit_done); | 2335 Bind(&limit_done); |
2327 { | 2336 { |
2328 Node* const limit = var_limit.value(); | 2337 Node* const limit = var_limit.value(); |
2329 RegExpPrototypeSplitBody(context, regexp, string, limit); | 2338 RegExpPrototypeSplitBody(context, regexp, string, limit); |
2330 } | 2339 } |
2340 | |
2341 Bind(&runtime); | |
2342 { | |
2343 // The runtime call passes in limit to ensure the second ToUint32(limit) | |
2344 // call is not observable. | |
2345 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(limit))); | |
Camillo Bruni
2017/04/06 14:54:15
nit: CSA_ASSERT(this, IsNumber(limit));
jgruber
2017/04/06 15:21:12
Can do in a follow-up (don't want to touch c-s-a.{
| |
2346 Return(CallRuntime(Runtime::kRegExpSplit, context, regexp, string, limit)); | |
2347 } | |
2331 } | 2348 } |
2332 | 2349 |
2333 // ES#sec-regexp.prototype-@@split | 2350 // ES#sec-regexp.prototype-@@split |
2334 // RegExp.prototype [ @@split ] ( string, limit ) | 2351 // RegExp.prototype [ @@split ] ( string, limit ) |
2335 TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { | 2352 TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { |
2336 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); | 2353 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); |
2337 Node* const maybe_string = Parameter(Descriptor::kString); | 2354 Node* const maybe_string = Parameter(Descriptor::kString); |
2338 Node* const maybe_limit = Parameter(Descriptor::kLimit); | 2355 Node* const maybe_limit = Parameter(Descriptor::kLimit); |
2339 Node* const context = Parameter(Descriptor::kContext); | 2356 Node* const context = Parameter(Descriptor::kContext); |
2340 | 2357 |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2692 GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); | 2709 GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); |
2693 Branch(IsCallableMap(LoadMap(replace_value)), &if_iscallable, | 2710 Branch(IsCallableMap(LoadMap(replace_value)), &if_iscallable, |
2694 &checkreplacestring); | 2711 &checkreplacestring); |
2695 | 2712 |
2696 // 3. Does ToString({replace_value}) contain '$'? | 2713 // 3. Does ToString({replace_value}) contain '$'? |
2697 Bind(&checkreplacestring); | 2714 Bind(&checkreplacestring); |
2698 { | 2715 { |
2699 Node* const replace_string = | 2716 Node* const replace_string = |
2700 CallBuiltin(Builtins::kToString, context, replace_value); | 2717 CallBuiltin(Builtins::kToString, context, replace_value); |
2701 | 2718 |
2719 // ToString(replaceValue) could potentially change the shape of the RegExp | |
2720 // object. Recheck that we are still on the fast path and bail to runtime | |
2721 // otherwise. | |
2722 { | |
2723 Label next(this); | |
2724 BranchIfFastRegExp(context, regexp, LoadMap(regexp), &next, &runtime); | |
2725 Bind(&next); | |
2726 } | |
2727 | |
2702 Node* const dollar_string = HeapConstant( | 2728 Node* const dollar_string = HeapConstant( |
2703 isolate()->factory()->LookupSingleCharacterStringFromCode('$')); | 2729 isolate()->factory()->LookupSingleCharacterStringFromCode('$')); |
2704 Node* const dollar_ix = | 2730 Node* const dollar_ix = |
2705 CallBuiltin(Builtins::kStringIndexOf, context, replace_string, | 2731 CallBuiltin(Builtins::kStringIndexOf, context, replace_string, |
2706 dollar_string, SmiConstant(0)); | 2732 dollar_string, SmiConstant(0)); |
2707 GotoIfNot(SmiEqual(dollar_ix, SmiConstant(-1)), &runtime); | 2733 GotoIfNot(SmiEqual(dollar_ix, SmiConstant(-1)), &runtime); |
2708 | 2734 |
2709 Return( | 2735 Return( |
2710 ReplaceSimpleStringFastPath(context, regexp, string, replace_string)); | 2736 ReplaceSimpleStringFastPath(context, regexp, string, replace_string)); |
2711 } | 2737 } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2811 Bind(&if_matched); | 2837 Bind(&if_matched); |
2812 { | 2838 { |
2813 Node* result = | 2839 Node* result = |
2814 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); | 2840 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); |
2815 Return(result); | 2841 Return(result); |
2816 } | 2842 } |
2817 } | 2843 } |
2818 | 2844 |
2819 } // namespace internal | 2845 } // namespace internal |
2820 } // namespace v8 | 2846 } // namespace v8 |
OLD | NEW |