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 // Value inputs to the {node} are as follows: |
| 1258 // |
| 1259 // - target, which is Function.prototype.bind JSFunction |
| 1260 // - receiver, which is the [[BoundTargetFunction]] |
| 1261 // - bound_this (optional), which is the [[BoundThis]] |
| 1262 // - and all the remaining value inouts are [[BoundArguments]] |
| 1263 Node* receiver = NodeProperties::GetValueInput(node, 1); |
| 1264 Type* receiver_type = NodeProperties::GetType(receiver); |
| 1265 Node* bound_this = (node->op()->ValueInputCount() < 3) |
| 1266 ? jsgraph()->UndefinedConstant() |
| 1267 : NodeProperties::GetValueInput(node, 2); |
| 1268 Node* effect = NodeProperties::GetEffectInput(node); |
| 1269 Node* control = NodeProperties::GetControlInput(node); |
| 1270 if (receiver_type->IsHeapConstant() && |
| 1271 receiver_type->AsHeapConstant()->Value()->IsJSFunction()) { |
| 1272 Handle<JSFunction> target_function = |
| 1273 Handle<JSFunction>::cast(receiver_type->AsHeapConstant()->Value()); |
| 1274 |
| 1275 // Check that the "length" property on the {target_function} is the |
| 1276 // default JSFunction accessor. |
| 1277 LookupIterator length_lookup(target_function, factory()->length_string(), |
| 1278 target_function, LookupIterator::OWN); |
| 1279 if (length_lookup.state() != LookupIterator::ACCESSOR || |
| 1280 !length_lookup.GetAccessors()->IsAccessorInfo()) { |
| 1281 return NoChange(); |
| 1282 } |
| 1283 |
| 1284 // Check that the "name" property on the {target_function} is the |
| 1285 // default JSFunction accessor. |
| 1286 LookupIterator name_lookup(target_function, factory()->name_string(), |
| 1287 target_function, LookupIterator::OWN); |
| 1288 if (name_lookup.state() != LookupIterator::ACCESSOR || |
| 1289 !name_lookup.GetAccessors()->IsAccessorInfo()) { |
| 1290 return NoChange(); |
| 1291 } |
| 1292 |
| 1293 // Determine the prototype of the {target_function}. |
| 1294 Handle<Object> prototype(target_function->map()->prototype(), isolate()); |
| 1295 |
| 1296 // Setup the map for the JSBoundFunction instance. |
| 1297 Handle<Map> map = target_function->IsConstructor() |
| 1298 ? isolate()->bound_function_with_constructor_map() |
| 1299 : isolate()->bound_function_without_constructor_map(); |
| 1300 if (map->prototype() != *prototype) { |
| 1301 map = Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE); |
| 1302 } |
| 1303 DCHECK_EQ(target_function->IsConstructor(), map->is_constructor()); |
| 1304 |
| 1305 // Create the [[BoundArguments]] for the result. |
| 1306 Node* bound_arguments = jsgraph()->EmptyFixedArrayConstant(); |
| 1307 if (node->op()->ValueInputCount() > 3) { |
| 1308 int const length = node->op()->ValueInputCount() - 3; |
| 1309 effect = graph()->NewNode( |
| 1310 common()->BeginRegion(RegionObservability::kNotObservable), effect); |
| 1311 bound_arguments = effect = graph()->NewNode( |
| 1312 simplified()->Allocate(Type::OtherInternal(), NOT_TENURED), |
| 1313 jsgraph()->Constant(FixedArray::SizeFor(length)), effect, control); |
| 1314 effect = graph()->NewNode( |
| 1315 simplified()->StoreField(AccessBuilder::ForMap()), bound_arguments, |
| 1316 jsgraph()->FixedArrayMapConstant(), effect, control); |
| 1317 effect = graph()->NewNode( |
| 1318 simplified()->StoreField(AccessBuilder::ForFixedArrayLength()), |
| 1319 bound_arguments, jsgraph()->Constant(length), effect, control); |
| 1320 for (int i = 0; i < length; ++i) { |
| 1321 effect = graph()->NewNode( |
| 1322 simplified()->StoreField(AccessBuilder::ForFixedArraySlot(i)), |
| 1323 bound_arguments, NodeProperties::GetValueInput(node, 3 + i), effect, |
| 1324 control); |
| 1325 } |
| 1326 bound_arguments = effect = |
| 1327 graph()->NewNode(common()->FinishRegion(), bound_arguments, effect); |
| 1328 } |
| 1329 |
| 1330 // Create the JSBoundFunction result. |
| 1331 effect = graph()->NewNode( |
| 1332 common()->BeginRegion(RegionObservability::kNotObservable), effect); |
| 1333 Node* value = effect = graph()->NewNode( |
| 1334 simplified()->Allocate(Type::BoundFunction(), NOT_TENURED), |
| 1335 jsgraph()->Constant(JSBoundFunction::kSize), effect, control); |
| 1336 effect = graph()->NewNode(simplified()->StoreField(AccessBuilder::ForMap()), |
| 1337 value, jsgraph()->Constant(map), effect, control); |
| 1338 effect = graph()->NewNode( |
| 1339 simplified()->StoreField(AccessBuilder::ForJSObjectProperties()), value, |
| 1340 jsgraph()->EmptyFixedArrayConstant(), effect, control); |
| 1341 effect = graph()->NewNode( |
| 1342 simplified()->StoreField(AccessBuilder::ForJSObjectElements()), value, |
| 1343 jsgraph()->EmptyFixedArrayConstant(), effect, control); |
| 1344 effect = graph()->NewNode( |
| 1345 simplified()->StoreField( |
| 1346 AccessBuilder::ForJSBoundFunctionBoundTargetFunction()), |
| 1347 value, receiver, effect, control); |
| 1348 effect = graph()->NewNode( |
| 1349 simplified()->StoreField(AccessBuilder::ForJSBoundFunctionBoundThis()), |
| 1350 value, bound_this, effect, control); |
| 1351 effect = |
| 1352 graph()->NewNode(simplified()->StoreField( |
| 1353 AccessBuilder::ForJSBoundFunctionBoundArguments()), |
| 1354 value, bound_arguments, effect, control); |
| 1355 value = effect = graph()->NewNode(common()->FinishRegion(), value, effect); |
| 1356 |
| 1357 ReplaceWithValue(node, value, effect, control); |
| 1358 return Replace(value); |
| 1359 } |
| 1360 return NoChange(); |
| 1361 } |
| 1362 |
1255 // ES6 section 18.2.2 isFinite ( number ) | 1363 // ES6 section 18.2.2 isFinite ( number ) |
1256 Reduction JSBuiltinReducer::ReduceGlobalIsFinite(Node* node) { | 1364 Reduction JSBuiltinReducer::ReduceGlobalIsFinite(Node* node) { |
1257 JSCallReduction r(node); | 1365 JSCallReduction r(node); |
1258 if (r.InputsMatchOne(Type::PlainPrimitive())) { | 1366 if (r.InputsMatchOne(Type::PlainPrimitive())) { |
1259 // isFinite(a:plain-primitive) -> NumberEqual(a', a') | 1367 // isFinite(a:plain-primitive) -> NumberEqual(a', a') |
1260 // where a' = NumberSubtract(ToNumber(a), ToNumber(a)) | 1368 // where a' = NumberSubtract(ToNumber(a), ToNumber(a)) |
1261 Node* input = ToNumber(r.GetJSCallInput(0)); | 1369 Node* input = ToNumber(r.GetJSCallInput(0)); |
1262 Node* diff = graph()->NewNode(simplified()->NumberSubtract(), input, input); | 1370 Node* diff = graph()->NewNode(simplified()->NumberSubtract(), input, input); |
1263 Node* value = graph()->NewNode(simplified()->NumberEqual(), diff, diff); | 1371 Node* value = graph()->NewNode(simplified()->NumberEqual(), diff, diff); |
1264 return Replace(value); | 1372 return Replace(value); |
(...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2319 case kArrayPop: | 2427 case kArrayPop: |
2320 return ReduceArrayPop(node); | 2428 return ReduceArrayPop(node); |
2321 case kArrayPush: | 2429 case kArrayPush: |
2322 return ReduceArrayPush(node); | 2430 return ReduceArrayPush(node); |
2323 case kArrayShift: | 2431 case kArrayShift: |
2324 return ReduceArrayShift(node); | 2432 return ReduceArrayShift(node); |
2325 case kDateNow: | 2433 case kDateNow: |
2326 return ReduceDateNow(node); | 2434 return ReduceDateNow(node); |
2327 case kDateGetTime: | 2435 case kDateGetTime: |
2328 return ReduceDateGetTime(node); | 2436 return ReduceDateGetTime(node); |
| 2437 case kFunctionBind: |
| 2438 return ReduceFunctionBind(node); |
2329 case kGlobalIsFinite: | 2439 case kGlobalIsFinite: |
2330 reduction = ReduceGlobalIsFinite(node); | 2440 reduction = ReduceGlobalIsFinite(node); |
2331 break; | 2441 break; |
2332 case kGlobalIsNaN: | 2442 case kGlobalIsNaN: |
2333 reduction = ReduceGlobalIsNaN(node); | 2443 reduction = ReduceGlobalIsNaN(node); |
2334 break; | 2444 break; |
2335 case kMathAbs: | 2445 case kMathAbs: |
2336 reduction = ReduceMathAbs(node); | 2446 reduction = ReduceMathAbs(node); |
2337 break; | 2447 break; |
2338 case kMathAcos: | 2448 case kMathAcos: |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2529 return jsgraph()->simplified(); | 2639 return jsgraph()->simplified(); |
2530 } | 2640 } |
2531 | 2641 |
2532 JSOperatorBuilder* JSBuiltinReducer::javascript() const { | 2642 JSOperatorBuilder* JSBuiltinReducer::javascript() const { |
2533 return jsgraph()->javascript(); | 2643 return jsgraph()->javascript(); |
2534 } | 2644 } |
2535 | 2645 |
2536 } // namespace compiler | 2646 } // namespace compiler |
2537 } // namespace internal | 2647 } // namespace internal |
2538 } // namespace v8 | 2648 } // namespace v8 |
OLD | NEW |