| 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/compiler-source-position-table.h" | 9 #include "src/compiler/compiler-source-position-table.h" |
| 10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
| (...skipping 2229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2240 jsgraph()->HeapConstant(callable.code())); | 2240 jsgraph()->HeapConstant(callable.code())); |
| 2241 node->InsertInput(graph()->zone(), 3, jsgraph()->NoContextConstant()); | 2241 node->InsertInput(graph()->zone(), 3, jsgraph()->NoContextConstant()); |
| 2242 node->InsertInput(graph()->zone(), 4, effect); | 2242 node->InsertInput(graph()->zone(), 4, effect); |
| 2243 NodeProperties::ChangeOp(node, common()->Call(desc)); | 2243 NodeProperties::ChangeOp(node, common()->Call(desc)); |
| 2244 return ValueEffectControl(node, node, control); | 2244 return ValueEffectControl(node, node, control); |
| 2245 } | 2245 } |
| 2246 | 2246 |
| 2247 EffectControlLinearizer::ValueEffectControl | 2247 EffectControlLinearizer::ValueEffectControl |
| 2248 EffectControlLinearizer::LowerStringCharCodeAt(Node* node, Node* effect, | 2248 EffectControlLinearizer::LowerStringCharCodeAt(Node* node, Node* effect, |
| 2249 Node* control) { | 2249 Node* control) { |
| 2250 Node* subject = node->InputAt(0); | 2250 Callable const callable = CodeFactory::StringCharCodeAt(isolate()); |
| 2251 Node* index = node->InputAt(1); | 2251 Operator::Properties properties = Operator::kNoThrow | Operator::kNoWrite; |
| 2252 | 2252 CallDescriptor::Flags flags = CallDescriptor::kNoFlags; |
| 2253 // We may need to loop several times for ConsString/SlicedString {subject}s. | 2253 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 2254 Node* loop = | 2254 isolate(), graph()->zone(), callable.descriptor(), 0, flags, properties, |
| 2255 graph()->NewNode(common()->Loop(4), control, control, control, control); | 2255 MachineType::TaggedSigned()); |
| 2256 Node* lsubject = | 2256 node->InsertInput(graph()->zone(), 0, |
| 2257 graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 4), | 2257 jsgraph()->HeapConstant(callable.code())); |
| 2258 subject, subject, subject, subject, loop); | 2258 node->InsertInput(graph()->zone(), 3, jsgraph()->NoContextConstant()); |
| 2259 Node* lindex = | 2259 node->InsertInput(graph()->zone(), 4, effect); |
| 2260 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 4), index, | 2260 NodeProperties::ChangeOp(node, common()->Call(desc)); |
| 2261 index, index, index, loop); | 2261 return ValueEffectControl(node, node, control); |
| 2262 Node* leffect = graph()->NewNode(common()->EffectPhi(4), effect, effect, | |
| 2263 effect, effect, loop); | |
| 2264 | |
| 2265 control = loop; | |
| 2266 effect = leffect; | |
| 2267 | |
| 2268 // Determine the instance type of {lsubject}. | |
| 2269 Node* lsubject_map = effect = | |
| 2270 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
| 2271 lsubject, effect, control); | |
| 2272 Node* lsubject_instance_type = effect = graph()->NewNode( | |
| 2273 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), | |
| 2274 lsubject_map, effect, control); | |
| 2275 | |
| 2276 // Check if {lsubject} is a SeqString. | |
| 2277 Node* check0 = graph()->NewNode( | |
| 2278 machine()->Word32Equal(), | |
| 2279 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | |
| 2280 jsgraph()->Int32Constant(kStringRepresentationMask)), | |
| 2281 jsgraph()->Int32Constant(kSeqStringTag)); | |
| 2282 Node* branch0 = graph()->NewNode(common()->Branch(), check0, control); | |
| 2283 | |
| 2284 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | |
| 2285 Node* etrue0 = effect; | |
| 2286 Node* vtrue0; | |
| 2287 { | |
| 2288 // Check if the {lsubject} is a TwoByteSeqString or a OneByteSeqString. | |
| 2289 Node* check1 = graph()->NewNode( | |
| 2290 machine()->Word32Equal(), | |
| 2291 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | |
| 2292 jsgraph()->Int32Constant(kStringEncodingMask)), | |
| 2293 jsgraph()->Int32Constant(kTwoByteStringTag)); | |
| 2294 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0); | |
| 2295 | |
| 2296 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 2297 Node* etrue1 = etrue0; | |
| 2298 Node* vtrue1 = etrue1 = | |
| 2299 graph()->NewNode(simplified()->LoadElement( | |
| 2300 AccessBuilder::ForSeqTwoByteStringCharacter()), | |
| 2301 lsubject, lindex, etrue1, if_true1); | |
| 2302 | |
| 2303 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 2304 Node* efalse1 = etrue0; | |
| 2305 Node* vfalse1 = efalse1 = | |
| 2306 graph()->NewNode(simplified()->LoadElement( | |
| 2307 AccessBuilder::ForSeqOneByteStringCharacter()), | |
| 2308 lsubject, lindex, efalse1, if_false1); | |
| 2309 | |
| 2310 if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1); | |
| 2311 etrue0 = | |
| 2312 graph()->NewNode(common()->EffectPhi(2), etrue1, efalse1, if_true0); | |
| 2313 vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 2314 vtrue1, vfalse1, if_true0); | |
| 2315 } | |
| 2316 | |
| 2317 Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0); | |
| 2318 Node* efalse0 = effect; | |
| 2319 Node* vfalse0; | |
| 2320 { | |
| 2321 // Check if the {lsubject} is a ConsString. | |
| 2322 Node* check1 = graph()->NewNode( | |
| 2323 machine()->Word32Equal(), | |
| 2324 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | |
| 2325 jsgraph()->Int32Constant(kStringRepresentationMask)), | |
| 2326 jsgraph()->Int32Constant(kConsStringTag)); | |
| 2327 Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0); | |
| 2328 | |
| 2329 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1); | |
| 2330 Node* etrue1 = efalse0; | |
| 2331 { | |
| 2332 // Load the right hand side of the {lsubject} ConsString. | |
| 2333 Node* lsubject_second = etrue1 = graph()->NewNode( | |
| 2334 simplified()->LoadField(AccessBuilder::ForConsStringSecond()), | |
| 2335 lsubject, etrue1, if_true1); | |
| 2336 | |
| 2337 // Check whether the right hand side is the empty string (i.e. if | |
| 2338 // this is really a flat string in a cons string). If that is not | |
| 2339 // the case we flatten the string first. | |
| 2340 Node* check2 = graph()->NewNode(machine()->WordEqual(), lsubject_second, | |
| 2341 jsgraph()->EmptyStringConstant()); | |
| 2342 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue), | |
| 2343 check2, if_true1); | |
| 2344 | |
| 2345 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | |
| 2346 Node* etrue2 = etrue1; | |
| 2347 Node* vtrue2 = etrue2 = graph()->NewNode( | |
| 2348 simplified()->LoadField(AccessBuilder::ForConsStringFirst()), | |
| 2349 lsubject, etrue2, if_true2); | |
| 2350 | |
| 2351 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
| 2352 Node* efalse2 = etrue1; | |
| 2353 Node* vfalse2; | |
| 2354 { | |
| 2355 // Flatten the {lsubject} ConsString first. | |
| 2356 Operator::Properties properties = | |
| 2357 Operator::kNoDeopt | Operator::kNoThrow; | |
| 2358 Runtime::FunctionId id = Runtime::kFlattenString; | |
| 2359 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( | |
| 2360 graph()->zone(), id, 1, properties, CallDescriptor::kNoFlags); | |
| 2361 vfalse2 = efalse2 = graph()->NewNode( | |
| 2362 common()->Call(desc), jsgraph()->CEntryStubConstant(1), lsubject, | |
| 2363 jsgraph()->ExternalConstant(ExternalReference(id, isolate())), | |
| 2364 jsgraph()->Int32Constant(1), jsgraph()->NoContextConstant(), | |
| 2365 efalse2, if_false2); | |
| 2366 } | |
| 2367 | |
| 2368 // Retry the {loop} with the new subject. | |
| 2369 loop->ReplaceInput(1, if_true2); | |
| 2370 lindex->ReplaceInput(1, lindex); | |
| 2371 leffect->ReplaceInput(1, etrue2); | |
| 2372 lsubject->ReplaceInput(1, vtrue2); | |
| 2373 loop->ReplaceInput(2, if_false2); | |
| 2374 lindex->ReplaceInput(2, lindex); | |
| 2375 leffect->ReplaceInput(2, efalse2); | |
| 2376 lsubject->ReplaceInput(2, vfalse2); | |
| 2377 } | |
| 2378 | |
| 2379 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1); | |
| 2380 Node* efalse1 = efalse0; | |
| 2381 Node* vfalse1; | |
| 2382 { | |
| 2383 // Check if the {lsubject} is an ExternalString. | |
| 2384 Node* check2 = graph()->NewNode( | |
| 2385 machine()->Word32Equal(), | |
| 2386 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | |
| 2387 jsgraph()->Int32Constant(kStringRepresentationMask)), | |
| 2388 jsgraph()->Int32Constant(kExternalStringTag)); | |
| 2389 Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kTrue), | |
| 2390 check2, if_false1); | |
| 2391 | |
| 2392 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2); | |
| 2393 Node* etrue2 = efalse1; | |
| 2394 Node* vtrue2; | |
| 2395 { | |
| 2396 // Check if the {lsubject} is a short external string. | |
| 2397 Node* check3 = graph()->NewNode( | |
| 2398 machine()->Word32Equal(), | |
| 2399 graph()->NewNode( | |
| 2400 machine()->Word32And(), lsubject_instance_type, | |
| 2401 jsgraph()->Int32Constant(kShortExternalStringMask)), | |
| 2402 jsgraph()->Int32Constant(0)); | |
| 2403 Node* branch3 = graph()->NewNode(common()->Branch(BranchHint::kTrue), | |
| 2404 check3, if_true2); | |
| 2405 | |
| 2406 Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3); | |
| 2407 Node* etrue3 = etrue2; | |
| 2408 Node* vtrue3; | |
| 2409 { | |
| 2410 // Load the actual resource data from the {lsubject}. | |
| 2411 Node* lsubject_resource_data = etrue3 = graph()->NewNode( | |
| 2412 simplified()->LoadField( | |
| 2413 AccessBuilder::ForExternalStringResourceData()), | |
| 2414 lsubject, etrue3, if_true3); | |
| 2415 | |
| 2416 // Check if the {lsubject} is a TwoByteExternalString or a | |
| 2417 // OneByteExternalString. | |
| 2418 Node* check4 = graph()->NewNode( | |
| 2419 machine()->Word32Equal(), | |
| 2420 graph()->NewNode(machine()->Word32And(), lsubject_instance_type, | |
| 2421 jsgraph()->Int32Constant(kStringEncodingMask)), | |
| 2422 jsgraph()->Int32Constant(kTwoByteStringTag)); | |
| 2423 Node* branch4 = | |
| 2424 graph()->NewNode(common()->Branch(), check4, if_true3); | |
| 2425 | |
| 2426 Node* if_true4 = graph()->NewNode(common()->IfTrue(), branch4); | |
| 2427 Node* etrue4 = etrue3; | |
| 2428 Node* vtrue4 = etrue4 = graph()->NewNode( | |
| 2429 simplified()->LoadElement( | |
| 2430 AccessBuilder::ForExternalTwoByteStringCharacter()), | |
| 2431 lsubject_resource_data, lindex, etrue4, if_true4); | |
| 2432 | |
| 2433 Node* if_false4 = graph()->NewNode(common()->IfFalse(), branch4); | |
| 2434 Node* efalse4 = etrue3; | |
| 2435 Node* vfalse4 = efalse4 = graph()->NewNode( | |
| 2436 simplified()->LoadElement( | |
| 2437 AccessBuilder::ForExternalOneByteStringCharacter()), | |
| 2438 lsubject_resource_data, lindex, efalse4, if_false4); | |
| 2439 | |
| 2440 if_true3 = graph()->NewNode(common()->Merge(2), if_true4, if_false4); | |
| 2441 etrue3 = graph()->NewNode(common()->EffectPhi(2), etrue4, efalse4, | |
| 2442 if_true3); | |
| 2443 vtrue3 = | |
| 2444 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 2445 vtrue4, vfalse4, if_true3); | |
| 2446 } | |
| 2447 | |
| 2448 Node* if_false3 = graph()->NewNode(common()->IfFalse(), branch3); | |
| 2449 Node* efalse3 = etrue2; | |
| 2450 Node* vfalse3; | |
| 2451 { | |
| 2452 // The {lsubject} might be compressed, call the runtime. | |
| 2453 Operator::Properties properties = | |
| 2454 Operator::kNoDeopt | Operator::kNoThrow; | |
| 2455 Runtime::FunctionId id = Runtime::kExternalStringGetChar; | |
| 2456 CallDescriptor const* desc = Linkage::GetRuntimeCallDescriptor( | |
| 2457 graph()->zone(), id, 2, properties, CallDescriptor::kNoFlags); | |
| 2458 vfalse3 = efalse3 = graph()->NewNode( | |
| 2459 common()->Call(desc), jsgraph()->CEntryStubConstant(1), lsubject, | |
| 2460 ChangeInt32ToSmi(lindex), | |
| 2461 jsgraph()->ExternalConstant(ExternalReference(id, isolate())), | |
| 2462 jsgraph()->Int32Constant(2), jsgraph()->NoContextConstant(), | |
| 2463 efalse3, if_false3); | |
| 2464 vfalse3 = ChangeSmiToInt32(vfalse3); | |
| 2465 } | |
| 2466 | |
| 2467 if_true2 = graph()->NewNode(common()->Merge(2), if_true3, if_false3); | |
| 2468 etrue2 = | |
| 2469 graph()->NewNode(common()->EffectPhi(2), etrue3, efalse3, if_true2); | |
| 2470 vtrue2 = | |
| 2471 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), | |
| 2472 vtrue3, vfalse3, if_true2); | |
| 2473 } | |
| 2474 | |
| 2475 Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2); | |
| 2476 Node* efalse2 = efalse1; | |
| 2477 { | |
| 2478 // The {lsubject} is a SlicedString, continue with its parent. | |
| 2479 Node* lsubject_parent = efalse2 = graph()->NewNode( | |
| 2480 simplified()->LoadField(AccessBuilder::ForSlicedStringParent()), | |
| 2481 lsubject, efalse2, if_false2); | |
| 2482 Node* lsubject_offset = efalse2 = graph()->NewNode( | |
| 2483 simplified()->LoadField(AccessBuilder::ForSlicedStringOffset()), | |
| 2484 lsubject, efalse2, if_false2); | |
| 2485 Node* lsubject_index = graph()->NewNode( | |
| 2486 machine()->Int32Add(), lindex, 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 = graph()->NewNode(common()->EffectPhi(2), etrue0, efalse0, control); | |
| 2507 Node* value = | |
| 2508 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 2), vtrue0, | |
| 2509 vfalse0, control); | |
| 2510 | |
| 2511 return ValueEffectControl(value, effect, control); | |
| 2512 } | 2262 } |
| 2513 | 2263 |
| 2514 EffectControlLinearizer::ValueEffectControl | 2264 EffectControlLinearizer::ValueEffectControl |
| 2515 EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect, | 2265 EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect, |
| 2516 Node* control) { | 2266 Node* control) { |
| 2517 Node* value = node->InputAt(0); | 2267 Node* value = node->InputAt(0); |
| 2518 | 2268 |
| 2519 // Compute the character code. | 2269 // Compute the character code. |
| 2520 Node* code = | 2270 Node* code = |
| 2521 graph()->NewNode(machine()->Word32And(), value, | 2271 graph()->NewNode(machine()->Word32And(), value, |
| (...skipping 1313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3835 isolate(), graph()->zone(), callable.descriptor(), 0, flags, | 3585 isolate(), graph()->zone(), callable.descriptor(), 0, flags, |
| 3836 Operator::kEliminatable); | 3586 Operator::kEliminatable); |
| 3837 to_number_operator_.set(common()->Call(desc)); | 3587 to_number_operator_.set(common()->Call(desc)); |
| 3838 } | 3588 } |
| 3839 return to_number_operator_.get(); | 3589 return to_number_operator_.get(); |
| 3840 } | 3590 } |
| 3841 | 3591 |
| 3842 } // namespace compiler | 3592 } // namespace compiler |
| 3843 } // namespace internal | 3593 } // namespace internal |
| 3844 } // namespace v8 | 3594 } // namespace v8 |
| OLD | NEW |