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

Side by Side Diff: src/compiler/js-typed-lowering.cc

Issue 2827013002: [turbofan] Constant-fold certain JSOrdinaryHasInstance nodes. (Closed)
Patch Set: Created 3 years, 8 months 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/compiler/js-native-context-specialization.cc ('k') | test/mjsunit/compiler/instanceof.js » ('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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/js-typed-lowering.h" 5 #include "src/compiler/js-typed-lowering.h"
6 6
7 #include "src/ast/modules.h" 7 #include "src/ast/modules.h"
8 #include "src/builtins/builtins-utils.h" 8 #include "src/builtins/builtins-utils.h"
9 #include "src/code-factory.h" 9 #include "src/code-factory.h"
10 #include "src/compilation-dependencies.h" 10 #include "src/compilation-dependencies.h"
(...skipping 1308 matching lines...) Expand 10 before | Expand all | Expand 10 after
1319 } 1319 }
1320 return NoChange(); 1320 return NoChange();
1321 } 1321 }
1322 1322
1323 Reduction JSTypedLowering::ReduceJSOrdinaryHasInstance(Node* node) { 1323 Reduction JSTypedLowering::ReduceJSOrdinaryHasInstance(Node* node) {
1324 DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode()); 1324 DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode());
1325 Node* constructor = NodeProperties::GetValueInput(node, 0); 1325 Node* constructor = NodeProperties::GetValueInput(node, 0);
1326 Type* constructor_type = NodeProperties::GetType(constructor); 1326 Type* constructor_type = NodeProperties::GetType(constructor);
1327 Node* object = NodeProperties::GetValueInput(node, 1); 1327 Node* object = NodeProperties::GetValueInput(node, 1);
1328 Type* object_type = NodeProperties::GetType(object); 1328 Type* object_type = NodeProperties::GetType(object);
1329 Node* context = NodeProperties::GetContextInput(node);
1330 Node* frame_state = NodeProperties::GetFrameStateInput(node);
1331 Node* effect = NodeProperties::GetEffectInput(node);
1332 Node* control = NodeProperties::GetControlInput(node);
1333 1329
1334 // Check if the {constructor} cannot be callable. 1330 // Check if the {constructor} cannot be callable.
1335 // See ES6 section 7.3.19 OrdinaryHasInstance ( C, O ) step 1. 1331 // See ES6 section 7.3.19 OrdinaryHasInstance ( C, O ) step 1.
1336 if (!constructor_type->Maybe(Type::Callable())) { 1332 if (!constructor_type->Maybe(Type::Callable())) {
1337 Node* value = jsgraph()->FalseConstant(); 1333 Node* value = jsgraph()->FalseConstant();
1338 ReplaceWithValue(node, value, effect, control); 1334 ReplaceWithValue(node, value);
1339 return Replace(value); 1335 return Replace(value);
1340 } 1336 }
1341 1337
1342 // If the {constructor} cannot be a JSBoundFunction and then {object} 1338 // If the {constructor} cannot be a JSBoundFunction and then {object}
1343 // cannot be a JSReceiver, then this can be constant-folded to false. 1339 // cannot be a JSReceiver, then this can be constant-folded to false.
1344 // See ES6 section 7.3.19 OrdinaryHasInstance ( C, O ) step 2 and 3. 1340 // See ES6 section 7.3.19 OrdinaryHasInstance ( C, O ) step 2 and 3.
1345 if (!object_type->Maybe(Type::Receiver()) && 1341 if (!object_type->Maybe(Type::Receiver()) &&
1346 !constructor_type->Maybe(Type::BoundFunction())) { 1342 !constructor_type->Maybe(Type::BoundFunction())) {
1347 Node* value = jsgraph()->FalseConstant(); 1343 Node* value = jsgraph()->FalseConstant();
1348 ReplaceWithValue(node, value, effect, control); 1344 ReplaceWithValue(node, value);
1349 return Replace(value); 1345 return Replace(value);
1350 } 1346 }
1351 1347
1352 // Check if the {constructor} is a (known) JSFunction. 1348 return NoChange();
1353 if (!constructor_type->IsHeapConstant() ||
1354 !constructor_type->AsHeapConstant()->Value()->IsJSFunction()) {
1355 return NoChange();
1356 }
1357 Handle<JSFunction> function =
1358 Handle<JSFunction>::cast(constructor_type->AsHeapConstant()->Value());
1359
1360 // Check if the {function} already has an initial map (i.e. the
1361 // {function} has been used as a constructor at least once).
1362 if (!function->has_initial_map()) return NoChange();
1363
1364 // Check if the {function}s "prototype" is a JSReceiver.
1365 if (!function->prototype()->IsJSReceiver()) return NoChange();
1366
1367 // Install a code dependency on the {function}s initial map.
1368 Handle<Map> initial_map(function->initial_map(), isolate());
1369 dependencies()->AssumeInitialMapCantChange(initial_map);
1370
1371 Node* prototype =
1372 jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
1373
1374 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), object);
1375 Node* branch0 =
1376 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
1377
1378 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1379 Node* etrue0 = effect;
1380 Node* vtrue0 = jsgraph()->FalseConstant();
1381
1382 control = graph()->NewNode(common()->IfFalse(), branch0);
1383
1384 // Loop through the {object}s prototype chain looking for the {prototype}.
1385 Node* loop = control = graph()->NewNode(common()->Loop(2), control, control);
1386 Node* eloop = effect =
1387 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop);
1388 Node* vloop = object = graph()->NewNode(
1389 common()->Phi(MachineRepresentation::kTagged, 2), object, object, loop);
1390 // TODO(jarin): This is a very ugly hack to work-around the super-smart
1391 // implicit typing of the Phi, which goes completely nuts if the {object}
1392 // is for example a HeapConstant.
1393 NodeProperties::SetType(vloop, Type::NonInternal());
1394
1395 // Load the {object} map and instance type.
1396 Node* object_map = effect =
1397 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), object,
1398 effect, control);
1399 Node* object_instance_type = effect = graph()->NewNode(
1400 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), object_map,
1401 effect, control);
1402
1403 // Check if the {object} is a special receiver, because for special
1404 // receivers, i.e. proxies or API objects that need access checks,
1405 // we have to use the %HasInPrototypeChain runtime function instead.
1406 Node* check1 = graph()->NewNode(
1407 simplified()->NumberLessThanOrEqual(), object_instance_type,
1408 jsgraph()->Constant(LAST_SPECIAL_RECEIVER_TYPE));
1409 Node* branch1 =
1410 graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control);
1411
1412 control = graph()->NewNode(common()->IfFalse(), branch1);
1413
1414 Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
1415 Node* etrue1 = effect;
1416 Node* vtrue1;
1417
1418 // Check if the {object} is not a receiver at all.
1419 Node* check10 =
1420 graph()->NewNode(simplified()->NumberLessThan(), object_instance_type,
1421 jsgraph()->Constant(FIRST_JS_RECEIVER_TYPE));
1422 Node* branch10 =
1423 graph()->NewNode(common()->Branch(BranchHint::kTrue), check10, if_true1);
1424
1425 // A primitive value cannot match the {prototype} we're looking for.
1426 if_true1 = graph()->NewNode(common()->IfTrue(), branch10);
1427 vtrue1 = jsgraph()->FalseConstant();
1428
1429 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch10);
1430 Node* efalse1 = etrue1;
1431 Node* vfalse1;
1432 {
1433 // Slow path, need to call the %HasInPrototypeChain runtime function.
1434 vfalse1 = efalse1 = if_false1 = graph()->NewNode(
1435 javascript()->CallRuntime(Runtime::kHasInPrototypeChain), object,
1436 prototype, context, frame_state, efalse1, if_false1);
1437
1438 // Replace any potential {IfException} uses of {node} to catch exceptions
1439 // from this %HasInPrototypeChain runtime call instead.
1440 Node* on_exception = nullptr;
1441 if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
1442 NodeProperties::ReplaceControlInput(on_exception, vfalse1);
1443 NodeProperties::ReplaceEffectInput(on_exception, efalse1);
1444 if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1);
1445 Revisit(on_exception);
1446 }
1447 }
1448
1449 // Load the {object} prototype.
1450 Node* object_prototype = effect = graph()->NewNode(
1451 simplified()->LoadField(AccessBuilder::ForMapPrototype()), object_map,
1452 effect, control);
1453
1454 // Check if we reached the end of {object}s prototype chain.
1455 Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(),
1456 object_prototype, jsgraph()->NullConstant());
1457 Node* branch2 = graph()->NewNode(common()->Branch(), check2, control);
1458
1459 Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
1460 Node* etrue2 = effect;
1461 Node* vtrue2 = jsgraph()->FalseConstant();
1462
1463 control = graph()->NewNode(common()->IfFalse(), branch2);
1464
1465 // Check if we reached the {prototype}.
1466 Node* check3 = graph()->NewNode(simplified()->ReferenceEqual(),
1467 object_prototype, prototype);
1468 Node* branch3 = graph()->NewNode(common()->Branch(), check3, control);
1469
1470 Node* if_true3 = graph()->NewNode(common()->IfTrue(), branch3);
1471 Node* etrue3 = effect;
1472 Node* vtrue3 = jsgraph()->TrueConstant();
1473
1474 control = graph()->NewNode(common()->IfFalse(), branch3);
1475
1476 // Close the loop.
1477 vloop->ReplaceInput(1, object_prototype);
1478 eloop->ReplaceInput(1, effect);
1479 loop->ReplaceInput(1, control);
1480
1481 control = graph()->NewNode(common()->Merge(5), if_true0, if_true1, if_true2,
1482 if_true3, if_false1);
1483 effect = graph()->NewNode(common()->EffectPhi(5), etrue0, etrue1, etrue2,
1484 etrue3, efalse1, control);
1485
1486 // Morph the {node} into an appropriate Phi.
1487 ReplaceWithValue(node, node, effect, control);
1488 node->ReplaceInput(0, vtrue0);
1489 node->ReplaceInput(1, vtrue1);
1490 node->ReplaceInput(2, vtrue2);
1491 node->ReplaceInput(3, vtrue3);
1492 node->ReplaceInput(4, vfalse1);
1493 node->ReplaceInput(5, control);
1494 node->TrimInputCount(6);
1495 NodeProperties::ChangeOp(node,
1496 common()->Phi(MachineRepresentation::kTagged, 5));
1497 return Changed(node);
1498 } 1349 }
1499 1350
1500 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { 1351 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) {
1501 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); 1352 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode());
1502 ContextAccess const& access = ContextAccessOf(node->op()); 1353 ContextAccess const& access = ContextAccessOf(node->op());
1503 Node* effect = NodeProperties::GetEffectInput(node); 1354 Node* effect = NodeProperties::GetEffectInput(node);
1504 Node* context = NodeProperties::GetContextInput(node); 1355 Node* context = NodeProperties::GetContextInput(node);
1505 Node* control = graph()->start(); 1356 Node* control = graph()->start();
1506 for (size_t i = 0; i < access.depth(); ++i) { 1357 for (size_t i = 0; i < access.depth(); ++i) {
1507 context = effect = graph()->NewNode( 1358 context = effect = graph()->NewNode(
(...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after
2390 } 2241 }
2391 2242
2392 2243
2393 CompilationDependencies* JSTypedLowering::dependencies() const { 2244 CompilationDependencies* JSTypedLowering::dependencies() const {
2394 return dependencies_; 2245 return dependencies_;
2395 } 2246 }
2396 2247
2397 } // namespace compiler 2248 } // namespace compiler
2398 } // namespace internal 2249 } // namespace internal
2399 } // namespace v8 2250 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.cc ('k') | test/mjsunit/compiler/instanceof.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698