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/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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |