diff options
Diffstat (limited to 'deps/v8/src/compiler/bytecode-graph-builder.cc')
-rw-r--r-- | deps/v8/src/compiler/bytecode-graph-builder.cc | 199 |
1 files changed, 96 insertions, 103 deletions
diff --git a/deps/v8/src/compiler/bytecode-graph-builder.cc b/deps/v8/src/compiler/bytecode-graph-builder.cc index dcaed97481..5bb9a8e976 100644 --- a/deps/v8/src/compiler/bytecode-graph-builder.cc +++ b/deps/v8/src/compiler/bytecode-graph-builder.cc @@ -82,9 +82,8 @@ class BytecodeGraphBuilder::Environment : public ZoneObject { bool StateValuesRequireUpdate(Node** state_values, Node** values, int count); void UpdateStateValues(Node** state_values, Node** values, int count); - void UpdateStateValuesWithCache(Node** state_values, Node** values, int count, - const BitVector* liveness, - int liveness_offset); + Node* GetStateValuesFromCache(Node** values, int count, + const BitVector* liveness, int liveness_offset); int RegisterToValuesIndex(interpreter::Register the_register) const; @@ -105,12 +104,22 @@ class BytecodeGraphBuilder::Environment : public ZoneObject { Node* effect_dependency_; NodeVector values_; Node* parameters_state_values_; - Node* registers_state_values_; - Node* accumulator_state_values_; int register_base_; int accumulator_base_; }; +// A helper for creating a temporary sub-environment for simple branches. +struct BytecodeGraphBuilder::SubEnvironment final { + public: + explicit SubEnvironment(BytecodeGraphBuilder* builder) + : builder_(builder), parent_(builder->environment()->Copy()) {} + + ~SubEnvironment() { builder_->set_environment(parent_); } + + private: + BytecodeGraphBuilder* builder_; + BytecodeGraphBuilder::Environment* parent_; +}; // Issues: // - Scopes - intimately tied to AST. Need to eval what is needed. @@ -127,9 +136,7 @@ BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder, control_dependency_(control_dependency), effect_dependency_(control_dependency), values_(builder->local_zone()), - parameters_state_values_(nullptr), - registers_state_values_(nullptr), - accumulator_state_values_(nullptr) { + parameters_state_values_(nullptr) { // The layout of values_ is: // // [receiver] [parameters] [registers] [accumulator] @@ -165,9 +172,7 @@ BytecodeGraphBuilder::Environment::Environment( control_dependency_(other->control_dependency_), effect_dependency_(other->effect_dependency_), values_(other->zone()), - parameters_state_values_(nullptr), - registers_state_values_(nullptr), - accumulator_state_values_(nullptr), + parameters_state_values_(other->parameters_state_values_), register_base_(other->register_base_), accumulator_base_(other->accumulator_base_) { values_ = other->values_; @@ -325,24 +330,6 @@ void BytecodeGraphBuilder::Environment::PrepareForOsrEntry() { if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; values()->at(i) = graph()->NewNode(common()->OsrValue(idx), entry); } - - BailoutId loop_id(builder_->bytecode_iterator().current_offset()); - Node* frame_state = - Checkpoint(loop_id, OutputFrameStateCombine::Ignore(), false, nullptr); - Node* checkpoint = - graph()->NewNode(common()->Checkpoint(), frame_state, entry, entry); - UpdateEffectDependency(checkpoint); - - // Create the OSR guard nodes. - const Operator* guard_op = common()->OsrGuard(OsrGuardType::kUninitialized); - Node* effect = checkpoint; - for (int i = 0; i < size; i++) { - values()->at(i) = effect = - graph()->NewNode(guard_op, values()->at(i), effect, entry); - } - Node* context = effect = graph()->NewNode(guard_op, Context(), effect, entry); - SetContext(context); - UpdateEffectDependency(effect); } bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( @@ -411,10 +398,9 @@ void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, } } -void BytecodeGraphBuilder::Environment::UpdateStateValuesWithCache( - Node** state_values, Node** values, int count, const BitVector* liveness, - int liveness_offset) { - *state_values = builder_->state_values_cache_.GetNodeForValues( +Node* BytecodeGraphBuilder::Environment::GetStateValuesFromCache( + Node** values, int count, const BitVector* liveness, int liveness_offset) { + return builder_->state_values_cache_.GetNodeForValues( values, static_cast<size_t>(count), liveness, liveness_offset); } @@ -424,37 +410,27 @@ Node* BytecodeGraphBuilder::Environment::Checkpoint( if (parameter_count() == register_count()) { // Re-use the state-value cache if the number of local registers happens // to match the parameter count. - UpdateStateValuesWithCache(¶meters_state_values_, &values()->at(0), - parameter_count(), nullptr, 0); + parameters_state_values_ = GetStateValuesFromCache( + &values()->at(0), parameter_count(), nullptr, 0); } else { UpdateStateValues(¶meters_state_values_, &values()->at(0), parameter_count()); } - UpdateStateValuesWithCache(®isters_state_values_, - &values()->at(register_base()), register_count(), - liveness ? &liveness->bit_vector() : nullptr, 0); + Node* registers_state_values = + GetStateValuesFromCache(&values()->at(register_base()), register_count(), + liveness ? &liveness->bit_vector() : nullptr, 0); bool accumulator_is_live = !liveness || liveness->AccumulatorIsLive(); - if (parameter_count() == 1 && accumulator_is_live && - values()->at(accumulator_base()) == values()->at(0)) { - // Re-use the parameter state values if there happens to only be one - // parameter and the accumulator is live and holds that parameter's value. - accumulator_state_values_ = parameters_state_values_; - } else { - // Otherwise, use the state values cache to hopefully re-use local register - // state values (if there is only one local register), or at the very least - // re-use previous accumulator state values. - UpdateStateValuesWithCache( - &accumulator_state_values_, &values()->at(accumulator_base()), 1, - liveness ? &liveness->bit_vector() : nullptr, register_count()); - } + Node* accumulator_state_value = + accumulator_is_live ? values()->at(accumulator_base()) + : builder()->jsgraph()->OptimizedOutConstant(); const Operator* op = common()->FrameState( bailout_id, combine, builder()->frame_state_function_info()); Node* result = graph()->NewNode( - op, parameters_state_values_, registers_state_values_, - accumulator_state_values_, Context(), builder()->GetFunctionClosure(), + op, parameters_state_values_, registers_state_values, + accumulator_state_value, Context(), builder()->GetFunctionClosure(), builder()->graph()->start()); return result; @@ -463,7 +439,7 @@ Node* BytecodeGraphBuilder::Environment::Checkpoint( BytecodeGraphBuilder::BytecodeGraphBuilder( Zone* local_zone, Handle<SharedFunctionInfo> shared_info, Handle<FeedbackVector> feedback_vector, BailoutId osr_ast_id, - JSGraph* jsgraph, float invocation_frequency, + JSGraph* jsgraph, CallFrequency invocation_frequency, SourcePositionTable* source_positions, int inlining_id, JSTypeHintLowering::Flags flags) : local_zone_(local_zone), @@ -482,7 +458,6 @@ BytecodeGraphBuilder::BytecodeGraphBuilder( bytecode_analysis_(nullptr), environment_(nullptr), osr_ast_id_(osr_ast_id), - osr_loop_offset_(-1), merge_environments_(local_zone), exception_handlers_(local_zone), current_exception_handler_(0), @@ -638,7 +613,7 @@ void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) { interpreter::BytecodeArrayIterator iterator(bytecode_array()); set_bytecode_iterator(&iterator); SourcePositionTableIterator source_position_iterator( - bytecode_array()->source_position_table()); + handle(bytecode_array()->SourcePositionTable())); if (FLAG_trace_environment_liveness) { OFStream of(stdout); @@ -907,9 +882,10 @@ BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions( jsgraph()->TheHoleConstant()); NewBranch(check_no_extension); - Environment* true_environment = environment()->Copy(); { + SubEnvironment sub_environment(this); + NewIfFalse(); // If there is an extension, merge into the slow path. if (slow_environment == nullptr) { @@ -920,12 +896,9 @@ BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions( } } - { - set_environment(true_environment); - NewIfTrue(); - // Do nothing on if there is no extension, eventually falling through to - // the fast path. - } + NewIfTrue(); + // Do nothing on if there is no extension, eventually falling through to + // the fast path. } // The depth can be zero, in which case no slow-path checks are built, and the @@ -1398,7 +1371,7 @@ void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode, STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0); VectorSlotPair feedback = CreateVectorSlotPair(slot_id); - float const frequency = ComputeCallFrequency(slot_id); + CallFrequency frequency = ComputeCallFrequency(slot_id); const Operator* call = javascript()->Call(arg_count, frequency, feedback, receiver_mode, tail_call_mode); Node* value = ProcessCallArguments(call, args, static_cast<int>(arg_count)); @@ -1680,7 +1653,7 @@ void BytecodeGraphBuilder::VisitConstruct() { Node* new_target = environment()->LookupAccumulator(); Node* callee = environment()->LookupRegister(callee_reg); - float const frequency = ComputeCallFrequency(slot_id); + CallFrequency frequency = ComputeCallFrequency(slot_id); const Operator* call = javascript()->Construct( static_cast<uint32_t>(reg_count + 2), frequency, feedback); Node* value = @@ -1748,9 +1721,11 @@ CompareOperationHint BytecodeGraphBuilder::GetCompareOperationHint() { return nexus.GetCompareOperationFeedback(); } -float BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const { +CallFrequency BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const { + if (invocation_frequency_.IsUnknown()) return CallFrequency(); CallICNexus nexus(feedback_vector(), feedback_vector()->ToSlot(slot_id)); - return nexus.ComputeCallFrequency() * invocation_frequency_; + return CallFrequency(nexus.ComputeCallFrequency() * + invocation_frequency_.value()); } void BytecodeGraphBuilder::VisitAdd() { @@ -1920,8 +1895,8 @@ void BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) { Node* key = environment()->LookupAccumulator(); Node* object = environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); - Node* node = - NewNode(javascript()->DeleteProperty(language_mode), object, key); + Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode)); + Node* node = NewNode(javascript()->DeleteProperty(), object, key, mode); environment()->BindAccumulator(node, Environment::kAttachFrameState); } @@ -2190,6 +2165,27 @@ void BytecodeGraphBuilder::VisitJumpIfNotUndefinedConstant() { void BytecodeGraphBuilder::VisitJumpLoop() { BuildJump(); } +void BytecodeGraphBuilder::BuildSwitchOnSmi(Node* condition) { + interpreter::JumpTableTargetOffsets offsets = + bytecode_iterator().GetJumpTableTargetOffsets(); + + NewSwitch(condition, offsets.size() + 1); + for (const auto& entry : offsets) { + SubEnvironment sub_environment(this); + NewIfValue(entry.case_value); + MergeIntoSuccessorEnvironment(entry.target_offset); + } + NewIfDefault(); +} + +void BytecodeGraphBuilder::VisitSwitchOnSmiNoFeedback() { + PrepareEagerCheckpoint(); + + Node* acc = environment()->LookupAccumulator(); + Node* acc_smi = NewNode(simplified()->CheckSmi(), acc); + BuildSwitchOnSmi(acc_smi); +} + void BytecodeGraphBuilder::VisitStackCheck() { PrepareEagerCheckpoint(); Node* node = NewNode(javascript()->StackCheck()); @@ -2300,8 +2296,6 @@ void BytecodeGraphBuilder::VisitSuspendGenerator() { } void BytecodeGraphBuilder::VisitResumeGenerator() { - PrepareEagerCheckpoint(); - Node* generator = environment()->LookupRegister( bytecode_iterator().GetRegisterOperand(0)); @@ -2315,7 +2309,7 @@ void BytecodeGraphBuilder::VisitResumeGenerator() { Node* state = NewNode(javascript()->GeneratorRestoreContinuation(), generator); - environment()->BindAccumulator(state, Environment::kAttachFrameState); + environment()->BindAccumulator(state); } void BytecodeGraphBuilder::VisitWide() { @@ -2387,7 +2381,7 @@ void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { DCHECK(bytecode_analysis()->IsLoopHeader(current_offset)); - if (!osr_ast_id_.IsNone() && osr_loop_offset_ == current_offset) { + if (bytecode_analysis()->IsOSREntryPoint(current_offset)) { // For OSR add a special {OsrLoopEntry} node into the current loop header. // It will be turned into a usable entry by the OSR deconstruction. Environment* osr_env = environment()->Copy(); @@ -2397,15 +2391,10 @@ void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { } void BytecodeGraphBuilder::BuildOSRNormalEntryPoint() { - if (!osr_ast_id_.IsNone()) { + if (bytecode_analysis()->HasOSREntryPoint()) { // For OSR add an {OsrNormalEntry} as the the top-level environment start. // It will be replaced with {Dead} by the OSR deconstruction. NewNode(common()->OsrNormalEntry()); - // Translate the offset of the jump instruction to the jump target offset of - // that instruction so that the derived BailoutId points to the loop header. - osr_loop_offset_ = - bytecode_analysis()->GetLoopOffsetFor(osr_ast_id_.ToInt()); - DCHECK(bytecode_analysis()->IsLoopHeader(osr_loop_offset_)); } } @@ -2440,19 +2429,21 @@ void BytecodeGraphBuilder::BuildJump() { void BytecodeGraphBuilder::BuildJumpIf(Node* condition) { NewBranch(condition); - Environment* if_false_environment = environment()->Copy(); - NewIfTrue(); - MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); - set_environment(if_false_environment); + { + SubEnvironment sub_environment(this); + NewIfTrue(); + MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); + } NewIfFalse(); } void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) { NewBranch(condition); - Environment* if_true_environment = environment()->Copy(); - NewIfFalse(); - MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); - set_environment(if_true_environment); + { + SubEnvironment sub_environment(this); + NewIfFalse(); + MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); + } NewIfTrue(); } @@ -2472,24 +2463,26 @@ void BytecodeGraphBuilder::BuildJumpIfNotEqual(Node* comperand) { void BytecodeGraphBuilder::BuildJumpIfFalse() { NewBranch(environment()->LookupAccumulator()); - Environment* if_true_environment = environment()->Copy(); - environment()->BindAccumulator(jsgraph()->FalseConstant()); - NewIfFalse(); - MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); - if_true_environment->BindAccumulator(jsgraph()->TrueConstant()); - set_environment(if_true_environment); + { + SubEnvironment sub_environment(this); + NewIfFalse(); + environment()->BindAccumulator(jsgraph()->FalseConstant()); + MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); + } NewIfTrue(); + environment()->BindAccumulator(jsgraph()->TrueConstant()); } void BytecodeGraphBuilder::BuildJumpIfTrue() { NewBranch(environment()->LookupAccumulator()); - Environment* if_false_environment = environment()->Copy(); - environment()->BindAccumulator(jsgraph()->TrueConstant()); - NewIfTrue(); - MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); - if_false_environment->BindAccumulator(jsgraph()->FalseConstant()); - set_environment(if_false_environment); + { + SubEnvironment sub_environment(this); + NewIfTrue(); + environment()->BindAccumulator(jsgraph()->TrueConstant()); + MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); + } NewIfFalse(); + environment()->BindAccumulator(jsgraph()->FalseConstant()); } void BytecodeGraphBuilder::BuildJumpIfToBooleanTrue() { @@ -2552,7 +2545,7 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op, // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being // pruned from the graph by a soft-deopt. It can happen that a LoadIC that // control-dominates the OSR entry is still in "uninitialized" state. - if (!osr_ast_id_.IsNone()) return nullptr; + if (bytecode_analysis()->HasOSREntryPoint()) return nullptr; Node* effect = environment()->GetEffectDependency(); Node* control = environment()->GetControlDependency(); Reduction early_reduction = type_hint_lowering().ReduceLoadNamedOperation( @@ -2571,7 +2564,7 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadKeyed(const Operator* op, // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being // pruned from the graph by a soft-deopt. It can happen that a LoadIC that // control-dominates the OSR entry is still in "uninitialized" state. - if (!osr_ast_id_.IsNone()) return nullptr; + if (bytecode_analysis()->HasOSREntryPoint()) return nullptr; Node* effect = environment()->GetEffectDependency(); Node* control = environment()->GetControlDependency(); Reduction early_reduction = type_hint_lowering().ReduceLoadKeyedOperation( @@ -2590,7 +2583,7 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedStoreNamed(const Operator* op, // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being // pruned from the graph by a soft-deopt. It can happen that a LoadIC that // control-dominates the OSR entry is still in "uninitialized" state. - if (!osr_ast_id_.IsNone()) return nullptr; + if (bytecode_analysis()->HasOSREntryPoint()) return nullptr; Node* effect = environment()->GetEffectDependency(); Node* control = environment()->GetControlDependency(); Reduction early_reduction = type_hint_lowering().ReduceStoreNamedOperation( @@ -2609,7 +2602,7 @@ Node* BytecodeGraphBuilder::TryBuildSimplifiedStoreKeyed(const Operator* op, // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being // pruned from the graph by a soft-deopt. It can happen that a LoadIC that // control-dominates the OSR entry is still in "uninitialized" state. - if (!osr_ast_id_.IsNone()) return nullptr; + if (bytecode_analysis()->HasOSREntryPoint()) return nullptr; Node* effect = environment()->GetEffectDependency(); Node* control = environment()->GetControlDependency(); Reduction early_reduction = type_hint_lowering().ReduceStoreKeyedOperation( |