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 |