1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/compiler/checkpoint-elimination.h" 6 7 #include "src/compiler/common-operator.h" 8 #include "src/compiler/node-properties.h" 9 10 namespace v8 { 11 namespace internal { 12 namespace compiler { 13 CheckpointElimination(Editor * editor)14CheckpointElimination::CheckpointElimination(Editor* editor) 15 : AdvancedReducer(editor) {} 16 17 namespace { 18 GetFunctionInfo(Node * checkpoint)19FrameStateFunctionInfo const* GetFunctionInfo(Node* checkpoint) { 20 DCHECK_EQ(IrOpcode::kCheckpoint, checkpoint->opcode()); 21 Node* frame_state = NodeProperties::GetFrameStateInput(checkpoint); 22 return frame_state->opcode() == IrOpcode::kFrameState 23 ? FrameStateInfoOf(frame_state->op()).function_info() 24 : nullptr; 25 } 26 27 // The given checkpoint is redundant if it is effect-wise dominated by another 28 // checkpoint of the same origin (*) and there is no observable write in 29 // between. For now we consider a linear effect chain only instead of true 30 // effect-wise dominance. 31 // "Same origin" here refers to the same graph building pass and is expressed as 32 // the identity of the checkpoint's FrameStateFunctionInfo pointer. This 33 // restriction ensures that an eager deopt from an inlined function will resume 34 // the inlined function's bytecode (rather than, say, the call in the caller's 35 // bytecode), which in turn is necessary to ensure that we learn something from 36 // the deopt in the case where an optimized code object for the inlined function 37 // exists. See regress-9945-*.js and v8:9945. IsRedundantCheckpoint(Node * node)38bool IsRedundantCheckpoint(Node* node) { 39 FrameStateFunctionInfo const* function_info = GetFunctionInfo(node); 40 if (function_info == nullptr) return false; 41 Node* effect = NodeProperties::GetEffectInput(node); 42 while (effect->op()->HasProperty(Operator::kNoWrite) && 43 effect->op()->EffectInputCount() == 1) { 44 if (effect->opcode() == IrOpcode::kCheckpoint) { 45 return GetFunctionInfo(effect) == function_info; 46 } 47 effect = NodeProperties::GetEffectInput(effect); 48 } 49 return false; 50 } 51 52 } // namespace 53 ReduceCheckpoint(Node * node)54Reduction CheckpointElimination::ReduceCheckpoint(Node* node) { 55 DCHECK_EQ(IrOpcode::kCheckpoint, node->opcode()); 56 if (IsRedundantCheckpoint(node)) { 57 return Replace(NodeProperties::GetEffectInput(node)); 58 } 59 return NoChange(); 60 } 61 Reduce(Node * node)62Reduction CheckpointElimination::Reduce(Node* node) { 63 DisallowHeapAccess no_heap_access; 64 switch (node->opcode()) { 65 case IrOpcode::kCheckpoint: 66 return ReduceCheckpoint(node); 67 default: 68 break; 69 } 70 return NoChange(); 71 } 72 73 } // namespace compiler 74 } // namespace internal 75 } // namespace v8 76