Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/effect-control-linearizer.h" | 5 #include "src/compiler/effect-control-linearizer.h" |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
| 9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
| 10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
| (...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 712 break; | 712 break; |
| 713 case IrOpcode::kObjectIsUndetectable: | 713 case IrOpcode::kObjectIsUndetectable: |
| 714 state = LowerObjectIsUndetectable(node, *effect, *control); | 714 state = LowerObjectIsUndetectable(node, *effect, *control); |
| 715 break; | 715 break; |
| 716 case IrOpcode::kArrayBufferWasNeutered: | 716 case IrOpcode::kArrayBufferWasNeutered: |
| 717 state = LowerArrayBufferWasNeutered(node, *effect, *control); | 717 state = LowerArrayBufferWasNeutered(node, *effect, *control); |
| 718 break; | 718 break; |
| 719 case IrOpcode::kStringFromCharCode: | 719 case IrOpcode::kStringFromCharCode: |
| 720 state = LowerStringFromCharCode(node, *effect, *control); | 720 state = LowerStringFromCharCode(node, *effect, *control); |
| 721 break; | 721 break; |
| 722 case IrOpcode::kStringFromCodePoint: | |
| 723 state = LowerStringFromCodePoint(node, *effect, *control); | |
| 724 break; | |
| 722 case IrOpcode::kStringCharCodeAt: | 725 case IrOpcode::kStringCharCodeAt: |
| 723 state = LowerStringCharCodeAt(node, *effect, *control); | 726 state = LowerStringCharCodeAt(node, *effect, *control); |
| 724 break; | 727 break; |
| 725 case IrOpcode::kStringEqual: | 728 case IrOpcode::kStringEqual: |
| 726 state = LowerStringEqual(node, *effect, *control); | 729 state = LowerStringEqual(node, *effect, *control); |
| 727 break; | 730 break; |
| 728 case IrOpcode::kStringLessThan: | 731 case IrOpcode::kStringLessThan: |
| 729 state = LowerStringLessThan(node, *effect, *control); | 732 state = LowerStringLessThan(node, *effect, *control); |
| 730 break; | 733 break; |
| 731 case IrOpcode::kStringLessThanOrEqual: | 734 case IrOpcode::kStringLessThanOrEqual: |
| (...skipping 1489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2221 graph()->NewNode(machine()->Word32And(), value_bit_field, | 2224 graph()->NewNode(machine()->Word32And(), value_bit_field, |
| 2222 jsgraph()->Int32Constant( | 2225 jsgraph()->Int32Constant( |
| 2223 JSArrayBuffer::WasNeutered::kMask)), | 2226 JSArrayBuffer::WasNeutered::kMask)), |
| 2224 jsgraph()->Int32Constant(0)), | 2227 jsgraph()->Int32Constant(0)), |
| 2225 jsgraph()->Int32Constant(0)); | 2228 jsgraph()->Int32Constant(0)); |
| 2226 | 2229 |
| 2227 return ValueEffectControl(value, effect, control); | 2230 return ValueEffectControl(value, effect, control); |
| 2228 } | 2231 } |
| 2229 | 2232 |
| 2230 EffectControlLinearizer::ValueEffectControl | 2233 EffectControlLinearizer::ValueEffectControl |
| 2231 EffectControlLinearizer::LowerStringCharCodeAt(Node* node, Node* effect, | 2234 EffectControlLinearizer::LowerStringCharCodeAt(Node* node, Node* effect, |
|
Benedikt Meurer
2016/09/29 13:04:27
Can you hold off with changing the StringCharCodeA
Benedikt Meurer
2016/09/29 16:40:01
I wonder how much the pre-flattening actually buys
caitp
2016/09/29 20:08:02
Comparing these, it doesn't look like there's a si
| |
| 2232 Node* control) { | 2235 Node* control) { |
| 2236 StringOperationHint hint = StringOperationHintOf(node->op()); | |
| 2233 Node* subject = node->InputAt(0); | 2237 Node* subject = node->InputAt(0); |
| 2234 Node* index = node->InputAt(1); | 2238 Node* index = node->InputAt(1); |
| 2235 | 2239 Node* value = nullptr; |
| 2236 // We may need to loop several times for ConsString/SlicedString {subject}s. | 2240 |
| 2237 Node* loop = | 2241 switch (hint) { |
| 2238 graph()->NewNode(common()->Loop(4), control, control, control, control); | 2242 case StringOperationHint::kAny: { |
| 2239 Node* lsubject = | 2243 // We may need to loop several times for ConsString/SlicedString |
| 2240 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 4), | 2244 // {subject}s. |
| 2241 subject, subject, subject, subject, loop); | 2245 Node* loop = graph()->NewNode(common()->Loop(4), control, control, |
| 2242 Node* lindex = | 2246 control, control); |
| 2243 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 4), index, | 2247 Node* lsubject = |
| 2244 index, index, index, loop); | 2248 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 4), |
| 2245 Node* leffect = graph()->NewNode(common()->EffectPhi(4), effect, effect, | 2249 subject, subject, subject, subject, loop); |
| 2246 effect, effect, loop); | 2250 Node* lindex = |
| 2247 | 2251 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 4), |
| 2248 control = loop; | 2252 index, index, index, index, loop); |
| 2249 effect = leffect; | 2253 Node* leffect = graph()->NewNode(common()->EffectPhi(4), effect, effect, |
| 2250 | 2254 effect, effect, loop); |
| 2251 // Determine the instance type of {lsubject}. | 2255 |
| 2252 Node* lsubject_map = effect = | 2256 control = loop; |
| 2253 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 2257 effect = leffect; |
| 2254 lsubject, effect, control); | 2258 |
| 2255 Node* lsubject_instance_type = effect = graph()->NewNode( | 2259 // Determine the instance type of {lsubject}. |
| 2256 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), | 2260 Node* lsubject_map = effect = |
| 2257 lsubject_map, effect, control); | 2261 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
| 2258 | 2262 lsubject, effect, control); |
| 2259 // Check if {lsubject} is a SeqString. | 2263 Node* lsubject_instance_type = effect = graph()->NewNode( |
| 2260 Node* check0 = graph()->NewNode( | 2264 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), |
| 2261 machine()->Word32Equal(), | 2265 lsubject_map, effect, control); |
| 2262 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | 2266 |
| 2263 jsgraph()->Int32Constant(kStringRepresentationMask)), | 2267 // Check if {lsubject} is a SeqString. |
| 2264 jsgraph()->Int32Constant(kSeqStringTag)); | 2268 Node* check0 = graph()->NewNode( |
| 2265 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); | |
| 2266 | |
| 2267 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | |
| 2268 Node* etrue0 = effect; | |
| 2269 Node* vtrue0; | |
| 2270 { | |
| 2271 // Check if the {lsubject} is a TwoByteSeqString or a OneByteSeqString. | |
| 2272 Node* check1 = graph()->NewNode( | |
| 2273 machine()->Word32Equal(), | |
| 2274 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | |
| 2275 jsgraph()->Int32Constant(kStringEncodingMask)), | |
| 2276 jsgraph()->Int32Constant(kTwoByteStringTag)); | |
| 2277 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); | |
| 2278 | |
| 2279 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 2280 Node* etrue1 = etrue0; | |
| 2281 Node* vtrue1 = etrue1 = | |
| 2282 graph()->NewNode(simplified()->LoadElement( | |
| 2283 AccessBuilder::ForSeqTwoByteStringCharacter()), | |
| 2284 lsubject, lindex, etrue1, if_true1); | |
| 2285 | |
| 2286 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 2287 Node* efalse1 = etrue0; | |
| 2288 Node* vfalse1 = efalse1 = | |
| 2289 graph()->NewNode(simplified()->LoadElement( | |
| 2290 AccessBuilder::ForSeqOneByteStringCharacter()), | |
| 2291 lsubject, lindex, efalse1, if_false1); | |
| 2292 | |
| 2293 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 2294 etrue0 = | |
| 2295 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); | |
| 2296 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 2297 vtrue1, vfalse1, if_true0); | |
| 2298 } | |
| 2299 | |
| 2300 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | |
| 2301 Node* efalse0 = effect; | |
| 2302 Node* vfalse0; | |
| 2303 { | |
| 2304 // Check if the {lsubject} is a ConsString. | |
| 2305 Node* check1 = graph()->NewNode( | |
| 2306 machine()->Word32Equal(), | |
| 2307 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | |
| 2308 jsgraph()->Int32Constant(kStringRepresentationMask)), | |
| 2309 jsgraph()->Int32Constant(kConsStringTag)); | |
| 2310 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); | |
| 2311 | |
| 2312 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 2313 Node* etrue1 = efalse0; | |
| 2314 { | |
| 2315 // Load the right hand side of the {lsubject} ConsString. | |
| 2316 Node* lsubject_second = etrue1 = graph()->NewNode( | |
| 2317 simplified()->LoadField(AccessBuilder::ForConsStringSecond()), | |
| 2318 lsubject, etrue1, if_true1); | |
| 2319 | |
| 2320 // Check whether the right hand side is the empty string (i.e. if | |
| 2321 // this is really a flat string in a cons string). If that is not | |
| 2322 // the case we flatten the string first. | |
| 2323 Node* check2 = graph()->NewNode(machine()->WordEqual(), lsubject_second, | |
| 2324 jsgraph()->EmptyStringConstant()); | |
| 2325 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue), | |
| 2326 check2, if_true1); | |
| 2327 | |
| 2328 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | |
| 2329 Node* etrue2 = etrue1; | |
| 2330 Node* vtrue2 = etrue2 = graph()->NewNode( | |
| 2331 simplified()->LoadField(AccessBuilder::ForConsStringFirst()), | |
| 2332 lsubject, etrue2, if_true2); | |
| 2333 | |
| 2334 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
| 2335 Node* efalse2 = etrue1; | |
| 2336 Node* vfalse2; | |
| 2337 { | |
| 2338 // Flatten the {lsubject} ConsString first. | |
| 2339 Operator::Properties properties = | |
| 2340 Operator::kNoDeopt | Operator::kNoThrow; | |
| 2341 Runtime::FunctionId id = Runtime::kFlattenString; | |
| 2342 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( | |
| 2343 graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); | |
| 2344 vfalse2 = efalse2 = graph()->NewNode( | |
| 2345 common()->Call(desc), jsgraph()->CEntryStubConstant(1), lsubject, | |
| 2346 jsgraph()->ExternalConstant(ExternalReference(id, isolate())), | |
| 2347 jsgraph()->Int32Constant(1), jsgraph()->NoContextConstant(), | |
| 2348 efalse2, if_false2); | |
| 2349 } | |
| 2350 | |
| 2351 // Retry the {loop} with the new subject. | |
| 2352 loop->ReplaceInput(1, if_true2); | |
| 2353 lindex->ReplaceInput(1, lindex); | |
| 2354 leffect->ReplaceInput(1, etrue2); | |
| 2355 lsubject->ReplaceInput(1, vtrue2); | |
| 2356 loop->ReplaceInput(2, if_false2); | |
| 2357 lindex->ReplaceInput(2, lindex); | |
| 2358 leffect->ReplaceInput(2, efalse2); | |
| 2359 lsubject->ReplaceInput(2, vfalse2); | |
| 2360 } | |
| 2361 | |
| 2362 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 2363 Node* efalse1 = efalse0; | |
| 2364 Node* vfalse1; | |
| 2365 { | |
| 2366 // Check if the {lsubject} is an ExternalString. | |
| 2367 Node* check2 = graph()->NewNode( | |
| 2368 machine()->Word32Equal(), | 2269 machine()->Word32Equal(), |
| 2369 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | 2270 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, |
| 2370 jsgraph()->Int32Constant(kStringRepresentationMask)), | 2271 jsgraph()->Int32Constant(kStringRepresentationMask)), |
| 2371 jsgraph()->Int32Constant(kExternalStringTag)); | 2272 jsgraph()->Int32Constant(kSeqStringTag)); |
| 2372 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 2273 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); |
| 2373 check2, if_false1); | 2274 |
| 2374 | 2275 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 2375 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | 2276 Node* etrue0 = effect; |
| 2376 Node* etrue2 = efalse1; | 2277 Node* vtrue0; |
| 2377 Node* vtrue2; | 2278 { |
| 2279 // Check if the {lsubject} is a TwoByteSeqString or a OneByteSeqString. | |
| 2280 Node* check1 = graph()->NewNode( | |
| 2281 machine()->Word32Equal(), | |
| 2282 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | |
| 2283 jsgraph()->Int32Constant(kStringEncodingMask)), | |
| 2284 jsgraph()->Int32Constant(kTwoByteStringTag)); | |
| 2285 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); | |
| 2286 | |
| 2287 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 2288 Node* etrue1 = etrue0; | |
| 2289 Node* vtrue1 = etrue1 = | |
| 2290 graph()->NewNode(simplified()->LoadElement( | |
| 2291 AccessBuilder::ForSeqTwoByteStringCharacter()), | |
| 2292 lsubject, lindex, etrue1, if_true1); | |
| 2293 | |
| 2294 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 2295 Node* efalse1 = etrue0; | |
| 2296 Node* vfalse1 = efalse1 = | |
| 2297 graph()->NewNode(simplified()->LoadElement( | |
| 2298 AccessBuilder::ForSeqOneByteStringCharacter()), | |
| 2299 lsubject, lindex, efalse1, if_false1); | |
| 2300 | |
| 2301 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 2302 etrue0 = | |
| 2303 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); | |
| 2304 vtrue0 = | |
| 2305 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 2306 vtrue1, vfalse1, if_true0); | |
| 2307 } | |
| 2308 | |
| 2309 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | |
| 2310 Node* efalse0 = effect; | |
| 2311 Node* vfalse0; | |
| 2312 { | |
| 2313 // Check if the {lsubject} is a ConsString. | |
| 2314 Node* check1 = graph()->NewNode( | |
| 2315 machine()->Word32Equal(), | |
| 2316 graph()->NewNode( | |
| 2317 machine()->Word32And(), lsubject_instance_type, | |
| 2318 jsgraph()->Int32Constant(kStringRepresentationMask)), | |
| 2319 jsgraph()->Int32Constant(kConsStringTag)); | |
| 2320 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); | |
| 2321 | |
| 2322 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 2323 Node* etrue1 = efalse0; | |
| 2324 { | |
| 2325 // Load the right hand side of the {lsubject} ConsString. | |
| 2326 Node* lsubject_second = etrue1 = graph()->NewNode( | |
| 2327 simplified()->LoadField(AccessBuilder::ForConsStringSecond()), | |
| 2328 lsubject, etrue1, if_true1); | |
| 2329 | |
| 2330 // Check whether the right hand side is the empty string (i.e. if | |
| 2331 // this is really a flat string in a cons string). If that is not | |
| 2332 // the case we flatten the string first. | |
| 2333 Node* check2 = | |
| 2334 graph()->NewNode(machine()->WordEqual(), lsubject_second, | |
| 2335 jsgraph()->EmptyStringConstant()); | |
| 2336 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue), | |
| 2337 check2, if_true1); | |
| 2338 | |
| 2339 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | |
| 2340 Node* etrue2 = etrue1; | |
| 2341 Node* vtrue2 = etrue2 = graph()->NewNode( | |
| 2342 simplified()->LoadField(AccessBuilder::ForConsStringFirst()), | |
| 2343 lsubject, etrue2, if_true2); | |
| 2344 | |
| 2345 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
| 2346 Node* efalse2 = etrue1; | |
| 2347 Node* vfalse2; | |
| 2348 { | |
| 2349 // Flatten the {lsubject} ConsString first. | |
| 2350 Operator::Properties properties = | |
| 2351 Operator::kNoDeopt | Operator::kNoThrow; | |
| 2352 Runtime::FunctionId id = Runtime::kFlattenString; | |
| 2353 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( | |
| 2354 graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); | |
| 2355 vfalse2 = efalse2 = graph()->NewNode( | |
| 2356 common()->Call(desc), jsgraph()->CEntryStubConstant(1), | |
| 2357 lsubject, | |
| 2358 jsgraph()->ExternalConstant(ExternalReference(id, isolate())), | |
| 2359 jsgraph()->Int32Constant(1), jsgraph()->NoContextConstant(), | |
| 2360 efalse2, if_false2); | |
| 2361 } | |
| 2362 | |
| 2363 // Retry the {loop} with the new subject. | |
| 2364 loop->ReplaceInput(1, if_true2); | |
| 2365 lindex->ReplaceInput(1, lindex); | |
| 2366 leffect->ReplaceInput(1, etrue2); | |
| 2367 lsubject->ReplaceInput(1, vtrue2); | |
| 2368 loop->ReplaceInput(2, if_false2); | |
| 2369 lindex->ReplaceInput(2, lindex); | |
| 2370 leffect->ReplaceInput(2, efalse2); | |
| 2371 lsubject->ReplaceInput(2, vfalse2); | |
| 2372 } | |
| 2373 | |
| 2374 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 2375 Node* efalse1 = efalse0; | |
| 2376 Node* vfalse1; | |
| 2377 { | |
| 2378 // Check if the {lsubject} is an ExternalString. | |
| 2379 Node* check2 = graph()->NewNode( | |
| 2380 machine()->Word32Equal(), | |
| 2381 graph()->NewNode( | |
| 2382 machine()->Word32And(), lsubject_instance_type, | |
| 2383 jsgraph()->Int32Constant(kStringRepresentationMask)), | |
| 2384 jsgraph()->Int32Constant(kExternalStringTag)); | |
| 2385 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue), | |
| 2386 check2, if_false1); | |
| 2387 | |
| 2388 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | |
| 2389 Node* etrue2 = efalse1; | |
| 2390 Node* vtrue2; | |
| 2391 { | |
| 2392 // Check if the {lsubject} is a short external string. | |
| 2393 Node* check3 = graph()->NewNode( | |
| 2394 machine()->Word32Equal(), | |
| 2395 graph()->NewNode( | |
| 2396 machine()->Word32And(), lsubject_instance_type, | |
| 2397 jsgraph()->Int32Constant(kShortExternalStringMask)), | |
| 2398 jsgraph()->Int32Constant(0)); | |
| 2399 Node* branch3 = graph()->NewNode( | |
| 2400 common()->Branch(BranchHint::kTrue), check3, if_true2); | |
| 2401 | |
| 2402 Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3); | |
| 2403 Node* etrue3 = etrue2; | |
| 2404 Node* vtrue3; | |
| 2405 { | |
| 2406 // Load the actual resource data from the {lsubject}. | |
| 2407 Node* lsubject_resource_data = etrue3 = graph()->NewNode( | |
| 2408 simplified()->LoadField( | |
| 2409 AccessBuilder::ForExternalStringResourceData()), | |
| 2410 lsubject, etrue3, if_true3); | |
| 2411 | |
| 2412 // Check if the {lsubject} is a TwoByteExternalString or a | |
| 2413 // OneByteExternalString. | |
| 2414 Node* check4 = graph()->NewNode( | |
| 2415 machine()->Word32Equal(), | |
| 2416 graph()->NewNode( | |
| 2417 machine()->Word32And(), lsubject_instance_type, | |
| 2418 jsgraph()->Int32Constant(kStringEncodingMask)), | |
| 2419 jsgraph()->Int32Constant(kTwoByteStringTag)); | |
| 2420 Node* branch4 = | |
| 2421 graph()->NewNode(common()->Branch(), check4, if_true3); | |
| 2422 | |
| 2423 Node* if_true4 = graph()->NewNode(common()->IfTrue(), branch4); | |
| 2424 Node* etrue4 = etrue3; | |
| 2425 Node* vtrue4 = etrue4 = graph()->NewNode( | |
| 2426 simplified()->LoadElement( | |
| 2427 AccessBuilder::ForExternalTwoByteStringCharacter()), | |
| 2428 lsubject_resource_data, lindex, etrue4, if_true4); | |
| 2429 | |
| 2430 Node* if_false4 = graph()->NewNode(common()->IfFalse(), branch4); | |
| 2431 Node* efalse4 = etrue3; | |
| 2432 Node* vfalse4 = efalse4 = graph()->NewNode( | |
| 2433 simplified()->LoadElement( | |
| 2434 AccessBuilder::ForExternalOneByteStringCharacter()), | |
| 2435 lsubject_resource_data, lindex, efalse4, if_false4); | |
| 2436 | |
| 2437 if_true3 = | |
| 2438 graph()->NewNode(common()->Merge(2), if_true4, if_false4); | |
| 2439 etrue3 = graph()->NewNode(common()->EffectPhi(2), etrue4, efalse4, | |
| 2440 if_true3); | |
| 2441 vtrue3 = graph()->NewNode( | |
| 2442 common()->Phi(MachineRepresentation::kWord32, 2), vtrue4, | |
| 2443 vfalse4, if_true3); | |
| 2444 } | |
| 2445 | |
| 2446 Node* if_false3 = graph()->NewNode(common()->IfFalse(), branch3); | |
| 2447 Node* efalse3 = etrue2; | |
| 2448 Node* vfalse3; | |
| 2449 { | |
| 2450 // The {lsubject} might be compressed, call the runtime. | |
| 2451 Operator::Properties properties = | |
| 2452 Operator::kNoDeopt | Operator::kNoThrow; | |
| 2453 Runtime::FunctionId id = Runtime::kExternalStringGetChar; | |
| 2454 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( | |
| 2455 graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); | |
| 2456 vfalse3 = efalse3 = graph()->NewNode( | |
| 2457 common()->Call(desc), jsgraph()->CEntryStubConstant(1), | |
| 2458 lsubject, ChangeInt32ToSmi(lindex), | |
| 2459 jsgraph()->ExternalConstant(ExternalReference(id, isolate())), | |
| 2460 jsgraph()->Int32Constant(2), jsgraph()->NoContextConstant(), | |
| 2461 efalse3, if_false3); | |
| 2462 vfalse3 = ChangeSmiToInt32(vfalse3); | |
| 2463 } | |
| 2464 | |
| 2465 if_true2 = | |
| 2466 graph()->NewNode(common()->Merge(2), if_true3, if_false3); | |
| 2467 etrue2 = graph()->NewNode(common()->EffectPhi(2), etrue3, efalse3, | |
| 2468 if_true2); | |
| 2469 vtrue2 = graph()->NewNode( | |
| 2470 common()->Phi(MachineRepresentation::kWord32, 2), vtrue3, | |
| 2471 vfalse3, if_true2); | |
| 2472 } | |
| 2473 | |
| 2474 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
| 2475 Node* efalse2 = efalse1; | |
| 2476 { | |
| 2477 // The {lsubject} is a SlicedString, continue with its parent. | |
| 2478 Node* lsubject_parent = efalse2 = graph()->NewNode( | |
| 2479 simplified()->LoadField(AccessBuilder::ForSlicedStringParent()), | |
| 2480 lsubject, efalse2, if_false2); | |
| 2481 Node* lsubject_offset = efalse2 = graph()->NewNode( | |
| 2482 simplified()->LoadField(AccessBuilder::ForSlicedStringOffset()), | |
| 2483 lsubject, efalse2, if_false2); | |
| 2484 Node* lsubject_index = | |
| 2485 graph()->NewNode(machine()->Int32Add(), lindex, | |
| 2486 ChangeSmiToInt32(lsubject_offset)); | |
| 2487 | |
| 2488 // Retry the {loop} with the parent subject. | |
| 2489 loop->ReplaceInput(3, if_false2); | |
| 2490 leffect->ReplaceInput(3, efalse2); | |
| 2491 lindex->ReplaceInput(3, lsubject_index); | |
| 2492 lsubject->ReplaceInput(3, lsubject_parent); | |
| 2493 } | |
| 2494 | |
| 2495 if_false1 = if_true2; | |
| 2496 efalse1 = etrue2; | |
| 2497 vfalse1 = vtrue2; | |
| 2498 } | |
| 2499 | |
| 2500 if_false0 = if_false1; | |
| 2501 efalse0 = efalse1; | |
| 2502 vfalse0 = vfalse1; | |
| 2503 } | |
| 2504 | |
| 2505 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
| 2506 effect = | |
| 2507 graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | |
| 2508 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 2509 vtrue0, vfalse0, control); | |
| 2510 } break; | |
| 2511 case StringOperationHint::kSeqStringOrExternalString: { | |
| 2512 // We may need to loop several times for ConsString/SlicedString | |
| 2513 // {subject}s. | |
| 2514 Node* loop = graph()->NewNode(common()->Loop(4), control, control, | |
| 2515 control, control); | |
| 2516 Node* lsubject = | |
| 2517 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 4), | |
| 2518 subject, subject, subject, subject, loop); | |
| 2519 Node* lindex = | |
| 2520 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 4), | |
| 2521 index, index, index, index, loop); | |
| 2522 Node* leffect = graph()->NewNode(common()->EffectPhi(4), effect, effect, | |
| 2523 effect, effect, loop); | |
| 2524 | |
| 2525 control = loop; | |
| 2526 effect = leffect; | |
| 2527 | |
| 2528 // Determine the instance type of {lsubject}. | |
| 2529 Node* lsubject_map = effect = | |
| 2530 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
| 2531 lsubject, effect, control); | |
| 2532 Node* lsubject_instance_type = effect = graph()->NewNode( | |
| 2533 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), | |
| 2534 lsubject_map, effect, control); | |
| 2535 | |
| 2536 // Check if {lsubject} is a SeqString. | |
| 2537 Node* check0 = graph()->NewNode( | |
| 2538 machine()->Word32Equal(), | |
| 2539 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | |
| 2540 jsgraph()->Int32Constant(kStringRepresentationMask)), | |
| 2541 jsgraph()->Int32Constant(kSeqStringTag)); | |
| 2542 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); | |
| 2543 | |
| 2544 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | |
| 2545 Node* etrue0 = effect; | |
| 2546 Node* vtrue0; | |
| 2547 { | |
| 2548 // Check if the {lsubject} is a TwoByteSeqString or a OneByteSeqString. | |
| 2549 Node* check1 = graph()->NewNode( | |
| 2550 machine()->Word32Equal(), | |
| 2551 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | |
| 2552 jsgraph()->Int32Constant(kStringEncodingMask)), | |
| 2553 jsgraph()->Int32Constant(kTwoByteStringTag)); | |
| 2554 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); | |
| 2555 | |
| 2556 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 2557 Node* etrue1 = etrue0; | |
| 2558 Node* vtrue1 = etrue1 = | |
| 2559 graph()->NewNode(simplified()->LoadElement( | |
| 2560 AccessBuilder::ForSeqTwoByteStringCharacter()), | |
| 2561 lsubject, lindex, etrue1, if_true1); | |
| 2562 | |
| 2563 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 2564 Node* efalse1 = etrue0; | |
| 2565 Node* vfalse1 = efalse1 = | |
| 2566 graph()->NewNode(simplified()->LoadElement( | |
| 2567 AccessBuilder::ForSeqOneByteStringCharacter()), | |
| 2568 lsubject, lindex, efalse1, if_false1); | |
| 2569 | |
| 2570 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 2571 etrue0 = | |
| 2572 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); | |
| 2573 vtrue0 = | |
| 2574 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 2575 vtrue1, vfalse1, if_true0); | |
| 2576 } | |
| 2577 | |
| 2578 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | |
| 2579 Node* efalse0 = effect; | |
| 2580 Node* vfalse0; | |
| 2378 { | 2581 { |
| 2379 // Check if the {lsubject} is a short external string. | 2582 // Check if the {lsubject} is a short external string. |
| 2380 Node* check3 = graph()->NewNode( | 2583 Node* check1 = graph()->NewNode( |
| 2381 machine()->Word32Equal(), | 2584 machine()->Word32Equal(), |
| 2382 graph()->NewNode( | 2585 graph()->NewNode( |
| 2383 machine()->Word32And(), lsubject_instance_type, | 2586 machine()->Word32And(), lsubject_instance_type, |
| 2384 jsgraph()->Int32Constant(kShortExternalStringMask)), | 2587 jsgraph()->Int32Constant(kShortExternalStringMask)), |
| 2385 jsgraph()->Int32Constant(0)); | 2588 jsgraph()->Int32Constant(0)); |
| 2386 Node* branch3 = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 2589 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 2387 check3, if_true2); | 2590 check1, if_false0); |
| 2388 | 2591 |
| 2389 Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3); | 2592 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); |
| 2390 Node* etrue3 = etrue2; | 2593 Node* etrue1 = efalse0; |
| 2391 Node* vtrue3; | 2594 Node* vtrue1; |
| 2392 { | 2595 { |
| 2393 // Load the actual resource data from the {lsubject}. | 2596 // Load the actual resource data from the {lsubject}. |
| 2394 Node* lsubject_resource_data = etrue3 = graph()->NewNode( | 2597 Node* lsubject_resource_data = etrue1 = graph()->NewNode( |
| 2395 simplified()->LoadField( | 2598 simplified()->LoadField( |
| 2396 AccessBuilder::ForExternalStringResourceData()), | 2599 AccessBuilder::ForExternalStringResourceData()), |
| 2397 lsubject, etrue3, if_true3); | 2600 lsubject, etrue1, if_true1); |
| 2398 | 2601 |
| 2399 // Check if the {lsubject} is a TwoByteExternalString or a | 2602 // Check if the {lsubject} is a TwoByteExternalString or a |
| 2400 // OneByteExternalString. | 2603 // OneByteExternalString. |
| 2401 Node* check4 = graph()->NewNode( | 2604 Node* check2 = graph()->NewNode( |
| 2402 machine()->Word32Equal(), | 2605 machine()->Word32Equal(), |
| 2403 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | 2606 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, |
| 2404 jsgraph()->Int32Constant(kStringEncodingMask)), | 2607 jsgraph()->Int32Constant(kStringEncodingMask)), |
| 2405 jsgraph()->Int32Constant(kTwoByteStringTag)); | 2608 jsgraph()->Int32Constant(kTwoByteStringTag)); |
| 2406 Node* branch4 = | 2609 Node* branch2 = |
| 2407 graph()->NewNode(common()->Branch(), check4, if_true3); | 2610 graph()->NewNode(common()->Branch(), check2, if_true1); |
| 2408 | 2611 |
| 2409 Node* if_true4 = graph()->NewNode(common()->IfTrue(), branch4); | 2612 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); |
| 2410 Node* etrue4 = etrue3; | 2613 Node* etrue2 = etrue1; |
| 2411 Node* vtrue4 = etrue4 = graph()->NewNode( | 2614 Node* vtrue2 = etrue2 = graph()->NewNode( |
| 2412 simplified()->LoadElement( | 2615 simplified()->LoadElement( |
| 2413 AccessBuilder::ForExternalTwoByteStringCharacter()), | 2616 AccessBuilder::ForExternalTwoByteStringCharacter()), |
| 2414 lsubject_resource_data, lindex, etrue4, if_true4); | 2617 lsubject_resource_data, index, etrue2, if_true2); |
| 2415 | 2618 |
| 2416 Node* if_false4 = graph()->NewNode(common()->IfFalse(), branch4); | 2619 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); |
| 2417 Node* efalse4 = etrue3; | 2620 Node* efalse2 = etrue1; |
| 2418 Node* vfalse4 = efalse4 = graph()->NewNode( | 2621 Node* vfalse2 = efalse2 = graph()->NewNode( |
| 2419 simplified()->LoadElement( | 2622 simplified()->LoadElement( |
| 2420 AccessBuilder::ForExternalOneByteStringCharacter()), | 2623 AccessBuilder::ForExternalOneByteStringCharacter()), |
| 2421 lsubject_resource_data, lindex, efalse4, if_false4); | 2624 lsubject_resource_data, index, efalse2, if_false2); |
| 2422 | 2625 |
| 2423 if_true3 = graph()->NewNode(common()->Merge(2), if_true4, if_false4); | 2626 if_true1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); |
| 2424 etrue3 = graph()->NewNode(common()->EffectPhi(2), etrue4, efalse4, | 2627 etrue1 = graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, |
| 2425 if_true3); | 2628 if_true1); |
| 2426 vtrue3 = | 2629 vtrue1 = |
| 2427 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | 2630 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 2428 vtrue4, vfalse4, if_true3); | 2631 vtrue2, vfalse2, if_true1); |
| 2429 } | 2632 } |
| 2430 | 2633 |
| 2431 Node* if_false3 = graph()->NewNode(common()->IfFalse(), branch3); | 2634 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); |
| 2432 Node* efalse3 = etrue2; | 2635 Node* efalse1 = efalse0; |
| 2433 Node* vfalse3; | 2636 Node* vfalse1; |
| 2434 { | 2637 { |
| 2435 // The {lsubject} might be compressed, call the runtime. | 2638 // The {lsubject} might be compressed, call the runtime. |
| 2436 Operator::Properties properties = | 2639 Operator::Properties properties = |
| 2437 Operator::kNoDeopt | Operator::kNoThrow; | 2640 Operator::kNoDeopt | Operator::kNoThrow; |
| 2438 Runtime::FunctionId id = Runtime::kExternalStringGetChar; | 2641 Runtime::FunctionId id = Runtime::kExternalStringGetChar; |
| 2439 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( | 2642 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( |
| 2440 graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); | 2643 graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); |
| 2441 vfalse3 = efalse3 = graph()->NewNode( | 2644 vfalse1 = efalse1 = graph()->NewNode( |
| 2442 common()->Call(desc), jsgraph()->CEntryStubConstant(1), lsubject, | 2645 common()->Call(desc), jsgraph()->CEntryStubConstant(1), lsubject, |
| 2443 ChangeInt32ToSmi(lindex), | 2646 ChangeInt32ToSmi(index), |
| 2444 jsgraph()->ExternalConstant(ExternalReference(id, isolate())), | 2647 jsgraph()->ExternalConstant(ExternalReference(id, isolate())), |
| 2445 jsgraph()->Int32Constant(2), jsgraph()->NoContextConstant(), | 2648 jsgraph()->Int32Constant(2), jsgraph()->NoContextConstant(), |
| 2446 efalse3, if_false3); | 2649 efalse1, if_false1); |
| 2447 vfalse3 = ChangeSmiToInt32(vfalse3); | 2650 vfalse1 = ChangeSmiToInt32(vfalse1); |
| 2448 } | 2651 } |
| 2449 | 2652 |
| 2450 if_true2 = graph()->NewNode(common()->Merge(2), if_true3, if_false3); | 2653 if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); |
| 2451 etrue2 = | 2654 efalse0 = graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, |
| 2452 graph()->NewNode(common()->EffectPhi(2), etrue3, efalse3, if_true2); | 2655 if_false0); |
| 2453 vtrue2 = | 2656 vfalse0 = |
| 2454 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | 2657 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 2455 vtrue3, vfalse3, if_true2); | 2658 vtrue1, vfalse1, if_false0); |
| 2456 } | 2659 } |
| 2457 | 2660 |
| 2458 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | 2661 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 2459 Node* efalse2 = efalse1; | 2662 effect = |
| 2460 { | 2663 graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); |
| 2461 // The {lsubject} is a SlicedString, continue with its parent. | 2664 value = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), |
| 2462 Node* lsubject_parent = efalse2 = graph()->NewNode( | 2665 vtrue0, vfalse0, control); |
| 2463 simplified()->LoadField(AccessBuilder::ForSlicedStringParent()), | 2666 break; |
| 2464 lsubject, efalse2, if_false2); | |
| 2465 Node* lsubject_offset = efalse2 = graph()->NewNode( | |
| 2466 simplified()->LoadField(AccessBuilder::ForSlicedStringOffset()), | |
| 2467 lsubject, efalse2, if_false2); | |
| 2468 Node* lsubject_index = graph()->NewNode( | |
| 2469 machine()->Int32Add(), lindex, ChangeSmiToInt32(lsubject_offset)); | |
| 2470 | |
| 2471 // Retry the {loop} with the parent subject. | |
| 2472 loop->ReplaceInput(3, if_false2); | |
| 2473 leffect->ReplaceInput(3, efalse2); | |
| 2474 lindex->ReplaceInput(3, lsubject_index); | |
| 2475 lsubject->ReplaceInput(3, lsubject_parent); | |
| 2476 } | |
| 2477 | |
| 2478 if_false1 = if_true2; | |
| 2479 efalse1 = etrue2; | |
| 2480 vfalse1 = vtrue2; | |
| 2481 } | 2667 } |
| 2482 | |
| 2483 if_false0 = if_false1; | |
| 2484 efalse0 = efalse1; | |
| 2485 vfalse0 = vfalse1; | |
| 2486 } | 2668 } |
| 2487 | 2669 |
| 2488 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
| 2489 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | |
| 2490 Node* value = | |
| 2491 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue0, | |
| 2492 vfalse0, control); | |
| 2493 | |
| 2494 return ValueEffectControl(value, effect, control); | 2670 return ValueEffectControl(value, effect, control); |
| 2495 } | 2671 } |
| 2496 | 2672 |
| 2497 EffectControlLinearizer::ValueEffectControl | 2673 EffectControlLinearizer::ValueEffectControl |
| 2498 EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect, | 2674 EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect, |
| 2499 Node* control) { | 2675 Node* control) { |
| 2500 Node* value = node->InputAt(0); | 2676 Node* value = node->InputAt(0); |
| 2501 | 2677 |
| 2502 // Compute the character code. | 2678 // Compute the character code. |
| 2503 Node* code = | 2679 Node* code = |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 2514 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 2690 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 2515 Node* etrue0 = effect; | 2691 Node* etrue0 = effect; |
| 2516 Node* vtrue0; | 2692 Node* vtrue0; |
| 2517 { | 2693 { |
| 2518 // Load the isolate wide single character string cache. | 2694 // Load the isolate wide single character string cache. |
| 2519 Node* cache = | 2695 Node* cache = |
| 2520 jsgraph()->HeapConstant(factory()->single_character_string_cache()); | 2696 jsgraph()->HeapConstant(factory()->single_character_string_cache()); |
| 2521 | 2697 |
| 2522 // Compute the {cache} index for {code}. | 2698 // Compute the {cache} index for {code}. |
| 2523 Node* index = | 2699 Node* index = |
| 2524 machine()->Is32() ? code : graph()->NewNode( | 2700 machine()->Is32() |
| 2525 machine()->ChangeUint32ToUint64(), code); | 2701 ? code |
| 2702 : graph()->NewNode(machine()->ChangeUint32ToUint64(), code); | |
| 2526 | 2703 |
| 2527 // Check if we have an entry for the {code} in the single character string | 2704 // Check if we have an entry for the {code} in the single character string |
| 2528 // cache already. | 2705 // cache already. |
| 2529 Node* entry = etrue0 = graph()->NewNode( | 2706 Node* entry = etrue0 = graph()->NewNode( |
| 2530 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), cache, | 2707 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), cache, |
| 2531 index, etrue0, if_true0); | 2708 index, etrue0, if_true0); |
| 2532 | 2709 |
| 2533 Node* check1 = graph()->NewNode(machine()->WordEqual(), entry, | 2710 Node* check1 = graph()->NewNode(machine()->WordEqual(), entry, |
| 2534 jsgraph()->UndefinedConstant()); | 2711 jsgraph()->UndefinedConstant()); |
| 2535 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | 2712 Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse), |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2607 | 2784 |
| 2608 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | 2785 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); |
| 2609 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | 2786 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); |
| 2610 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | 2787 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), |
| 2611 vtrue0, vfalse0, control); | 2788 vtrue0, vfalse0, control); |
| 2612 | 2789 |
| 2613 return ValueEffectControl(value, effect, control); | 2790 return ValueEffectControl(value, effect, control); |
| 2614 } | 2791 } |
| 2615 | 2792 |
| 2616 EffectControlLinearizer::ValueEffectControl | 2793 EffectControlLinearizer::ValueEffectControl |
| 2794 EffectControlLinearizer::LowerStringFromCodePoint(Node* node, Node* effect, | |
| 2795 Node* control) { | |
| 2796 Node* value = node->InputAt(0); | |
| 2797 Node* code = value; | |
| 2798 | |
| 2799 Node* etrue0 = effect; | |
| 2800 Node* vtrue0; | |
| 2801 | |
| 2802 // Check if the {code} is a single code unit | |
| 2803 Node* check0 = graph()->NewNode(machine()->Uint32LessThanOrEqual(), code, | |
| 2804 jsgraph()->Uint32Constant(0xFFFF)); | |
| 2805 Node* branch0 = | |
| 2806 graph()->NewNode(common()->Branch(BranchHint::kTrue), check0, control); | |
| 2807 | |
| 2808 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | |
| 2809 | |
| 2810 // Check if the {code} is a one byte character | |
| 2811 Node* check1 = | |
| 2812 graph()->NewNode(machine()->Uint32LessThanOrEqual(), code, | |
| 2813 jsgraph()->Uint32Constant(String::kMaxOneByteCharCode)); | |
| 2814 Node* branch1 = | |
| 2815 graph()->NewNode(common()->Branch(BranchHint::kTrue), check1, if_true0); | |
| 2816 | |
| 2817 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 2818 Node* etrue1 = etrue0; | |
| 2819 Node* vtrue1; | |
| 2820 { | |
| 2821 // Load the isolate wide single character string cache. | |
| 2822 Node* cache = | |
| 2823 jsgraph()->HeapConstant(factory()->single_character_string_cache()); | |
| 2824 | |
| 2825 // Compute the {cache} index for {code}. | |
| 2826 Node* index = | |
| 2827 machine()->Is32() | |
| 2828 ? code | |
| 2829 : graph()->NewNode(machine()->ChangeUint32ToUint64(), code); | |
| 2830 | |
| 2831 // Check if we have an entry for the {code} in the single character string | |
| 2832 // cache already. | |
| 2833 Node* entry = etrue1 = graph()->NewNode( | |
| 2834 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), cache, | |
| 2835 index, etrue1, if_true1); | |
| 2836 | |
| 2837 Node* check2 = graph()->NewNode(machine()->WordEqual(), entry, | |
| 2838 jsgraph()->UndefinedConstant()); | |
| 2839 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
| 2840 check2, if_true1); | |
| 2841 | |
| 2842 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | |
| 2843 Node* etrue2 = etrue1; | |
| 2844 Node* vtrue2; | |
| 2845 { | |
| 2846 // Allocate a new SeqOneByteString for {code}. | |
| 2847 vtrue2 = etrue2 = graph()->NewNode( | |
| 2848 simplified()->Allocate(NOT_TENURED), | |
| 2849 jsgraph()->Int32Constant(SeqOneByteString::SizeFor(1)), etrue2, | |
| 2850 if_true2); | |
| 2851 etrue2 = graph()->NewNode( | |
| 2852 simplified()->StoreField(AccessBuilder::ForMap()), vtrue2, | |
| 2853 jsgraph()->HeapConstant(factory()->one_byte_string_map()), etrue2, | |
| 2854 if_true2); | |
| 2855 etrue2 = graph()->NewNode( | |
| 2856 simplified()->StoreField(AccessBuilder::ForNameHashField()), vtrue2, | |
| 2857 jsgraph()->IntPtrConstant(Name::kEmptyHashField), etrue2, if_true2); | |
| 2858 etrue2 = graph()->NewNode( | |
| 2859 simplified()->StoreField(AccessBuilder::ForStringLength()), vtrue2, | |
| 2860 jsgraph()->SmiConstant(1), etrue2, if_true2); | |
| 2861 etrue2 = graph()->NewNode( | |
| 2862 machine()->Store(StoreRepresentation(MachineRepresentation::kWord8, | |
| 2863 kNoWriteBarrier)), | |
| 2864 vtrue2, jsgraph()->IntPtrConstant(SeqOneByteString::kHeaderSize - | |
| 2865 kHeapObjectTag), | |
| 2866 code, etrue2, if_true2); | |
| 2867 | |
| 2868 // Remember it in the {cache}. | |
| 2869 etrue2 = graph()->NewNode( | |
| 2870 simplified()->StoreElement(AccessBuilder::ForFixedArrayElement()), | |
| 2871 cache, index, vtrue2, etrue2, if_true2); | |
| 2872 } | |
| 2873 | |
| 2874 // Use the {entry} from the {cache}. | |
| 2875 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
| 2876 Node* efalse2 = etrue0; | |
| 2877 Node* vfalse2 = entry; | |
| 2878 | |
| 2879 if_true1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2); | |
| 2880 etrue1 = | |
| 2881 graph()->NewNode(common()->EffectPhi(2), etrue2, efalse2, if_true1); | |
| 2882 vtrue1 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2883 vtrue2, vfalse2, if_true1); | |
| 2884 } | |
| 2885 | |
| 2886 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 2887 Node* efalse1 = effect; | |
| 2888 Node* vfalse1; | |
| 2889 { | |
| 2890 // Allocate a new SeqTwoByteString for {code}. | |
| 2891 vfalse1 = efalse1 = | |
| 2892 graph()->NewNode(simplified()->Allocate(NOT_TENURED), | |
| 2893 jsgraph()->Int32Constant(SeqTwoByteString::SizeFor(1)), | |
| 2894 efalse1, if_false1); | |
| 2895 efalse1 = graph()->NewNode( | |
| 2896 simplified()->StoreField(AccessBuilder::ForMap()), vfalse1, | |
| 2897 jsgraph()->HeapConstant(factory()->string_map()), efalse1, if_false1); | |
| 2898 efalse1 = graph()->NewNode( | |
| 2899 simplified()->StoreField(AccessBuilder::ForNameHashField()), vfalse1, | |
| 2900 jsgraph()->IntPtrConstant(Name::kEmptyHashField), efalse1, if_false1); | |
| 2901 efalse1 = graph()->NewNode( | |
| 2902 simplified()->StoreField(AccessBuilder::ForStringLength()), vfalse1, | |
| 2903 jsgraph()->SmiConstant(1), efalse1, if_false1); | |
| 2904 efalse1 = graph()->NewNode( | |
| 2905 machine()->Store(StoreRepresentation(MachineRepresentation::kWord16, | |
| 2906 kNoWriteBarrier)), | |
| 2907 vfalse1, jsgraph()->IntPtrConstant(SeqTwoByteString::kHeaderSize - | |
| 2908 kHeapObjectTag), | |
| 2909 code, efalse1, if_false1); | |
| 2910 } | |
| 2911 | |
| 2912 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 2913 etrue0 = graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); | |
| 2914 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2915 vtrue1, vfalse1, control); | |
| 2916 | |
| 2917 // Generate surrogate pair string | |
| 2918 Node* if_false0 = graph()->NewNode(common()->IfTrue(), branch0); | |
| 2919 Node* efalse0 = effect; | |
| 2920 Node* vfalse0; | |
| 2921 { | |
| 2922 switch (UnicodeEncodingOf(node->op())) { | |
| 2923 case UnicodeEncoding::UTF16: | |
| 2924 break; | |
| 2925 | |
| 2926 case UnicodeEncoding::UTF32: { | |
| 2927 // Convert UTF32 to UTF16 code units, and store as a 32 bit word. | |
| 2928 Node* lead_offset = jsgraph()->Int32Constant(0xD800 - (0x10000 >> 10)); | |
| 2929 | |
| 2930 // lead = (codepoint >> 10) + LEAD_OFFSET | |
| 2931 Node* lead = | |
| 2932 graph()->NewNode(machine()->Int32Add(), | |
| 2933 graph()->NewNode(machine()->Word32Shr(), code, | |
| 2934 jsgraph()->Int32Constant(10)), | |
| 2935 lead_offset); | |
| 2936 | |
| 2937 // trail = (codepoint & 0x3FF) + 0xDC00; | |
| 2938 Node* trail = | |
| 2939 graph()->NewNode(machine()->Int32Add(), | |
| 2940 graph()->NewNode(machine()->Word32And(), code, | |
| 2941 jsgraph()->Int32Constant(0x3FF)), | |
| 2942 jsgraph()->Int32Constant(0xDC00)); | |
| 2943 | |
| 2944 // codpoint = (trail << 16) | lead; | |
| 2945 code = efalse1 = | |
| 2946 graph()->NewNode(machine()->Word32Or(), | |
| 2947 graph()->NewNode(machine()->Word32Shl(), trail, | |
| 2948 jsgraph()->Int32Constant(16)), | |
| 2949 lead); | |
| 2950 break; | |
| 2951 } | |
| 2952 } | |
| 2953 | |
| 2954 // Allocate a new SeqTwoByteString for {code}. | |
| 2955 vfalse0 = efalse0 = | |
| 2956 graph()->NewNode(simplified()->Allocate(NOT_TENURED), | |
| 2957 jsgraph()->Int32Constant(SeqTwoByteString::SizeFor(2)), | |
| 2958 efalse0, if_false0); | |
| 2959 efalse0 = graph()->NewNode( | |
| 2960 simplified()->StoreField(AccessBuilder::ForMap()), vfalse0, | |
| 2961 jsgraph()->HeapConstant(factory()->string_map()), efalse0, if_false0); | |
| 2962 efalse0 = graph()->NewNode( | |
| 2963 simplified()->StoreField(AccessBuilder::ForNameHashField()), vfalse0, | |
| 2964 jsgraph()->IntPtrConstant(Name::kEmptyHashField), efalse0, if_false1); | |
| 2965 efalse0 = graph()->NewNode( | |
| 2966 simplified()->StoreField(AccessBuilder::ForStringLength()), vfalse0, | |
| 2967 jsgraph()->SmiConstant(2), efalse0, if_false0); | |
| 2968 efalse0 = graph()->NewNode( | |
| 2969 machine()->Store(StoreRepresentation(MachineRepresentation::kWord32, | |
| 2970 kNoWriteBarrier)), | |
| 2971 vfalse0, jsgraph()->IntPtrConstant(SeqTwoByteString::kHeaderSize - | |
| 2972 kHeapObjectTag), | |
| 2973 code, efalse0, if_false0); | |
| 2974 } | |
| 2975 | |
| 2976 control = graph()->NewNode(common()->Merge(2), if_true0, if_false0); | |
| 2977 effect = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | |
| 2978 value = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2), | |
| 2979 vtrue0, vfalse0, control); | |
| 2980 | |
| 2981 return ValueEffectControl(value, effect, control); | |
| 2982 } | |
| 2983 | |
| 2984 EffectControlLinearizer::ValueEffectControl | |
| 2617 EffectControlLinearizer::LowerStringComparison(Callable const& callable, | 2985 EffectControlLinearizer::LowerStringComparison(Callable const& callable, |
| 2618 Node* node, Node* effect, | 2986 Node* node, Node* effect, |
| 2619 Node* control) { | 2987 Node* control) { |
| 2620 Operator::Properties properties = Operator::kEliminatable; | 2988 Operator::Properties properties = Operator::kEliminatable; |
| 2621 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; | 2989 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
| 2622 CallDescriptor* desc = Linkage::GetStubCallDescriptor( | 2990 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 2623 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); | 2991 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties); |
| 2624 node->InsertInput(graph()->zone(), 0, | 2992 node->InsertInput(graph()->zone(), 0, |
| 2625 jsgraph()->HeapConstant(callable.code())); | 2993 jsgraph()->HeapConstant(callable.code())); |
| 2626 node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant()); | 2994 node->AppendInput(graph()->zone(), jsgraph()->NoContextConstant()); |
| (...skipping 928 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3555 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3923 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 3556 Operator::kEliminatable); | 3924 Operator::kEliminatable); |
| 3557 to_number_operator_.set(common()->Call(desc)); | 3925 to_number_operator_.set(common()->Call(desc)); |
| 3558 } | 3926 } |
| 3559 return to_number_operator_.get(); | 3927 return to_number_operator_.get(); |
| 3560 } | 3928 } |
| 3561 | 3929 |
| 3562 } // namespace compiler | 3930 } // namespace compiler |
| 3563 } // namespace internal | 3931 } // namespace internal |
| 3564 } // namespace v8 | 3932 } // namespace v8 |
| OLD | NEW |