Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(217)

Side by Side Diff: src/compiler/effect-control-linearizer.cc

Issue 2600443002: [turbofan] Lower StringCharCodeAt to a dedicated builtin. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/code-factory.cc ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/code-factory.cc ('k') | src/compiler/simplified-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698