| 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 1241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1252 node->ReplaceInput(5, control); | 1252 node->ReplaceInput(5, control); |
| 1253 node->TrimInputCount(6); | 1253 node->TrimInputCount(6); |
| 1254 NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access)); | 1254 NodeProperties::ChangeOp(node, simplified()->StoreBuffer(access)); |
| 1255 return Changed(node); | 1255 return Changed(node); |
| 1256 } | 1256 } |
| 1257 } | 1257 } |
| 1258 } | 1258 } |
| 1259 return NoChange(); | 1259 return NoChange(); |
| 1260 } | 1260 } |
| 1261 | 1261 |
| 1262 Reduction JSTypedLowering::ReduceJSInstanceOf(Node* node) { | 1262 Reduction JSTypedLowering::ReduceJSOrdinaryHasInstance(Node* node) { |
| 1263 DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode()); | 1263 DCHECK_EQ(IrOpcode::kJSOrdinaryHasInstance, node->opcode()); |
| 1264 Node* const context = NodeProperties::GetContextInput(node); | 1264 Node* constructor = NodeProperties::GetValueInput(node, 0); |
| 1265 Node* const frame_state = NodeProperties::GetFrameStateInput(node); | 1265 Type* constructor_type = NodeProperties::GetType(constructor); |
| 1266 Node* object = NodeProperties::GetValueInput(node, 1); |
| 1267 Node* context = NodeProperties::GetContextInput(node); |
| 1268 Node* frame_state = NodeProperties::GetFrameStateInput(node); |
| 1269 Node* effect = NodeProperties::GetEffectInput(node); |
| 1270 Node* control = NodeProperties::GetControlInput(node); |
| 1266 | 1271 |
| 1267 // If deoptimization is disabled, we cannot optimize. | 1272 // Check if the {constructor} is a (known) JSFunction. |
| 1268 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 1273 if (!constructor_type->IsConstant() || |
| 1269 | 1274 !constructor_type->AsConstant()->Value()->IsJSFunction()) { |
| 1270 // If we are in a try block, don't optimize since the runtime call | |
| 1271 // in the proxy case can throw. | |
| 1272 if (NodeProperties::IsExceptionalCall(node)) return NoChange(); | |
| 1273 | |
| 1274 JSBinopReduction r(this, node); | |
| 1275 Node* object = r.left(); | |
| 1276 Node* effect = r.effect(); | |
| 1277 Node* control = r.control(); | |
| 1278 | |
| 1279 if (!r.right_type()->IsConstant() || | |
| 1280 !r.right_type()->AsConstant()->Value()->IsJSFunction()) { | |
| 1281 return NoChange(); | 1275 return NoChange(); |
| 1282 } | 1276 } |
| 1277 Handle<JSFunction> function = |
| 1278 Handle<JSFunction>::cast(constructor_type->AsConstant()->Value()); |
| 1283 | 1279 |
| 1284 Handle<JSFunction> function = | 1280 // Check if the {function} already has an initial map (i.e. the |
| 1285 Handle<JSFunction>::cast(r.right_type()->AsConstant()->Value()); | 1281 // {function} has been used as a constructor at least once). |
| 1286 Handle<SharedFunctionInfo> shared(function->shared(), isolate()); | 1282 if (!function->has_initial_map()) return NoChange(); |
| 1287 | 1283 |
| 1288 // Make sure the prototype of {function} is the %FunctionPrototype%, and it | 1284 // Check if the {function}s "prototype" is a JSReceiver. |
| 1289 // already has a meaningful initial map (i.e. we constructed at least one | 1285 if (!function->prototype()->IsJSReceiver()) return NoChange(); |
| 1290 // instance using the constructor {function}). | |
| 1291 if (function->map()->prototype() != function->native_context()->closure() || | |
| 1292 function->map()->has_non_instance_prototype() || | |
| 1293 !function->has_initial_map()) { | |
| 1294 return NoChange(); | |
| 1295 } | |
| 1296 | 1286 |
| 1297 // We can only use the fast case if @@hasInstance was not used so far. | 1287 // Install a code dependency on the {function}s initial map. |
| 1298 if (!isolate()->IsHasInstanceLookupChainIntact()) return NoChange(); | |
| 1299 dependencies()->AssumePropertyCell(factory()->has_instance_protector()); | |
| 1300 | |
| 1301 Handle<Map> initial_map(function->initial_map(), isolate()); | 1288 Handle<Map> initial_map(function->initial_map(), isolate()); |
| 1302 dependencies()->AssumeInitialMapCantChange(initial_map); | 1289 dependencies()->AssumeInitialMapCantChange(initial_map); |
| 1290 |
| 1303 Node* prototype = | 1291 Node* prototype = |
| 1304 jsgraph()->Constant(handle(initial_map->prototype(), isolate())); | 1292 jsgraph()->Constant(handle(initial_map->prototype(), isolate())); |
| 1305 | 1293 |
| 1306 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), object); | 1294 Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), object); |
| 1307 Node* branch0 = | 1295 Node* branch0 = |
| 1308 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control); | 1296 graph()->NewNode(common()->Branch(BranchHint::kFalse), check0, control); |
| 1309 | 1297 |
| 1310 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); | 1298 Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0); |
| 1311 Node* etrue0 = effect; | 1299 Node* etrue0 = effect; |
| 1312 Node* vtrue0 = jsgraph()->FalseConstant(); | 1300 Node* vtrue0 = jsgraph()->FalseConstant(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1360 | 1348 |
| 1361 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch10); | 1349 Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch10); |
| 1362 Node* efalse1 = etrue1; | 1350 Node* efalse1 = etrue1; |
| 1363 Node* vfalse1; | 1351 Node* vfalse1; |
| 1364 { | 1352 { |
| 1365 // Slow path, need to call the %HasInPrototypeChain runtime function. | 1353 // Slow path, need to call the %HasInPrototypeChain runtime function. |
| 1366 vfalse1 = efalse1 = graph()->NewNode( | 1354 vfalse1 = efalse1 = graph()->NewNode( |
| 1367 javascript()->CallRuntime(Runtime::kHasInPrototypeChain), object, | 1355 javascript()->CallRuntime(Runtime::kHasInPrototypeChain), object, |
| 1368 prototype, context, frame_state, efalse1, if_false1); | 1356 prototype, context, frame_state, efalse1, if_false1); |
| 1369 if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1); | 1357 if_false1 = graph()->NewNode(common()->IfSuccess(), vfalse1); |
| 1358 |
| 1359 // Replace any potential IfException on {node} to catch exceptions |
| 1360 // from this %HasInPrototypeChain runtime call instead. |
| 1361 for (Edge edge : node->use_edges()) { |
| 1362 if (edge.from()->opcode() == IrOpcode::kIfException) { |
| 1363 edge.UpdateTo(vfalse1); |
| 1364 Revisit(edge.from()); |
| 1365 } |
| 1366 } |
| 1370 } | 1367 } |
| 1371 | 1368 |
| 1372 // Load the {object} prototype. | 1369 // Load the {object} prototype. |
| 1373 Node* object_prototype = effect = graph()->NewNode( | 1370 Node* object_prototype = effect = graph()->NewNode( |
| 1374 simplified()->LoadField(AccessBuilder::ForMapPrototype()), object_map, | 1371 simplified()->LoadField(AccessBuilder::ForMapPrototype()), object_map, |
| 1375 effect, control); | 1372 effect, control); |
| 1376 | 1373 |
| 1377 // Check if we reached the end of {object}s prototype chain. | 1374 // Check if we reached the end of {object}s prototype chain. |
| 1378 Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(), | 1375 Node* check2 = graph()->NewNode(simplified()->ReferenceEqual(), |
| 1379 object_prototype, jsgraph()->NullConstant()); | 1376 object_prototype, jsgraph()->NullConstant()); |
| (...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2062 return ReduceUI32Shift(node, kSigned); | 2059 return ReduceUI32Shift(node, kSigned); |
| 2063 case IrOpcode::kJSShiftRightLogical: | 2060 case IrOpcode::kJSShiftRightLogical: |
| 2064 return ReduceUI32Shift(node, kUnsigned); | 2061 return ReduceUI32Shift(node, kUnsigned); |
| 2065 case IrOpcode::kJSAdd: | 2062 case IrOpcode::kJSAdd: |
| 2066 return ReduceJSAdd(node); | 2063 return ReduceJSAdd(node); |
| 2067 case IrOpcode::kJSSubtract: | 2064 case IrOpcode::kJSSubtract: |
| 2068 case IrOpcode::kJSMultiply: | 2065 case IrOpcode::kJSMultiply: |
| 2069 case IrOpcode::kJSDivide: | 2066 case IrOpcode::kJSDivide: |
| 2070 case IrOpcode::kJSModulus: | 2067 case IrOpcode::kJSModulus: |
| 2071 return ReduceNumberBinop(node); | 2068 return ReduceNumberBinop(node); |
| 2069 case IrOpcode::kJSOrdinaryHasInstance: |
| 2070 return ReduceJSOrdinaryHasInstance(node); |
| 2072 case IrOpcode::kJSToBoolean: | 2071 case IrOpcode::kJSToBoolean: |
| 2073 return ReduceJSToBoolean(node); | 2072 return ReduceJSToBoolean(node); |
| 2074 case IrOpcode::kJSToInteger: | 2073 case IrOpcode::kJSToInteger: |
| 2075 return ReduceJSToInteger(node); | 2074 return ReduceJSToInteger(node); |
| 2076 case IrOpcode::kJSToLength: | 2075 case IrOpcode::kJSToLength: |
| 2077 return ReduceJSToLength(node); | 2076 return ReduceJSToLength(node); |
| 2078 case IrOpcode::kJSToNumber: | 2077 case IrOpcode::kJSToNumber: |
| 2079 return ReduceJSToNumber(node); | 2078 return ReduceJSToNumber(node); |
| 2080 case IrOpcode::kJSToString: | 2079 case IrOpcode::kJSToString: |
| 2081 return ReduceJSToString(node); | 2080 return ReduceJSToString(node); |
| 2082 case IrOpcode::kJSToObject: | 2081 case IrOpcode::kJSToObject: |
| 2083 return ReduceJSToObject(node); | 2082 return ReduceJSToObject(node); |
| 2084 case IrOpcode::kJSLoadNamed: | 2083 case IrOpcode::kJSLoadNamed: |
| 2085 return ReduceJSLoadNamed(node); | 2084 return ReduceJSLoadNamed(node); |
| 2086 case IrOpcode::kJSLoadProperty: | 2085 case IrOpcode::kJSLoadProperty: |
| 2087 return ReduceJSLoadProperty(node); | 2086 return ReduceJSLoadProperty(node); |
| 2088 case IrOpcode::kJSStoreProperty: | 2087 case IrOpcode::kJSStoreProperty: |
| 2089 return ReduceJSStoreProperty(node); | 2088 return ReduceJSStoreProperty(node); |
| 2090 case IrOpcode::kJSInstanceOf: | |
| 2091 return ReduceJSInstanceOf(node); | |
| 2092 case IrOpcode::kJSLoadContext: | 2089 case IrOpcode::kJSLoadContext: |
| 2093 return ReduceJSLoadContext(node); | 2090 return ReduceJSLoadContext(node); |
| 2094 case IrOpcode::kJSStoreContext: | 2091 case IrOpcode::kJSStoreContext: |
| 2095 return ReduceJSStoreContext(node); | 2092 return ReduceJSStoreContext(node); |
| 2096 case IrOpcode::kJSConvertReceiver: | 2093 case IrOpcode::kJSConvertReceiver: |
| 2097 return ReduceJSConvertReceiver(node); | 2094 return ReduceJSConvertReceiver(node); |
| 2098 case IrOpcode::kJSCallConstruct: | 2095 case IrOpcode::kJSCallConstruct: |
| 2099 return ReduceJSCallConstruct(node); | 2096 return ReduceJSCallConstruct(node); |
| 2100 case IrOpcode::kJSCallFunction: | 2097 case IrOpcode::kJSCallFunction: |
| 2101 return ReduceJSCallFunction(node); | 2098 return ReduceJSCallFunction(node); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2137 } | 2134 } |
| 2138 | 2135 |
| 2139 | 2136 |
| 2140 CompilationDependencies* JSTypedLowering::dependencies() const { | 2137 CompilationDependencies* JSTypedLowering::dependencies() const { |
| 2141 return dependencies_; | 2138 return dependencies_; |
| 2142 } | 2139 } |
| 2143 | 2140 |
| 2144 } // namespace compiler | 2141 } // namespace compiler |
| 2145 } // namespace internal | 2142 } // namespace internal |
| 2146 } // namespace v8 | 2143 } // namespace v8 |
| OLD | NEW |