 Chromium Code Reviews
 Chromium Code Reviews Issue 2916063002:
  [turbofan] Optimize Function.prototype.bind for the common case.  (Closed)
    
  
    Issue 2916063002:
  [turbofan] Optimize Function.prototype.bind for the common case.  (Closed) 
  | 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-builtin-reducer.h" | 5 #include "src/compiler/js-builtin-reducer.h" | 
| 6 | 6 | 
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.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 1234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1245 if (HasInstanceTypeWitness(receiver, effect, JS_DATE_TYPE)) { | 1245 if (HasInstanceTypeWitness(receiver, effect, JS_DATE_TYPE)) { | 
| 1246 Node* value = effect = graph()->NewNode( | 1246 Node* value = effect = graph()->NewNode( | 
| 1247 simplified()->LoadField(AccessBuilder::ForJSDateValue()), receiver, | 1247 simplified()->LoadField(AccessBuilder::ForJSDateValue()), receiver, | 
| 1248 effect, control); | 1248 effect, control); | 
| 1249 ReplaceWithValue(node, value, effect, control); | 1249 ReplaceWithValue(node, value, effect, control); | 
| 1250 return Replace(value); | 1250 return Replace(value); | 
| 1251 } | 1251 } | 
| 1252 return NoChange(); | 1252 return NoChange(); | 
| 1253 } | 1253 } | 
| 1254 | 1254 | 
| 1255 // ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args ) | |
| 1256 Reduction JSBuiltinReducer::ReduceFunctionBind(Node* node) { | |
| 1257 Node* receiver = NodeProperties::GetValueInput(node, 1); | |
| 1258 Type* receiver_type = NodeProperties::GetType(receiver); | |
| 1259 Node* bound_this = (node->op()->ValueInputCount() < 3) | |
| 1260 ? jsgraph()->UndefinedConstant() | |
| 1261 : NodeProperties::GetValueInput(node, 2); | |
| 
Jarin
2017/06/02 08:07:42
Please describe in a comment what is the layout of
 
Benedikt Meurer
2017/06/02 11:58:43
Done.
 | |
| 1262 Node* effect = NodeProperties::GetEffectInput(node); | |
| 1263 Node* control = NodeProperties::GetControlInput(node); | |
| 1264 if (receiver_type->IsHeapConstant() && | |
| 1265 receiver_type->AsHeapConstant()->Value()->IsJSFunction()) { | |
| 1266 Handle<JSFunction> target_function = | |
| 1267 Handle<JSFunction>::cast(receiver_type->AsHeapConstant()->Value()); | |
| 1268 | |
| 1269 // Check that the "length" property on the {target_function} is the | |
| 1270 // default JSFunction accessor. | |
| 1271 LookupIterator length_lookup(target_function, factory()->length_string(), | |
| 1272 target_function, LookupIterator::OWN); | |
| 1273 if (length_lookup.state() != LookupIterator::ACCESSOR || | |
| 1274 !length_lookup.GetAccessors()->IsAccessorInfo()) { | |
| 1275 return NoChange(); | |
| 1276 } | |
| 1277 | |
| 1278 // Check that the "name" property on the {target_function} is the | |
| 1279 // default JSFunction accessor. | |
| 1280 LookupIterator name_lookup(target_function, factory()->name_string(), | |
| 1281 target_function, LookupIterator::OWN); | |
| 1282 if (name_lookup.state() != LookupIterator::ACCESSOR || | |
| 1283 !name_lookup.GetAccessors()->IsAccessorInfo()) { | |
| 1284 return NoChange(); | |
| 1285 } | |
| 1286 | |
| 1287 // Determine the prototype of the {target_function}. | |
| 1288 Handle<Object> prototype(target_function->map()->prototype(), isolate()); | |
| 1289 | |
| 1290 // Setup the map for the JSBoundFunction instance. | |
| 1291 Handle<Map> map = target_function->IsConstructor() | |
| 1292 ? isolate()->bound_function_with_constructor_map() | |
| 1293 : isolate()->bound_function_without_constructor_map(); | |
| 1294 if (map->prototype() != *prototype) { | |
| 1295 map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE); | |
| 1296 } | |
| 1297 DCHECK_EQ(target_function->IsConstructor(), map->is_constructor()); | |
| 1298 | |
| 1299 // Create the [[BoundArguments]] for the result. | |
| 1300 Node* bound_arguments = jsgraph()->EmptyFixedArrayConstant(); | |
| 1301 if (node->op()->ValueInputCount() > 3) { | |
| 1302 int const length = node->op()->ValueInputCount() - 3; | |
| 1303 effect = graph()->NewNode( | |
| 1304 common()->BeginRegion(RegionObservability::kNotObservable), effect); | |
| 1305 bound_arguments = effect = graph()->NewNode( | |
| 1306 simplified()->Allocate(Type::OtherInternal(), NOT_TENURED), | |
| 1307 jsgraph()->Constant(FixedArray::SizeFor(length)), effect, control); | |
| 1308 effect = graph()->NewNode( | |
| 1309 simplified()->StoreField(AccessBuilder::ForMap()), bound_arguments, | |
| 1310 jsgraph()->FixedArrayMapConstant(), effect, control); | |
| 1311 effect = graph()->NewNode( | |
| 1312 simplified()->StoreField(AccessBuilder::ForFixedArrayLength()), | |
| 1313 bound_arguments, jsgraph()->Constant(length), effect, control); | |
| 1314 for (int i = 0; i < length; ++i) { | |
| 1315 effect = graph()->NewNode( | |
| 1316 simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), | |
| 1317 bound_arguments, NodeProperties::GetValueInput(node, 3 + i), effect, | |
| 1318 control); | |
| 1319 } | |
| 1320 bound_arguments = effect = | |
| 1321 graph()->NewNode(common()->FinishRegion(), bound_arguments, effect); | |
| 1322 } | |
| 1323 | |
| 1324 // Create the JSBoundFunction result. | |
| 1325 effect = graph()->NewNode( | |
| 1326 common()->BeginRegion(RegionObservability::kNotObservable), effect); | |
| 1327 Node* value = effect = graph()->NewNode( | |
| 1328 simplified()->Allocate(Type::BoundFunction(), NOT_TENURED), | |
| 1329 jsgraph()->Constant(JSBoundFunction::kSize), effect, control); | |
| 1330 effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), | |
| 1331 value, jsgraph()->Constant(map), effect, control); | |
| 1332 effect = graph()->NewNode( | |
| 1333 simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value, | |
| 1334 jsgraph()->EmptyFixedArrayConstant(), effect, control); | |
| 1335 effect = graph()->NewNode( | |
| 1336 simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value, | |
| 1337 jsgraph()->EmptyFixedArrayConstant(), effect, control); | |
| 1338 effect = graph()->NewNode( | |
| 1339 simplified()->StoreField( | |
| 1340 AccessBuilder::ForJSBoundFunctionBoundTargetFunction()), | |
| 1341 value, receiver, effect, control); | |
| 1342 effect = graph()->NewNode( | |
| 1343 simplified()->StoreField(AccessBuilder::ForJSBoundFunctionBoundThis()), | |
| 1344 value, bound_this, effect, control); | |
| 1345 effect = | |
| 1346 graph()->NewNode(simplified()->StoreField( | |
| 1347 AccessBuilder::ForJSBoundFunctionBoundArguments()), | |
| 1348 value, bound_arguments, effect, control); | |
| 1349 value = effect = graph()->NewNode(common()->FinishRegion(), value, effect); | |
| 1350 | |
| 1351 ReplaceWithValue(node, value, effect, control); | |
| 1352 return Replace(value); | |
| 1353 } | |
| 1354 return NoChange(); | |
| 1355 } | |
| 1356 | |
| 1255 // ES6 section 18.2.2 isFinite ( number ) | 1357 // ES6 section 18.2.2 isFinite ( number ) | 
| 1256 Reduction JSBuiltinReducer::ReduceGlobalIsFinite(Node* node) { | 1358 Reduction JSBuiltinReducer::ReduceGlobalIsFinite(Node* node) { | 
| 1257 JSCallReduction r(node); | 1359 JSCallReduction r(node); | 
| 1258 if (r.InputsMatchOne(Type::PlainPrimitive())) { | 1360 if (r.InputsMatchOne(Type::PlainPrimitive())) { | 
| 1259 // isFinite(a:plain-primitive) -> NumberEqual(a', a') | 1361 // isFinite(a:plain-primitive) -> NumberEqual(a', a') | 
| 1260 // where a' = NumberSubtract(ToNumber(a), ToNumber(a)) | 1362 // where a' = NumberSubtract(ToNumber(a), ToNumber(a)) | 
| 1261 Node* input = ToNumber(r.GetJSCallInput(0)); | 1363 Node* input = ToNumber(r.GetJSCallInput(0)); | 
| 1262 Node* diff = graph()->NewNode(simplified()->NumberSubtract(), input, input); | 1364 Node* diff = graph()->NewNode(simplified()->NumberSubtract(), input, input); | 
| 1263 Node* value = graph()->NewNode(simplified()->NumberEqual(), diff, diff); | 1365 Node* value = graph()->NewNode(simplified()->NumberEqual(), diff, diff); | 
| 1264 return Replace(value); | 1366 return Replace(value); | 
| (...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2319 case kArrayPop: | 2421 case kArrayPop: | 
| 2320 return ReduceArrayPop(node); | 2422 return ReduceArrayPop(node); | 
| 2321 case kArrayPush: | 2423 case kArrayPush: | 
| 2322 return ReduceArrayPush(node); | 2424 return ReduceArrayPush(node); | 
| 2323 case kArrayShift: | 2425 case kArrayShift: | 
| 2324 return ReduceArrayShift(node); | 2426 return ReduceArrayShift(node); | 
| 2325 case kDateNow: | 2427 case kDateNow: | 
| 2326 return ReduceDateNow(node); | 2428 return ReduceDateNow(node); | 
| 2327 case kDateGetTime: | 2429 case kDateGetTime: | 
| 2328 return ReduceDateGetTime(node); | 2430 return ReduceDateGetTime(node); | 
| 2431 case kFunctionBind: | |
| 2432 return ReduceFunctionBind(node); | |
| 2329 case kGlobalIsFinite: | 2433 case kGlobalIsFinite: | 
| 2330 reduction = ReduceGlobalIsFinite(node); | 2434 reduction = ReduceGlobalIsFinite(node); | 
| 2331 break; | 2435 break; | 
| 2332 case kGlobalIsNaN: | 2436 case kGlobalIsNaN: | 
| 2333 reduction = ReduceGlobalIsNaN(node); | 2437 reduction = ReduceGlobalIsNaN(node); | 
| 2334 break; | 2438 break; | 
| 2335 case kMathAbs: | 2439 case kMathAbs: | 
| 2336 reduction = ReduceMathAbs(node); | 2440 reduction = ReduceMathAbs(node); | 
| 2337 break; | 2441 break; | 
| 2338 case kMathAcos: | 2442 case kMathAcos: | 
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2529 return jsgraph()->simplified(); | 2633 return jsgraph()->simplified(); | 
| 2530 } | 2634 } | 
| 2531 | 2635 | 
| 2532 JSOperatorBuilder* JSBuiltinReducer::javascript() const { | 2636 JSOperatorBuilder* JSBuiltinReducer::javascript() const { | 
| 2533 return jsgraph()->javascript(); | 2637 return jsgraph()->javascript(); | 
| 2534 } | 2638 } | 
| 2535 | 2639 | 
| 2536 } // namespace compiler | 2640 } // namespace compiler | 
| 2537 } // namespace internal | 2641 } // namespace internal | 
| 2538 } // namespace v8 | 2642 } // namespace v8 | 
| OLD | NEW |