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 |