OLD | NEW |
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/builtins/builtins-utils.h" | 7 #include "src/builtins/builtins-utils.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
10 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
(...skipping 1258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1269 return Changed(node); | 1269 return Changed(node); |
1270 } | 1270 } |
1271 } | 1271 } |
1272 } | 1272 } |
1273 return NoChange(); | 1273 return NoChange(); |
1274 } | 1274 } |
1275 | 1275 |
1276 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) { | 1276 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) { |
1277 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); | 1277 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); |
1278 VectorSlotPair const& feedback = VectorSlotPairOf(node->op()); | 1278 VectorSlotPair const& feedback = VectorSlotPairOf(node->op()); |
| 1279 Node* right = NodeProperties::GetValueInput(node, 1); |
| 1280 Type* right_type = NodeProperties::GetType(right); |
| 1281 Node* effect = NodeProperties::GetEffectInput(node); |
| 1282 Node* control = NodeProperties::GetControlInput(node); |
1279 | 1283 |
1280 // If deoptimization is disabled, we cannot optimize. | 1284 // If deoptimization is disabled, we cannot optimize. |
1281 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 1285 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
1282 | 1286 |
1283 // Make sure we do have feedback for the {node}, and check that the | 1287 // Make sure we do have feedback for the {node}, and check that the |
1284 // {feedback} suggests that we haven't seen any funny inputs in this | 1288 // {feedback} suggests that we haven't seen any funny inputs in this |
1285 // place so far. | 1289 // place so far. |
1286 // TODO(turbofan): We might want to collect the right-hand side map | 1290 // TODO(turbofan): We might want to collect the right-hand side map |
1287 // for instanceof and turn this into some vector based InstanceOfIC. | 1291 // for instanceof and turn this into some vector based InstanceOfIC. |
1288 if (!feedback.IsValid()) return NoChange(); | 1292 if (!feedback.IsValid()) return NoChange(); |
1289 if (feedback.vector()->Get(feedback.slot()) != | 1293 if (feedback.vector()->Get(feedback.slot()) != |
1290 *TypeFeedbackVector::UninitializedSentinel(isolate())) { | 1294 *TypeFeedbackVector::UninitializedSentinel(isolate())) { |
1291 return NoChange(); | 1295 return NoChange(); |
1292 } | 1296 } |
1293 | 1297 |
1294 JSBinopReduction r(this, node); | |
1295 if (!r.right_type()->IsConstant() || | |
1296 !r.right_type()->AsConstant()->Value()->IsJSFunction()) { | |
1297 return NoChange(); | |
1298 } | |
1299 | |
1300 Handle<JSFunction> function = | |
1301 Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value()); | |
1302 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); | |
1303 | |
1304 // Make sure the prototype of {function} is the %FunctionPrototype%, and it | |
1305 // already has a meaningful initial map (i.e. we constructed at least one | |
1306 // instance using the constructor {function}). | |
1307 if (function->map()->prototype() != function->native_context()->closure() || | |
1308 function->map()->has_non_instance_prototype() || | |
1309 !function->has_initial_map()) { | |
1310 return NoChange(); | |
1311 } | |
1312 | |
1313 // We can only use the fast case if @@hasInstance was not used so far. | 1298 // We can only use the fast case if @@hasInstance was not used so far. |
1314 if (!isolate()->IsHasInstanceLookupChainIntact()) return NoChange(); | 1299 if (!isolate()->IsHasInstanceLookupChainIntact()) return NoChange(); |
| 1300 |
| 1301 if (right_type->IsConstant() && |
| 1302 right_type->AsConstant()->Value()->IsJSFunction()) { |
| 1303 Handle<JSFunction> function = |
| 1304 Handle<JSFunction>::cast(right_type->AsConstant()->Value()); |
| 1305 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); |
| 1306 |
| 1307 // Make sure the prototype of {function} is the %FunctionPrototype%, and it |
| 1308 // already has a meaningful initial map (i.e. we constructed at least one |
| 1309 // instance using the constructor {function}). |
| 1310 if (function->map()->prototype() != function->native_context()->closure() || |
| 1311 function->map()->has_non_instance_prototype() || |
| 1312 !function->has_initial_map()) { |
| 1313 return NoChange(); |
| 1314 } |
| 1315 |
| 1316 Handle<Map> initial_map(function->initial_map(), isolate()); |
| 1317 dependencies()->AssumeInitialMapCantChange(initial_map); |
| 1318 Handle<Object> prototype(initial_map->prototype(), isolate()); |
| 1319 right = jsgraph()->Constant(prototype); |
| 1320 } else { |
| 1321 // The {right} hand side must be a HeapObject. |
| 1322 effect = graph()->NewNode(simplified()->CheckHeapObject(), right, effect, |
| 1323 control); |
| 1324 |
| 1325 // TODO(bmeurer): Properly check the right-hand side with above conditions. |
| 1326 right = effect = graph()->NewNode( |
| 1327 simplified()->LoadField( |
| 1328 AccessBuilder::ForJSFunctionPrototypeOrInitialMap()), |
| 1329 right, effect, control); |
| 1330 right = effect = graph()->NewNode( |
| 1331 simplified()->LoadField(AccessBuilder::ForMapPrototype()), |
| 1332 right, effect, control); |
| 1333 } |
| 1334 |
| 1335 // Add the code dependency to protect against @@hasInstance. |
1315 dependencies()->AssumePropertyCell(factory()->has_instance_protector()); | 1336 dependencies()->AssumePropertyCell(factory()->has_instance_protector()); |
1316 | 1337 |
1317 Handle<Map> initial_map(function->initial_map(), isolate()); | 1338 // Morph the {node} into an optimistic prototype chain walk (which just |
1318 dependencies()->AssumeInitialMapCantChange(initial_map); | |
1319 Node* prototype = | |
1320 jsgraph()->Constant(handle(initial_map->prototype(), isolate())); | |
1321 | |
1322 // Morph the {node} into an optimistic prototype chain walk (which just | |
1323 // deopts if it sees anything funny in the prototype chain, i.e. a proxy). | 1339 // deopts if it sees anything funny in the prototype chain, i.e. a proxy). |
1324 RelaxControls(node); | 1340 RelaxControls(node); |
1325 node->ReplaceInput(1, prototype); // prototype | 1341 NodeProperties::ReplaceValueInput(node, right, 1); // prototype |
1326 node->RemoveInput(3); // frame state | 1342 NodeProperties::ReplaceEffectInput(node, effect); // effect |
1327 node->RemoveInput(2); // context | 1343 node->RemoveInput(3); // frame state |
| 1344 node->RemoveInput(2); // context |
1328 NodeProperties::ChangeOp(node, simplified()->CheckHasInPrototypeChain()); | 1345 NodeProperties::ChangeOp(node, simplified()->CheckHasInPrototypeChain()); |
1329 return Changed(node); | 1346 return Changed(node); |
1330 } | 1347 } |
1331 | 1348 |
1332 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { | 1349 Reduction JSTypedLowering::ReduceJSLoadContext(Node* node) { |
1333 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); | 1350 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); |
1334 ContextAccess const& access = ContextAccessOf(node->op()); | 1351 ContextAccess const& access = ContextAccessOf(node->op()); |
1335 Node* effect = NodeProperties::GetEffectInput(node); | 1352 Node* effect = NodeProperties::GetEffectInput(node); |
1336 Node* control = graph()->start(); | 1353 Node* control = graph()->start(); |
1337 for (size_t i = 0; i < access.depth(); ++i) { | 1354 for (size_t i = 0; i < access.depth(); ++i) { |
(...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2046 } | 2063 } |
2047 | 2064 |
2048 | 2065 |
2049 CompilationDependencies* JSTypedLowering::dependencies() const { | 2066 CompilationDependencies* JSTypedLowering::dependencies() const { |
2050 return dependencies_; | 2067 return dependencies_; |
2051 } | 2068 } |
2052 | 2069 |
2053 } // namespace compiler | 2070 } // namespace compiler |
2054 } // namespace internal | 2071 } // namespace internal |
2055 } // namespace v8 | 2072 } // namespace v8 |
OLD | NEW |