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

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

Issue 2511223003: [turbofan] Properly optimize instanceof (even in the presence of @@hasInstance). (Closed)
Patch Set: Created 4 years, 1 month 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
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 1293 matching lines...) Expand 10 before | Expand all | Expand 10 after
1304 node->ReplaceInput(5, control); 1304 node->ReplaceInput(5, control);
1305 node->TrimInputCount(6); 1305 node->TrimInputCount(6);
1306 NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access)); 1306 NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access));
1307 return Changed(node); 1307 return Changed(node);
1308 } 1308 }
1309 } 1309 }
1310 } 1310 }
1311 return NoChange(); 1311 return NoChange();
1312 } 1312 }
1313 1313
1314 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) { 1314 Reduction JSTypedLowering::ReduceJSOrdinaryHasInstance(Node* node) {
1315 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); 1315 DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode());
1316 Node* const context = NodeProperties::GetContextInput(node); 1316 Node* constructor = NodeProperties::GetValueInput(node, 0);
1317 Node* const frame_state = NodeProperties::GetFrameStateInput(node); 1317 Type* constructor_type = NodeProperties::GetType(constructor);
1318 Node* object = NodeProperties::GetValueInput(node, 1);
1319 Node* context = NodeProperties::GetContextInput(node);
1320 Node* frame_state = NodeProperties::GetFrameStateInput(node);
1321 Node* effect = NodeProperties::GetEffectInput(node);
1322 Node* control = NodeProperties::GetControlInput(node);
1318 1323
1319 // If deoptimization is disabled, we cannot optimize. 1324 // Check if the {constructor} is a (known) JSFunction.
1320 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); 1325 if (!constructor_type->IsHeapConstant() ||
1321 1326 !constructor_type->AsHeapConstant()->Value()->IsJSFunction()) {
1322 // If we are in a try block, don't optimize since the runtime call
1323 // in the proxy case can throw.
1324 if (NodeProperties::IsExceptionalCall(node)) return NoChange();
1325
1326 JSBinopReduction r(this, node);
1327 Node* object = r.left();
1328 Node* effect = r.effect();
1329 Node* control = r.control();
1330
1331 if (!r.right_type()->IsHeapConstant() ||
1332 !r.right_type()->AsHeapConstant()->Value()->IsJSFunction()) {
1333 return NoChange(); 1327 return NoChange();
1334 } 1328 }
1329 Handle<JSFunction> function =
1330 Handle<JSFunction>::cast(constructor_type->AsHeapConstant()->Value());
1335 1331
1336 Handle<JSFunction> function = 1332 // Check if the {function} already has an initial map (i.e. the
1337 Handle<JSFunction>::cast(r.right_type()->AsHeapConstant()->Value()); 1333 // {function} has been used as a constructor at least once).
1338 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); 1334 if (!function->has_initial_map()) return NoChange();
1339 1335
1340 // Make sure the prototype of {function} is the %FunctionPrototype%, and it 1336 // Check if the {function}s "prototype" is a JSReceiver.
1341 // already has a meaningful initial map (i.e. we constructed at least one 1337 if (!function->prototype()->IsJSReceiver()) return NoChange();
1342 // instance using the constructor {function}).
1343 if (function->map()->prototype() != function->native_context()->closure() ||
1344 function->map()->has_non_instance_prototype() ||
1345 !function->has_initial_map()) {
1346 return NoChange();
1347 }
1348 1338
1349 // We can only use the fast case if @@hasInstance was not used so far. 1339 // Install a code dependency on the {function}s initial map.
1350 if (!isolate()->IsHasInstanceLookupChainIntact()) return NoChange();
1351 dependencies()->AssumePropertyCell(factory()->has_instance_protector());
1352
1353 Handle<Map> initial_map(function->initial_map(), isolate()); 1340 Handle<Map> initial_map(function->initial_map(), isolate());
1354 dependencies()->AssumeInitialMapCantChange(initial_map); 1341 dependencies()->AssumeInitialMapCantChange(initial_map);
1342
1355 Node* prototype = 1343 Node* prototype =
1356 jsgraph()->Constant(handle(initial_map->prototype(), isolate())); 1344 jsgraph()->Constant(handle(initial_map->prototype(), isolate()));
1357 1345
1358 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), object); 1346 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), object);
1359 Node* branch0 = 1347 Node* branch0 =
1360 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control); 1348 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control);
1361 1349
1362 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); 1350 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
1363 Node* etrue0 = effect; 1351 Node* etrue0 = effect;
1364 Node* vtrue0 = jsgraph()->FalseConstant(); 1352 Node* vtrue0 = jsgraph()->FalseConstant();
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1412 1400
1413 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch10); 1401 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch10);
1414 Node* efalse1 = etrue1; 1402 Node* efalse1 = etrue1;
1415 Node* vfalse1; 1403 Node* vfalse1;
1416 { 1404 {
1417 // Slow path, need to call the %HasInPrototypeChain runtime function. 1405 // Slow path, need to call the %HasInPrototypeChain runtime function.
1418 vfalse1 = efalse1 = graph()->NewNode( 1406 vfalse1 = efalse1 = graph()->NewNode(
1419 javascript()->CallRuntime(Runtime::kHasInPrototypeChain), object, 1407 javascript()->CallRuntime(Runtime::kHasInPrototypeChain), object,
1420 prototype, context, frame_state, efalse1, if_false1); 1408 prototype, context, frame_state, efalse1, if_false1);
1421 if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1); 1409 if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1);
1410
1411 // Replace any potential IfException on {node} to catch exceptions
1412 // from this %HasInPrototypeChain runtime call instead.
1413 for (Edge edge : node->use_edges()) {
1414 if (edge.from()->opcode() == IrOpcode::kIfException) {
1415 edge.UpdateTo(vfalse1);
1416 Revisit(edge.from());
1417 }
1418 }
1422 } 1419 }
1423 1420
1424 // Load the {object} prototype. 1421 // Load the {object} prototype.
1425 Node* object_prototype = effect = graph()->NewNode( 1422 Node* object_prototype = effect = graph()->NewNode(
1426 simplified()->LoadField(AccessBuilder::ForMapPrototype()), object_map, 1423 simplified()->LoadField(AccessBuilder::ForMapPrototype()), object_map,
1427 effect, control); 1424 effect, control);
1428 1425
1429 // Check if we reached the end of {object}s prototype chain. 1426 // Check if we reached the end of {object}s prototype chain.
1430 Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(), 1427 Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(),
1431 object_prototype, jsgraph()->NullConstant()); 1428 object_prototype, jsgraph()->NullConstant());
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
2191 return ReduceUI32Shift(node, kSigned); 2188 return ReduceUI32Shift(node, kSigned);
2192 case IrOpcode::kJSShiftRightLogical: 2189 case IrOpcode::kJSShiftRightLogical:
2193 return ReduceUI32Shift(node, kUnsigned); 2190 return ReduceUI32Shift(node, kUnsigned);
2194 case IrOpcode::kJSAdd: 2191 case IrOpcode::kJSAdd:
2195 return ReduceJSAdd(node); 2192 return ReduceJSAdd(node);
2196 case IrOpcode::kJSSubtract: 2193 case IrOpcode::kJSSubtract:
2197 case IrOpcode::kJSMultiply: 2194 case IrOpcode::kJSMultiply:
2198 case IrOpcode::kJSDivide: 2195 case IrOpcode::kJSDivide:
2199 case IrOpcode::kJSModulus: 2196 case IrOpcode::kJSModulus:
2200 return ReduceNumberBinop(node); 2197 return ReduceNumberBinop(node);
2198 case IrOpcode::kJSOrdinaryHasInstance:
2199 return ReduceJSOrdinaryHasInstance(node);
2201 case IrOpcode::kJSToBoolean: 2200 case IrOpcode::kJSToBoolean:
2202 return ReduceJSToBoolean(node); 2201 return ReduceJSToBoolean(node);
2203 case IrOpcode::kJSToInteger: 2202 case IrOpcode::kJSToInteger:
2204 return ReduceJSToInteger(node); 2203 return ReduceJSToInteger(node);
2205 case IrOpcode::kJSToLength: 2204 case IrOpcode::kJSToLength:
2206 return ReduceJSToLength(node); 2205 return ReduceJSToLength(node);
2207 case IrOpcode::kJSToName: 2206 case IrOpcode::kJSToName:
2208 return ReduceJSToName(node); 2207 return ReduceJSToName(node);
2209 case IrOpcode::kJSToNumber: 2208 case IrOpcode::kJSToNumber:
2210 return ReduceJSToNumber(node); 2209 return ReduceJSToNumber(node);
2211 case IrOpcode::kJSToString: 2210 case IrOpcode::kJSToString:
2212 return ReduceJSToString(node); 2211 return ReduceJSToString(node);
2213 case IrOpcode::kJSToObject: 2212 case IrOpcode::kJSToObject:
2214 return ReduceJSToObject(node); 2213 return ReduceJSToObject(node);
2215 case IrOpcode::kJSTypeOf: 2214 case IrOpcode::kJSTypeOf:
2216 return ReduceJSTypeOf(node); 2215 return ReduceJSTypeOf(node);
2217 case IrOpcode::kJSLoadNamed: 2216 case IrOpcode::kJSLoadNamed:
2218 return ReduceJSLoadNamed(node); 2217 return ReduceJSLoadNamed(node);
2219 case IrOpcode::kJSLoadProperty: 2218 case IrOpcode::kJSLoadProperty:
2220 return ReduceJSLoadProperty(node); 2219 return ReduceJSLoadProperty(node);
2221 case IrOpcode::kJSStoreProperty: 2220 case IrOpcode::kJSStoreProperty:
2222 return ReduceJSStoreProperty(node); 2221 return ReduceJSStoreProperty(node);
2223 case IrOpcode::kJSInstanceOf:
2224 return ReduceJSInstanceOf(node);
2225 case IrOpcode::kJSLoadContext: 2222 case IrOpcode::kJSLoadContext:
2226 return ReduceJSLoadContext(node); 2223 return ReduceJSLoadContext(node);
2227 case IrOpcode::kJSStoreContext: 2224 case IrOpcode::kJSStoreContext:
2228 return ReduceJSStoreContext(node); 2225 return ReduceJSStoreContext(node);
2229 case IrOpcode::kJSLoadModule: 2226 case IrOpcode::kJSLoadModule:
2230 return ReduceJSLoadModule(node); 2227 return ReduceJSLoadModule(node);
2231 case IrOpcode::kJSStoreModule: 2228 case IrOpcode::kJSStoreModule:
2232 return ReduceJSStoreModule(node); 2229 return ReduceJSStoreModule(node);
2233 case IrOpcode::kJSConvertReceiver: 2230 case IrOpcode::kJSConvertReceiver:
2234 return ReduceJSConvertReceiver(node); 2231 return ReduceJSConvertReceiver(node);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
2274 } 2271 }
2275 2272
2276 2273
2277 CompilationDependencies* JSTypedLowering::dependencies() const { 2274 CompilationDependencies* JSTypedLowering::dependencies() const {
2278 return dependencies_; 2275 return dependencies_;
2279 } 2276 }
2280 2277
2281 } // namespace compiler 2278 } // namespace compiler
2282 } // namespace internal 2279 } // namespace internal
2283 } // namespace v8 2280 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698