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 |