OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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-call-reducer.h" | 5 #include "src/compiler/js-call-reducer.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
10 #include "src/compiler/access-builder.h" | |
10 #include "src/compiler/js-graph.h" | 11 #include "src/compiler/js-graph.h" |
11 #include "src/compiler/linkage.h" | 12 #include "src/compiler/linkage.h" |
12 #include "src/compiler/node-matchers.h" | 13 #include "src/compiler/node-matchers.h" |
13 #include "src/compiler/simplified-operator.h" | 14 #include "src/compiler/simplified-operator.h" |
14 #include "src/feedback-vector-inl.h" | 15 #include "src/feedback-vector-inl.h" |
15 #include "src/ic/call-optimization.h" | 16 #include "src/ic/call-optimization.h" |
16 #include "src/objects-inl.h" | 17 #include "src/objects-inl.h" |
17 | 18 |
18 namespace v8 { | 19 namespace v8 { |
19 namespace internal { | 20 namespace internal { |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
343 | 344 |
344 // ES6 section 26.1.7 Reflect.getPrototypeOf ( target ) | 345 // ES6 section 26.1.7 Reflect.getPrototypeOf ( target ) |
345 Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) { | 346 Reduction JSCallReducer::ReduceReflectGetPrototypeOf(Node* node) { |
346 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); | 347 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
347 Node* target = (node->op()->ValueInputCount() >= 3) | 348 Node* target = (node->op()->ValueInputCount() >= 3) |
348 ? NodeProperties::GetValueInput(node, 2) | 349 ? NodeProperties::GetValueInput(node, 2) |
349 : jsgraph()->UndefinedConstant(); | 350 : jsgraph()->UndefinedConstant(); |
350 return ReduceObjectGetPrototype(node, target); | 351 return ReduceObjectGetPrototype(node, target); |
351 } | 352 } |
352 | 353 |
354 Reduction JSCallReducer::ReduceArrayForEach(Handle<SharedFunctionInfo> shared, | |
355 Node* node) { | |
356 if (!FLAG_inline_array_builtins) return NoChange(); | |
357 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); | |
358 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node); | |
359 Node* effect = NodeProperties::GetEffectInput(node); | |
360 Node* control = NodeProperties::GetControlInput(node); | |
361 Node* context = NodeProperties::GetContextInput(node); | |
362 CallParameters const& p = CallParametersOf(node->op()); | |
363 | |
364 // Try to determine the {receiver} map. | |
365 Node* receiver = NodeProperties::GetValueInput(node, 1); | |
366 Node* fncallback = node->op()->ValueInputCount() > 2 | |
367 ? NodeProperties::GetValueInput(node, 2) | |
368 : jsgraph()->UndefinedConstant(); | |
369 Node* this_arg = node->op()->ValueInputCount() > 3 | |
370 ? NodeProperties::GetValueInput(node, 3) | |
371 : jsgraph()->UndefinedConstant(); | |
372 ZoneHandleSet<Map> receiver_maps; | |
373 if (!NodeProperties::InferReceiverMaps(receiver, effect, &receiver_maps)) { | |
Benedikt Meurer
2017/05/22 19:29:40
This returns an enum. You only want to deal with r
danno
2017/06/06 12:04:52
Done.
| |
374 return NoChange(); | |
375 } | |
376 if (receiver_maps.size() != 1) return NoChange(); | |
377 Handle<Map> receiver_map(receiver_maps[0]); | |
378 ElementsKind kind = receiver_map->elements_kind(); | |
379 // TODO(danno): Handle holey Smi and Object fast elements kinds and double | |
380 // packed. | |
381 if (!IsFastPackedElementsKind(kind) || IsFastDoubleElementsKind(kind)) { | |
382 return NoChange(); | |
383 } | |
384 | |
385 Node* k = jsgraph()->Constant(0); | |
Jarin
2017/05/24 06:41:22
a.k.a. ZeroConstant()
danno
2017/06/06 12:04:52
Done.
| |
386 | |
387 Node* original_length = graph()->NewNode( | |
388 simplified()->LoadField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)), | |
389 receiver, effect, control); | |
390 | |
391 Node* loop = control = graph()->NewNode(common()->Loop(2), control, control); | |
392 Node* eloop = effect = | |
393 graph()->NewNode(common()->EffectPhi(2), effect, effect, loop); | |
394 Node* vloop = k = graph()->NewNode( | |
395 common()->Phi(MachineRepresentation::kTagged, 2), k, k, loop); | |
396 | |
397 control = loop; | |
398 effect = eloop; | |
399 | |
400 Node* continue_test = | |
401 graph()->NewNode(simplified()->NumberLessThan(), k, original_length); | |
402 Node* continue_branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | |
403 continue_test, control); | |
404 | |
405 Node* if_true = graph()->NewNode(common()->IfTrue(), continue_branch); | |
406 Node* if_false = graph()->NewNode(common()->IfFalse(), continue_branch); | |
407 control = if_true; | |
408 | |
409 std::vector<Node*> checkpoint_params( | |
410 {receiver, fncallback, this_arg, k, original_length}); | |
411 const int stack_parameters = static_cast<int>(checkpoint_params.size()); | |
412 | |
413 Node* frame_state = CreateJavaScriptBuiltinContinuationFrameState( | |
414 jsgraph(), shared, Builtins::kArrayForEachLoopEagerDeoptContinuation, | |
415 node->InputAt(0), context, &checkpoint_params[0], stack_parameters, | |
416 outer_frame_state, ContinuationFrameStateMode::EAGER); | |
417 | |
418 effect = | |
419 graph()->NewNode(common()->Checkpoint(), frame_state, effect, control); | |
420 | |
421 // Make sure the map hasn't changed during the iteration | |
422 Node* orig_map = jsgraph()->HeapConstant(receiver_map); | |
423 Node* array_map = effect = | |
424 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
425 receiver, effect, control); | |
426 Node* check_map = | |
427 graph()->NewNode(simplified()->ReferenceEqual(), array_map, orig_map); | |
428 effect = | |
429 graph()->NewNode(simplified()->CheckIf(), check_map, effect, control); | |
430 | |
431 // Make sure that the access is still in bounds, since the callback could have | |
432 // changed the array's size. | |
433 Node* length = graph()->NewNode( | |
434 simplified()->LoadField(AccessBuilder::ForJSArrayLength(FAST_ELEMENTS)), | |
435 receiver, effect, control); | |
436 k = effect = | |
437 graph()->NewNode(simplified()->CheckBounds(), k, length, effect, control); | |
438 USE(length); | |
Benedikt Meurer
2017/05/22 19:29:40
This is unnecessary.
danno
2017/06/06 12:04:52
Done.
| |
439 | |
440 // Reload the elements pointer before calling the callback, since the previous | |
441 // callback might have resized the array causing the elements buffer to be | |
442 // re-allocated. | |
443 Node* elements = graph()->NewNode( | |
444 simplified()->LoadField(AccessBuilder::ForJSObjectElements()), receiver, | |
445 effect, control); | |
446 | |
447 Node* element = graph()->NewNode( | |
448 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), | |
449 elements, k, effect, control); | |
450 | |
451 Node* next_k = | |
452 graph()->NewNode(simplified()->NumberAdd(), k, jsgraph()->Constant(1)); | |
453 checkpoint_params[3] = next_k; | |
454 frame_state = CreateJavaScriptBuiltinContinuationFrameState( | |
455 jsgraph(), shared, Builtins::kArrayForEachLoopLazyDeoptContinuation, | |
456 node->InputAt(0), context, &checkpoint_params[0], stack_parameters, | |
457 outer_frame_state, ContinuationFrameStateMode::LAZY); | |
458 | |
459 Node* call_back = control = effect = graph()->NewNode( | |
460 javascript()->Call(5, p.frequency()), fncallback, this_arg, element, k, | |
Benedikt Meurer
2017/05/22 19:29:40
This doesn't properly rewire IfException edges. Ca
danno
2017/06/06 12:04:52
Done.
| |
461 receiver, context, frame_state, effect, control); | |
462 USE(call_back); | |
Benedikt Meurer
2017/05/22 19:29:40
You don't seem to need the call_back variable.
danno
2017/06/06 12:04:52
Done.
| |
463 USE(this_arg); | |
Benedikt Meurer
2017/05/22 19:29:40
This is unnecessary.
danno
2017/06/06 12:04:52
Done.
| |
464 | |
465 k = next_k; | |
466 | |
467 loop->ReplaceInput(1, control); | |
468 vloop->ReplaceInput(1, k); | |
469 eloop->ReplaceInput(1, effect); | |
470 | |
471 control = if_false; | |
472 effect = eloop; | |
473 | |
474 NodeProperties::ReplaceUses(node, jsgraph()->UndefinedConstant(), effect, | |
Benedikt Meurer
2017/05/22 19:29:40
Can you use ReplaceWithValue instead of this magic
Michael Starzinger
2017/05/24 13:54:59
+1, otherwise we might run into similar issues as
danno
2017/06/06 12:04:52
Done.
danno
2017/06/06 12:04:52
Done.
| |
475 control); | |
476 | |
477 node->TrimInputCount(0); | |
478 NodeProperties::ChangeOp(node, common()->Dead()); | |
479 return Changed(node); | |
480 } | |
481 | |
353 Reduction JSCallReducer::ReduceCallApiFunction( | 482 Reduction JSCallReducer::ReduceCallApiFunction( |
354 Node* node, Handle<FunctionTemplateInfo> function_template_info) { | 483 Node* node, Handle<FunctionTemplateInfo> function_template_info) { |
355 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); | 484 DCHECK_EQ(IrOpcode::kJSCall, node->opcode()); |
356 CallParameters const& p = CallParametersOf(node->op()); | 485 CallParameters const& p = CallParametersOf(node->op()); |
357 int const argc = static_cast<int>(p.arity()) - 2; | 486 int const argc = static_cast<int>(p.arity()) - 2; |
358 Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined) | 487 Node* receiver = (p.convert_mode() == ConvertReceiverMode::kNullOrUndefined) |
359 ? jsgraph()->HeapConstant(global_proxy()) | 488 ? jsgraph()->HeapConstant(global_proxy()) |
360 : NodeProperties::GetValueInput(node, 1); | 489 : NodeProperties::GetValueInput(node, 1); |
361 Node* effect = NodeProperties::GetEffectInput(node); | 490 Node* effect = NodeProperties::GetEffectInput(node); |
362 | 491 |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
609 case Builtins::kFunctionPrototypeHasInstance: | 738 case Builtins::kFunctionPrototypeHasInstance: |
610 return ReduceFunctionPrototypeHasInstance(node); | 739 return ReduceFunctionPrototypeHasInstance(node); |
611 case Builtins::kNumberConstructor: | 740 case Builtins::kNumberConstructor: |
612 return ReduceNumberConstructor(node); | 741 return ReduceNumberConstructor(node); |
613 case Builtins::kObjectGetPrototypeOf: | 742 case Builtins::kObjectGetPrototypeOf: |
614 return ReduceObjectGetPrototypeOf(node); | 743 return ReduceObjectGetPrototypeOf(node); |
615 case Builtins::kObjectPrototypeGetProto: | 744 case Builtins::kObjectPrototypeGetProto: |
616 return ReduceObjectPrototypeGetProto(node); | 745 return ReduceObjectPrototypeGetProto(node); |
617 case Builtins::kReflectGetPrototypeOf: | 746 case Builtins::kReflectGetPrototypeOf: |
618 return ReduceReflectGetPrototypeOf(node); | 747 return ReduceReflectGetPrototypeOf(node); |
748 case Builtins::kArrayForEach: | |
749 return ReduceArrayForEach(shared, node); | |
619 default: | 750 default: |
620 break; | 751 break; |
621 } | 752 } |
622 | 753 |
623 // Check for the Array constructor. | 754 // Check for the Array constructor. |
624 if (*function == function->native_context()->array_function()) { | 755 if (*function == function->native_context()->array_function()) { |
625 return ReduceArrayConstructor(node); | 756 return ReduceArrayConstructor(node); |
626 } | 757 } |
627 | 758 |
628 if (!FLAG_runtime_stats && shared->IsApiFunction()) { | 759 if (!FLAG_runtime_stats && shared->IsApiFunction()) { |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
892 return jsgraph()->javascript(); | 1023 return jsgraph()->javascript(); |
893 } | 1024 } |
894 | 1025 |
895 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { | 1026 SimplifiedOperatorBuilder* JSCallReducer::simplified() const { |
896 return jsgraph()->simplified(); | 1027 return jsgraph()->simplified(); |
897 } | 1028 } |
898 | 1029 |
899 } // namespace compiler | 1030 } // namespace compiler |
900 } // namespace internal | 1031 } // namespace internal |
901 } // namespace v8 | 1032 } // namespace v8 |
OLD | NEW |