diff options
Diffstat (limited to 'deps/v8/src/compiler/bytecode-graph-builder.cc')
-rw-r--r-- | deps/v8/src/compiler/bytecode-graph-builder.cc | 1574 |
1 files changed, 650 insertions, 924 deletions
diff --git a/deps/v8/src/compiler/bytecode-graph-builder.cc b/deps/v8/src/compiler/bytecode-graph-builder.cc index cf0b6ab438..e28c19d844 100644 --- a/deps/v8/src/compiler/bytecode-graph-builder.cc +++ b/deps/v8/src/compiler/bytecode-graph-builder.cc @@ -13,25 +13,108 @@ namespace v8 { namespace internal { namespace compiler { +// The abstract execution environment simulates the content of the interpreter +// register file. The environment performs SSA-renaming of all tracked nodes at +// split and merge points in the control flow. +class BytecodeGraphBuilder::Environment : public ZoneObject { + public: + Environment(BytecodeGraphBuilder* builder, int register_count, + int parameter_count, Node* control_dependency, Node* context); + + int parameter_count() const { return parameter_count_; } + int register_count() const { return register_count_; } + + Node* LookupAccumulator() const; + Node* LookupRegister(interpreter::Register the_register) const; + + void BindAccumulator(Node* node, FrameStateBeforeAndAfter* states = nullptr); + void BindRegister(interpreter::Register the_register, Node* node, + FrameStateBeforeAndAfter* states = nullptr); + void BindRegistersToProjections(interpreter::Register first_reg, Node* node, + FrameStateBeforeAndAfter* states = nullptr); + void RecordAfterState(Node* node, FrameStateBeforeAndAfter* states); + + // Effect dependency tracked by this environment. + Node* GetEffectDependency() { return effect_dependency_; } + void UpdateEffectDependency(Node* dependency) { + effect_dependency_ = dependency; + } + + // Preserve a checkpoint of the environment for the IR graph. Any + // further mutation of the environment will not affect checkpoints. + Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine); + + // Returns true if the state values are up to date with the current + // environment. + bool StateValuesAreUpToDate(int output_poke_offset, int output_poke_count); + + // Control dependency tracked by this environment. + Node* GetControlDependency() const { return control_dependency_; } + void UpdateControlDependency(Node* dependency) { + control_dependency_ = dependency; + } + + Node* Context() const { return context_; } + void SetContext(Node* new_context) { context_ = new_context; } + + Environment* CopyForConditional() const; + Environment* CopyForLoop(); + void Merge(Environment* other); + + private: + explicit Environment(const Environment* copy); + void PrepareForLoop(); + bool StateValuesAreUpToDate(Node** state_values, int offset, int count, + int output_poke_start, int output_poke_end); + bool StateValuesRequireUpdate(Node** state_values, int offset, int count); + void UpdateStateValues(Node** state_values, int offset, int count); + + int RegisterToValuesIndex(interpreter::Register the_register) const; + + Zone* zone() const { return builder_->local_zone(); } + Graph* graph() const { return builder_->graph(); } + CommonOperatorBuilder* common() const { return builder_->common(); } + BytecodeGraphBuilder* builder() const { return builder_; } + const NodeVector* values() const { return &values_; } + NodeVector* values() { return &values_; } + int register_base() const { return register_base_; } + int accumulator_base() const { return accumulator_base_; } + + BytecodeGraphBuilder* builder_; + int register_count_; + int parameter_count_; + Node* context_; + Node* control_dependency_; + Node* effect_dependency_; + NodeVector values_; + Node* parameters_state_values_; + Node* registers_state_values_; + Node* accumulator_state_values_; + int register_base_; + int accumulator_base_; +}; + // Helper for generating frame states for before and after a bytecode. class BytecodeGraphBuilder::FrameStateBeforeAndAfter { public: - FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder, - const interpreter::BytecodeArrayIterator& iterator) + explicit FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder) : builder_(builder), id_after_(BailoutId::None()), added_to_node_(false), + frame_states_unused_(false), output_poke_offset_(0), output_poke_count_(0) { - BailoutId id_before(iterator.current_offset()); + BailoutId id_before(builder->bytecode_iterator().current_offset()); frame_state_before_ = builder_->environment()->Checkpoint( id_before, OutputFrameStateCombine::Ignore()); - id_after_ = BailoutId(id_before.ToInt() + iterator.current_bytecode_size()); + id_after_ = BailoutId(id_before.ToInt() + + builder->bytecode_iterator().current_bytecode_size()); } ~FrameStateBeforeAndAfter() { DCHECK(added_to_node_); - DCHECK(builder_->environment()->StateValuesAreUpToDate(output_poke_offset_, + DCHECK(frame_states_unused_ || + builder_->environment()->StateValuesAreUpToDate(output_poke_offset_, output_poke_count_)); } @@ -62,6 +145,7 @@ class BytecodeGraphBuilder::FrameStateBeforeAndAfter { output_poke_offset_ = static_cast<int>(combine.GetOffsetToPokeAt()); output_poke_count_ = node->op()->ValueOutputCount(); } + frame_states_unused_ = count == 0; added_to_node_ = true; } @@ -70,6 +154,7 @@ class BytecodeGraphBuilder::FrameStateBeforeAndAfter { BailoutId id_after_; bool added_to_node_; + bool frame_states_unused_; int output_poke_offset_; int output_poke_count_; }; @@ -155,8 +240,8 @@ Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { Node* BytecodeGraphBuilder::Environment::LookupRegister( interpreter::Register the_register) const { - if (the_register.is_function_context()) { - return builder()->GetFunctionContext(); + if (the_register.is_current_context()) { + return Context(); } else if (the_register.is_function_closure()) { return builder()->GetFunctionClosure(); } else if (the_register.is_new_target()) { @@ -168,16 +253,6 @@ Node* BytecodeGraphBuilder::Environment::LookupRegister( } -void BytecodeGraphBuilder::Environment::ExchangeRegisters( - interpreter::Register reg0, interpreter::Register reg1) { - int reg0_index = RegisterToValuesIndex(reg0); - int reg1_index = RegisterToValuesIndex(reg1); - Node* saved_reg0_value = values()->at(reg0_index); - values()->at(reg0_index) = values()->at(reg1_index); - values()->at(reg1_index) = saved_reg0_value; -} - - void BytecodeGraphBuilder::Environment::BindAccumulator( Node* node, FrameStateBeforeAndAfter* states) { if (states) { @@ -220,16 +295,6 @@ void BytecodeGraphBuilder::Environment::RecordAfterState( } -bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const { - return GetControlDependency()->opcode() == IrOpcode::kDead; -} - - -void BytecodeGraphBuilder::Environment::MarkAsUnreachable() { - UpdateControlDependency(builder()->jsgraph()->Dead()); -} - - BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::Environment::CopyForLoop() { PrepareForLoop(); @@ -245,11 +310,6 @@ BytecodeGraphBuilder::Environment::CopyForConditional() const { void BytecodeGraphBuilder::Environment::Merge( BytecodeGraphBuilder::Environment* other) { - // Nothing to do if the other environment is dead. - if (other->IsMarkedAsUnreachable()) { - return; - } - // Create a merge of the control dependencies of both environments and update // the current environment's control dependency accordingly. Node* control = builder()->MergeControl(GetControlDependency(), @@ -295,7 +355,7 @@ void BytecodeGraphBuilder::Environment::PrepareForLoop() { bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( Node** state_values, int offset, int count) { - if (!builder()->info()->is_deoptimization_enabled()) { + if (!builder()->deoptimization_enabled_) { return false; } if (*state_values == nullptr) { @@ -325,7 +385,7 @@ void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, Node* BytecodeGraphBuilder::Environment::Checkpoint( BailoutId bailout_id, OutputFrameStateCombine combine) { - if (!builder()->info()->is_deoptimization_enabled()) { + if (!builder()->deoptimization_enabled_) { return builder()->jsgraph()->EmptyFrameState(); } @@ -363,6 +423,7 @@ bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( int output_poke_offset, int output_poke_count) { + if (!builder()->deoptimization_enabled_) return true; // Poke offset is relative to the top of the stack (i.e., the accumulator). int output_poke_start = accumulator_base() - output_poke_offset; int output_poke_end = output_poke_start + output_poke_count; @@ -375,26 +436,27 @@ bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( 1, output_poke_start, output_poke_end); } - BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, - CompilationInfo* compilation_info, + CompilationInfo* info, JSGraph* jsgraph) : local_zone_(local_zone), - info_(compilation_info), jsgraph_(jsgraph), - bytecode_array_(handle(info()->shared_info()->bytecode_array())), + bytecode_array_(handle(info->shared_info()->bytecode_array())), + exception_handler_table_( + handle(HandlerTable::cast(bytecode_array()->handler_table()))), + feedback_vector_(info->feedback_vector()), frame_state_function_info_(common()->CreateFrameStateFunctionInfo( FrameStateType::kInterpretedFunction, bytecode_array()->parameter_count(), - bytecode_array()->register_count(), info()->shared_info(), - CALL_MAINTAINS_NATIVE_CONTEXT)), + bytecode_array()->register_count(), info->shared_info())), + deoptimization_enabled_(info->is_deoptimization_enabled()), merge_environments_(local_zone), - loop_header_environments_(local_zone), + exception_handlers_(local_zone), + current_exception_handler_(0), input_buffer_size_(0), input_buffer_(nullptr), exit_controls_(local_zone) {} - Node* BytecodeGraphBuilder::GetNewTarget() { if (!new_target_.is_set()) { int params = bytecode_array()->parameter_count(); @@ -430,21 +492,6 @@ Node* BytecodeGraphBuilder::GetFunctionClosure() { } -Node* BytecodeGraphBuilder::BuildLoadObjectField(Node* object, int offset) { - return NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()), object, - jsgraph()->IntPtrConstant(offset - kHeapObjectTag)); -} - - -Node* BytecodeGraphBuilder::BuildLoadImmutableObjectField(Node* object, - int offset) { - return graph()->NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()), - object, - jsgraph()->IntPtrConstant(offset - kHeapObjectTag), - graph()->start(), graph()->start()); -} - - Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) { const Operator* op = javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true); @@ -453,30 +500,15 @@ Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) { } -Node* BytecodeGraphBuilder::BuildLoadFeedbackVector() { - if (!feedback_vector_.is_set()) { - Node* closure = GetFunctionClosure(); - Node* shared = BuildLoadImmutableObjectField( - closure, JSFunction::kSharedFunctionInfoOffset); - Node* vector = BuildLoadImmutableObjectField( - shared, SharedFunctionInfo::kFeedbackVectorOffset); - feedback_vector_.set(vector); - } - return feedback_vector_.get(); -} - - VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { - Handle<TypeFeedbackVector> feedback_vector = info()->feedback_vector(); FeedbackVectorSlot slot; if (slot_id >= TypeFeedbackVector::kReservedIndexCount) { - slot = feedback_vector->ToSlot(slot_id); + slot = feedback_vector()->ToSlot(slot_id); } - return VectorSlotPair(feedback_vector, slot); + return VectorSlotPair(feedback_vector(), slot); } - -bool BytecodeGraphBuilder::CreateGraph(bool stack_check) { +bool BytecodeGraphBuilder::CreateGraph() { // Set up the basic structure of the graph. Outputs for {Start} are // the formal parameters (including the receiver) plus context and // closure. @@ -492,7 +524,7 @@ bool BytecodeGraphBuilder::CreateGraph(bool stack_check) { GetFunctionContext()); set_environment(&env); - CreateGraphBody(stack_check); + VisitBytecodes(); // Finish the basic structure of the graph. DCHECK_NE(0u, exit_controls_.size()); @@ -504,20 +536,6 @@ bool BytecodeGraphBuilder::CreateGraph(bool stack_check) { return true; } - -void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) { - // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments - // object setup, this function variable if used, tracing hooks. - - if (stack_check) { - Node* node = NewNode(javascript()->StackCheck()); - PrepareEntryFrameState(node); - } - - VisitBytecodes(); -} - - void BytecodeGraphBuilder::VisitBytecodes() { BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); analysis.Analyze(); @@ -526,14 +544,15 @@ void BytecodeGraphBuilder::VisitBytecodes() { set_bytecode_iterator(&iterator); while (!iterator.done()) { int current_offset = iterator.current_offset(); - if (analysis.is_reachable(current_offset)) { - MergeEnvironmentsOfForwardBranches(current_offset); - BuildLoopHeaderForBackwardBranches(current_offset); + EnterAndExitExceptionHandlers(current_offset); + SwitchToMergeEnvironment(current_offset); + if (environment() != nullptr) { + BuildLoopHeaderEnvironment(current_offset); switch (iterator.current_bytecode()) { #define BYTECODE_CASE(name, ...) \ case interpreter::Bytecode::k##name: \ - Visit##name(iterator); \ + Visit##name(); \ break; BYTECODE_LIST(BYTECODE_CASE) #undef BYTECODE_CODE @@ -543,635 +562,417 @@ void BytecodeGraphBuilder::VisitBytecodes() { } set_branch_analysis(nullptr); set_bytecode_iterator(nullptr); + DCHECK(exception_handlers_.empty()); } - -void BytecodeGraphBuilder::VisitLdaZero( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitLdaZero() { Node* node = jsgraph()->ZeroConstant(); environment()->BindAccumulator(node); } - -void BytecodeGraphBuilder::VisitLdaSmi8( - const interpreter::BytecodeArrayIterator& iterator) { - Node* node = jsgraph()->Constant(iterator.GetImmediateOperand(0)); +void BytecodeGraphBuilder::VisitLdaSmi8() { + Node* node = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); environment()->BindAccumulator(node); } - -void BytecodeGraphBuilder::VisitLdaConstantWide( - const interpreter::BytecodeArrayIterator& iterator) { - Node* node = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0)); +void BytecodeGraphBuilder::VisitLdaConstantWide() { + Node* node = + jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); environment()->BindAccumulator(node); } - -void BytecodeGraphBuilder::VisitLdaConstant( - const interpreter::BytecodeArrayIterator& iterator) { - Node* node = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0)); +void BytecodeGraphBuilder::VisitLdaConstant() { + Node* node = + jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); environment()->BindAccumulator(node); } - -void BytecodeGraphBuilder::VisitLdaUndefined( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitLdaUndefined() { Node* node = jsgraph()->UndefinedConstant(); environment()->BindAccumulator(node); } - -void BytecodeGraphBuilder::VisitLdaNull( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitLdaNull() { Node* node = jsgraph()->NullConstant(); environment()->BindAccumulator(node); } - -void BytecodeGraphBuilder::VisitLdaTheHole( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitLdaTheHole() { Node* node = jsgraph()->TheHoleConstant(); environment()->BindAccumulator(node); } - -void BytecodeGraphBuilder::VisitLdaTrue( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitLdaTrue() { Node* node = jsgraph()->TrueConstant(); environment()->BindAccumulator(node); } - -void BytecodeGraphBuilder::VisitLdaFalse( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitLdaFalse() { Node* node = jsgraph()->FalseConstant(); environment()->BindAccumulator(node); } - -void BytecodeGraphBuilder::VisitLdar( - const interpreter::BytecodeArrayIterator& iterator) { - Node* value = environment()->LookupRegister(iterator.GetRegisterOperand(0)); +void BytecodeGraphBuilder::VisitLdar() { + Node* value = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); environment()->BindAccumulator(value); } - -void BytecodeGraphBuilder::VisitStar( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitStar() { Node* value = environment()->LookupAccumulator(); - environment()->BindRegister(iterator.GetRegisterOperand(0), value); + environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value); } - -void BytecodeGraphBuilder::VisitMov( - const interpreter::BytecodeArrayIterator& iterator) { - Node* value = environment()->LookupRegister(iterator.GetRegisterOperand(0)); - environment()->BindRegister(iterator.GetRegisterOperand(1), value); -} - - -void BytecodeGraphBuilder::VisitExchange( - const interpreter::BytecodeArrayIterator& iterator) { - environment()->ExchangeRegisters(iterator.GetRegisterOperand(0), - iterator.GetRegisterOperand(1)); -} - - -void BytecodeGraphBuilder::VisitExchangeWide( - const interpreter::BytecodeArrayIterator& iterator) { - environment()->ExchangeRegisters(iterator.GetRegisterOperand(0), - iterator.GetRegisterOperand(1)); +void BytecodeGraphBuilder::VisitMov() { + Node* value = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); + environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value); } +void BytecodeGraphBuilder::VisitMovWide() { VisitMov(); } void BytecodeGraphBuilder::BuildLoadGlobal( - const interpreter::BytecodeArrayIterator& iterator, TypeofMode typeof_mode) { - FrameStateBeforeAndAfter states(this, iterator); + FrameStateBeforeAndAfter states(this); Handle<Name> name = - Handle<Name>::cast(iterator.GetConstantForIndexOperand(0)); - VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1)); + Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0)); + VectorSlotPair feedback = + CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1)); const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode); - Node* node = NewNode(op, BuildLoadFeedbackVector()); + Node* node = NewNode(op, GetFunctionClosure()); environment()->BindAccumulator(node, &states); } - -void BytecodeGraphBuilder::VisitLdaGlobalSloppy( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF); -} - - -void BytecodeGraphBuilder::VisitLdaGlobalStrict( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF); -} - - -void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppy( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF); -} - - -void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrict( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF); -} - - -void BytecodeGraphBuilder::VisitLdaGlobalSloppyWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF); +void BytecodeGraphBuilder::VisitLdaGlobal() { + BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF); } - -void BytecodeGraphBuilder::VisitLdaGlobalStrictWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF); +void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() { + BuildLoadGlobal(TypeofMode::INSIDE_TYPEOF); } - -void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppyWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF); +void BytecodeGraphBuilder::VisitLdaGlobalWide() { + BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF); } - -void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrictWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF); +void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofWide() { + BuildLoadGlobal(TypeofMode::INSIDE_TYPEOF); } - -void BytecodeGraphBuilder::BuildStoreGlobal( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildStoreGlobal(LanguageMode language_mode) { + FrameStateBeforeAndAfter states(this); Handle<Name> name = - Handle<Name>::cast(iterator.GetConstantForIndexOperand(0)); - VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1)); + Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0)); + VectorSlotPair feedback = + CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1)); Node* value = environment()->LookupAccumulator(); - const Operator* op = - javascript()->StoreGlobal(language_mode(), name, feedback); - Node* node = NewNode(op, value, BuildLoadFeedbackVector()); + const Operator* op = javascript()->StoreGlobal(language_mode, name, feedback); + Node* node = NewNode(op, value, GetFunctionClosure()); environment()->RecordAfterState(node, &states); } - -void BytecodeGraphBuilder::VisitStaGlobalSloppy( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildStoreGlobal(iterator); +void BytecodeGraphBuilder::VisitStaGlobalSloppy() { + BuildStoreGlobal(LanguageMode::SLOPPY); } - -void BytecodeGraphBuilder::VisitStaGlobalStrict( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildStoreGlobal(iterator); +void BytecodeGraphBuilder::VisitStaGlobalStrict() { + BuildStoreGlobal(LanguageMode::STRICT); } -void BytecodeGraphBuilder::VisitStaGlobalSloppyWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildStoreGlobal(iterator); +void BytecodeGraphBuilder::VisitStaGlobalSloppyWide() { + BuildStoreGlobal(LanguageMode::SLOPPY); } - -void BytecodeGraphBuilder::VisitStaGlobalStrictWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildStoreGlobal(iterator); +void BytecodeGraphBuilder::VisitStaGlobalStrictWide() { + BuildStoreGlobal(LanguageMode::STRICT); } - -void BytecodeGraphBuilder::VisitLdaContextSlot( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitLdaContextSlot() { // TODO(mythria): LoadContextSlots are unrolled by the required depth when // generating bytecode. Hence the value of depth is always 0. Update this // code, when the implementation changes. // TODO(mythria): immutable flag is also set to false. This information is not // available in bytecode array. update this code when the implementation // changes. - const Operator* op = - javascript()->LoadContext(0, iterator.GetIndexOperand(1), false); - Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0)); + const Operator* op = javascript()->LoadContext( + 0, bytecode_iterator().GetIndexOperand(1), false); + Node* context = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); Node* node = NewNode(op, context); environment()->BindAccumulator(node); } +void BytecodeGraphBuilder::VisitLdaContextSlotWide() { VisitLdaContextSlot(); } -void BytecodeGraphBuilder::VisitLdaContextSlotWide( - const interpreter::BytecodeArrayIterator& iterator) { - VisitLdaContextSlot(iterator); -} - - -void BytecodeGraphBuilder::VisitStaContextSlot( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitStaContextSlot() { // TODO(mythria): LoadContextSlots are unrolled by the required depth when // generating bytecode. Hence the value of depth is always 0. Update this // code, when the implementation changes. const Operator* op = - javascript()->StoreContext(0, iterator.GetIndexOperand(1)); - Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0)); + javascript()->StoreContext(0, bytecode_iterator().GetIndexOperand(1)); + Node* context = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); Node* value = environment()->LookupAccumulator(); NewNode(op, context, value); } +void BytecodeGraphBuilder::VisitStaContextSlotWide() { VisitStaContextSlot(); } -void BytecodeGraphBuilder::VisitStaContextSlotWide( - const interpreter::BytecodeArrayIterator& iterator) { - VisitStaContextSlot(iterator); -} - - -void BytecodeGraphBuilder::BuildLdaLookupSlot( - TypeofMode typeof_mode, - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - Handle<String> name = - Handle<String>::cast(iterator.GetConstantForIndexOperand(0)); - const Operator* op = javascript()->LoadDynamic(name, typeof_mode); - Node* value = - NewNode(op, BuildLoadFeedbackVector(), environment()->Context()); +void BytecodeGraphBuilder::BuildLdaLookupSlot(TypeofMode typeof_mode) { + FrameStateBeforeAndAfter states(this); + Node* name = + jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); + const Operator* op = + javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF + ? Runtime::kLoadLookupSlot + : Runtime::kLoadLookupSlotInsideTypeof); + Node* value = NewNode(op, name); environment()->BindAccumulator(value, &states); } - -void BytecodeGraphBuilder::VisitLdaLookupSlot( - const interpreter::BytecodeArrayIterator& iterator) { - BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF, iterator); +void BytecodeGraphBuilder::VisitLdaLookupSlot() { + BuildLdaLookupSlot(TypeofMode::NOT_INSIDE_TYPEOF); } - -void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof( - const interpreter::BytecodeArrayIterator& iterator) { - BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF, iterator); +void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() { + BuildLdaLookupSlot(TypeofMode::INSIDE_TYPEOF); } - -void BytecodeGraphBuilder::BuildStaLookupSlot( - LanguageMode language_mode, - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildStaLookupSlot(LanguageMode language_mode) { + FrameStateBeforeAndAfter states(this); Node* value = environment()->LookupAccumulator(); - Node* name = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0)); - Node* language = jsgraph()->Constant(language_mode); - const Operator* op = javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4); - Node* store = NewNode(op, value, environment()->Context(), name, language); + Node* name = + jsgraph()->Constant(bytecode_iterator().GetConstantForIndexOperand(0)); + const Operator* op = javascript()->CallRuntime( + is_strict(language_mode) ? Runtime::kStoreLookupSlot_Strict + : Runtime::kStoreLookupSlot_Sloppy); + Node* store = NewNode(op, name, value); environment()->BindAccumulator(store, &states); } +void BytecodeGraphBuilder::VisitLdaLookupSlotWide() { VisitLdaLookupSlot(); } -void BytecodeGraphBuilder::VisitLdaLookupSlotWide( - const interpreter::BytecodeArrayIterator& iterator) { - VisitLdaLookupSlot(iterator); -} - - -void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeofWide( - const interpreter::BytecodeArrayIterator& iterator) { - VisitLdaLookupSlotInsideTypeof(iterator); +void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeofWide() { + VisitLdaLookupSlotInsideTypeof(); } - -void BytecodeGraphBuilder::VisitStaLookupSlotSloppy( - const interpreter::BytecodeArrayIterator& iterator) { - BuildStaLookupSlot(LanguageMode::SLOPPY, iterator); +void BytecodeGraphBuilder::VisitStaLookupSlotSloppy() { + BuildStaLookupSlot(LanguageMode::SLOPPY); } - -void BytecodeGraphBuilder::VisitStaLookupSlotStrict( - const interpreter::BytecodeArrayIterator& iterator) { - BuildStaLookupSlot(LanguageMode::STRICT, iterator); +void BytecodeGraphBuilder::VisitStaLookupSlotStrict() { + BuildStaLookupSlot(LanguageMode::STRICT); } - -void BytecodeGraphBuilder::VisitStaLookupSlotSloppyWide( - const interpreter::BytecodeArrayIterator& iterator) { - VisitStaLookupSlotSloppy(iterator); +void BytecodeGraphBuilder::VisitStaLookupSlotSloppyWide() { + VisitStaLookupSlotSloppy(); } - -void BytecodeGraphBuilder::VisitStaLookupSlotStrictWide( - const interpreter::BytecodeArrayIterator& iterator) { - VisitStaLookupSlotStrict(iterator); +void BytecodeGraphBuilder::VisitStaLookupSlotStrictWide() { + VisitStaLookupSlotStrict(); } - -void BytecodeGraphBuilder::BuildNamedLoad( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0)); +void BytecodeGraphBuilder::BuildNamedLoad() { + FrameStateBeforeAndAfter states(this); + Node* object = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); Handle<Name> name = - Handle<Name>::cast(iterator.GetConstantForIndexOperand(1)); - VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2)); + Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1)); + VectorSlotPair feedback = + CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2)); - const Operator* op = javascript()->LoadNamed(language_mode(), name, feedback); - Node* node = NewNode(op, object, BuildLoadFeedbackVector()); + const Operator* op = javascript()->LoadNamed(name, feedback); + Node* node = NewNode(op, object, GetFunctionClosure()); environment()->BindAccumulator(node, &states); } +void BytecodeGraphBuilder::VisitLoadIC() { BuildNamedLoad(); } -void BytecodeGraphBuilder::VisitLoadICSloppy( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildNamedLoad(iterator); -} - - -void BytecodeGraphBuilder::VisitLoadICStrict( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildNamedLoad(iterator); -} - - -void BytecodeGraphBuilder::VisitLoadICSloppyWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildNamedLoad(iterator); -} - +void BytecodeGraphBuilder::VisitLoadICWide() { BuildNamedLoad(); } -void BytecodeGraphBuilder::VisitLoadICStrictWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildNamedLoad(iterator); -} - - -void BytecodeGraphBuilder::BuildKeyedLoad( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildKeyedLoad() { + FrameStateBeforeAndAfter states(this); Node* key = environment()->LookupAccumulator(); - Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0)); - VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1)); + Node* object = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); + VectorSlotPair feedback = + CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1)); - const Operator* op = javascript()->LoadProperty(language_mode(), feedback); - Node* node = NewNode(op, object, key, BuildLoadFeedbackVector()); + const Operator* op = javascript()->LoadProperty(feedback); + Node* node = NewNode(op, object, key, GetFunctionClosure()); environment()->BindAccumulator(node, &states); } +void BytecodeGraphBuilder::VisitKeyedLoadIC() { BuildKeyedLoad(); } -void BytecodeGraphBuilder::VisitKeyedLoadICSloppy( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildKeyedLoad(iterator); -} +void BytecodeGraphBuilder::VisitKeyedLoadICWide() { BuildKeyedLoad(); } - -void BytecodeGraphBuilder::VisitKeyedLoadICStrict( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildKeyedLoad(iterator); -} - - -void BytecodeGraphBuilder::VisitKeyedLoadICSloppyWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildKeyedLoad(iterator); -} - - -void BytecodeGraphBuilder::VisitKeyedLoadICStrictWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildKeyedLoad(iterator); -} - - -void BytecodeGraphBuilder::BuildNamedStore( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildNamedStore(LanguageMode language_mode) { + FrameStateBeforeAndAfter states(this); Node* value = environment()->LookupAccumulator(); - Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0)); + Node* object = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); Handle<Name> name = - Handle<Name>::cast(iterator.GetConstantForIndexOperand(1)); - VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2)); + Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(1)); + VectorSlotPair feedback = + CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2)); - const Operator* op = - javascript()->StoreNamed(language_mode(), name, feedback); - Node* node = NewNode(op, object, value, BuildLoadFeedbackVector()); + const Operator* op = javascript()->StoreNamed(language_mode, name, feedback); + Node* node = NewNode(op, object, value, GetFunctionClosure()); environment()->RecordAfterState(node, &states); } - -void BytecodeGraphBuilder::VisitStoreICSloppy( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildNamedStore(iterator); +void BytecodeGraphBuilder::VisitStoreICSloppy() { + BuildNamedStore(LanguageMode::SLOPPY); } - -void BytecodeGraphBuilder::VisitStoreICStrict( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildNamedStore(iterator); +void BytecodeGraphBuilder::VisitStoreICStrict() { + BuildNamedStore(LanguageMode::STRICT); } - -void BytecodeGraphBuilder::VisitStoreICSloppyWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildNamedStore(iterator); +void BytecodeGraphBuilder::VisitStoreICSloppyWide() { + BuildNamedStore(LanguageMode::SLOPPY); } - -void BytecodeGraphBuilder::VisitStoreICStrictWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildNamedStore(iterator); +void BytecodeGraphBuilder::VisitStoreICStrictWide() { + BuildNamedStore(LanguageMode::STRICT); } - -void BytecodeGraphBuilder::BuildKeyedStore( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildKeyedStore(LanguageMode language_mode) { + FrameStateBeforeAndAfter states(this); Node* value = environment()->LookupAccumulator(); - Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0)); - Node* key = environment()->LookupRegister(iterator.GetRegisterOperand(1)); - VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2)); - - const Operator* op = javascript()->StoreProperty(language_mode(), feedback); - Node* node = NewNode(op, object, key, value, BuildLoadFeedbackVector()); + Node* object = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); + Node* key = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); + VectorSlotPair feedback = + CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2)); + + const Operator* op = javascript()->StoreProperty(language_mode, feedback); + Node* node = NewNode(op, object, key, value, GetFunctionClosure()); environment()->RecordAfterState(node, &states); } - -void BytecodeGraphBuilder::VisitKeyedStoreICSloppy( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildKeyedStore(iterator); +void BytecodeGraphBuilder::VisitKeyedStoreICSloppy() { + BuildKeyedStore(LanguageMode::SLOPPY); } - -void BytecodeGraphBuilder::VisitKeyedStoreICStrict( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildKeyedStore(iterator); +void BytecodeGraphBuilder::VisitKeyedStoreICStrict() { + BuildKeyedStore(LanguageMode::STRICT); } - -void BytecodeGraphBuilder::VisitKeyedStoreICSloppyWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildKeyedStore(iterator); +void BytecodeGraphBuilder::VisitKeyedStoreICSloppyWide() { + BuildKeyedStore(LanguageMode::SLOPPY); } - -void BytecodeGraphBuilder::VisitKeyedStoreICStrictWide( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildKeyedStore(iterator); +void BytecodeGraphBuilder::VisitKeyedStoreICStrictWide() { + BuildKeyedStore(LanguageMode::STRICT); } - -void BytecodeGraphBuilder::VisitPushContext( - const interpreter::BytecodeArrayIterator& iterator) { - Node* context = environment()->LookupAccumulator(); - environment()->BindRegister(iterator.GetRegisterOperand(0), context); - environment()->SetContext(context); +void BytecodeGraphBuilder::VisitPushContext() { + Node* new_context = environment()->LookupAccumulator(); + environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), + environment()->Context()); + environment()->SetContext(new_context); } - -void BytecodeGraphBuilder::VisitPopContext( - const interpreter::BytecodeArrayIterator& iterator) { - Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0)); +void BytecodeGraphBuilder::VisitPopContext() { + Node* context = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); environment()->SetContext(context); } - -void BytecodeGraphBuilder::VisitCreateClosure( - const interpreter::BytecodeArrayIterator& iterator) { - Handle<SharedFunctionInfo> shared_info = - Handle<SharedFunctionInfo>::cast(iterator.GetConstantForIndexOperand(0)); +void BytecodeGraphBuilder::VisitCreateClosure() { + Handle<SharedFunctionInfo> shared_info = Handle<SharedFunctionInfo>::cast( + bytecode_iterator().GetConstantForIndexOperand(0)); PretenureFlag tenured = - iterator.GetImmediateOperand(1) ? TENURED : NOT_TENURED; + bytecode_iterator().GetImmediateOperand(1) ? TENURED : NOT_TENURED; const Operator* op = javascript()->CreateClosure(shared_info, tenured); Node* closure = NewNode(op); environment()->BindAccumulator(closure); } +void BytecodeGraphBuilder::VisitCreateClosureWide() { VisitCreateClosure(); } -void BytecodeGraphBuilder::VisitCreateClosureWide( - const interpreter::BytecodeArrayIterator& iterator) { - VisitCreateClosure(iterator); -} - - -void BytecodeGraphBuilder::BuildCreateArguments( - CreateArgumentsParameters::Type type, - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - const Operator* op = javascript()->CreateArguments(type, 0); +void BytecodeGraphBuilder::BuildCreateArguments(CreateArgumentsType type) { + FrameStateBeforeAndAfter states(this); + const Operator* op = javascript()->CreateArguments(type); Node* object = NewNode(op, GetFunctionClosure()); environment()->BindAccumulator(object, &states); } - -void BytecodeGraphBuilder::VisitCreateMappedArguments( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCreateArguments(CreateArgumentsParameters::kMappedArguments, iterator); +void BytecodeGraphBuilder::VisitCreateMappedArguments() { + BuildCreateArguments(CreateArgumentsType::kMappedArguments); } - -void BytecodeGraphBuilder::VisitCreateUnmappedArguments( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCreateArguments(CreateArgumentsParameters::kUnmappedArguments, iterator); +void BytecodeGraphBuilder::VisitCreateUnmappedArguments() { + BuildCreateArguments(CreateArgumentsType::kUnmappedArguments); } +void BytecodeGraphBuilder::VisitCreateRestParameter() { + BuildCreateArguments(CreateArgumentsType::kRestParameter); +} -void BytecodeGraphBuilder::BuildCreateLiteral( - const Operator* op, const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildCreateLiteral(const Operator* op) { + FrameStateBeforeAndAfter states(this); Node* literal = NewNode(op, GetFunctionClosure()); environment()->BindAccumulator(literal, &states); } - -void BytecodeGraphBuilder::BuildCreateRegExpLiteral( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::BuildCreateRegExpLiteral() { Handle<String> constant_pattern = - Handle<String>::cast(iterator.GetConstantForIndexOperand(0)); - int literal_index = iterator.GetIndexOperand(1); - int literal_flags = iterator.GetImmediateOperand(2); + Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(0)); + int literal_index = bytecode_iterator().GetIndexOperand(1); + int literal_flags = bytecode_iterator().GetImmediateOperand(2); const Operator* op = javascript()->CreateLiteralRegExp( constant_pattern, literal_flags, literal_index); - BuildCreateLiteral(op, iterator); + BuildCreateLiteral(op); } - -void BytecodeGraphBuilder::VisitCreateRegExpLiteral( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCreateRegExpLiteral(iterator); +void BytecodeGraphBuilder::VisitCreateRegExpLiteral() { + BuildCreateRegExpLiteral(); } - -void BytecodeGraphBuilder::VisitCreateRegExpLiteralWide( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCreateRegExpLiteral(iterator); +void BytecodeGraphBuilder::VisitCreateRegExpLiteralWide() { + BuildCreateRegExpLiteral(); } - -void BytecodeGraphBuilder::BuildCreateArrayLiteral( - const interpreter::BytecodeArrayIterator& iterator) { - Handle<FixedArray> constant_elements = - Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0)); - int literal_index = iterator.GetIndexOperand(1); - int literal_flags = iterator.GetImmediateOperand(2); +void BytecodeGraphBuilder::BuildCreateArrayLiteral() { + Handle<FixedArray> constant_elements = Handle<FixedArray>::cast( + bytecode_iterator().GetConstantForIndexOperand(0)); + int literal_index = bytecode_iterator().GetIndexOperand(1); + int literal_flags = bytecode_iterator().GetImmediateOperand(2); const Operator* op = javascript()->CreateLiteralArray( constant_elements, literal_flags, literal_index); - BuildCreateLiteral(op, iterator); + BuildCreateLiteral(op); } - -void BytecodeGraphBuilder::VisitCreateArrayLiteral( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCreateArrayLiteral(iterator); +void BytecodeGraphBuilder::VisitCreateArrayLiteral() { + BuildCreateArrayLiteral(); } - -void BytecodeGraphBuilder::VisitCreateArrayLiteralWide( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCreateArrayLiteral(iterator); +void BytecodeGraphBuilder::VisitCreateArrayLiteralWide() { + BuildCreateArrayLiteral(); } - -void BytecodeGraphBuilder::BuildCreateObjectLiteral( - const interpreter::BytecodeArrayIterator& iterator) { - Handle<FixedArray> constant_properties = - Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0)); - int literal_index = iterator.GetIndexOperand(1); - int literal_flags = iterator.GetImmediateOperand(2); +void BytecodeGraphBuilder::BuildCreateObjectLiteral() { + Handle<FixedArray> constant_properties = Handle<FixedArray>::cast( + bytecode_iterator().GetConstantForIndexOperand(0)); + int literal_index = bytecode_iterator().GetIndexOperand(1); + int literal_flags = bytecode_iterator().GetImmediateOperand(2); const Operator* op = javascript()->CreateLiteralObject( constant_properties, literal_flags, literal_index); - BuildCreateLiteral(op, iterator); + BuildCreateLiteral(op); } - -void BytecodeGraphBuilder::VisitCreateObjectLiteral( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCreateObjectLiteral(iterator); +void BytecodeGraphBuilder::VisitCreateObjectLiteral() { + BuildCreateObjectLiteral(); } - -void BytecodeGraphBuilder::VisitCreateObjectLiteralWide( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCreateObjectLiteral(iterator); +void BytecodeGraphBuilder::VisitCreateObjectLiteralWide() { + BuildCreateObjectLiteral(); } @@ -1179,7 +980,7 @@ Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op, Node* callee, interpreter::Register receiver, size_t arity) { - Node** all = info()->zone()->NewArray<Node*>(static_cast<int>(arity)); + Node** all = local_zone()->NewArray<Node*>(static_cast<int>(arity)); all[0] = callee; all[1] = environment()->LookupRegister(receiver); int receiver_index = receiver.index(); @@ -1191,57 +992,58 @@ Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op, return value; } - -void BytecodeGraphBuilder::BuildCall( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode) { + FrameStateBeforeAndAfter states(this); // TODO(rmcilroy): Set receiver_hint correctly based on whether the receiver // register has been loaded with null / undefined explicitly or we are sure it // is not null / undefined. ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny; - Node* callee = environment()->LookupRegister(iterator.GetRegisterOperand(0)); - interpreter::Register receiver = iterator.GetRegisterOperand(1); - size_t arg_count = iterator.GetCountOperand(2); - VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(3)); + Node* callee = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); + interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); + size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); + VectorSlotPair feedback = + CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(3)); const Operator* call = javascript()->CallFunction( - arg_count + 2, language_mode(), feedback, receiver_hint); - Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2); + arg_count + 1, feedback, receiver_hint, tail_call_mode); + Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1); environment()->BindAccumulator(value, &states); } +void BytecodeGraphBuilder::VisitCall() { BuildCall(TailCallMode::kDisallow); } -void BytecodeGraphBuilder::VisitCall( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCall(iterator); +void BytecodeGraphBuilder::VisitCallWide() { + BuildCall(TailCallMode::kDisallow); } +void BytecodeGraphBuilder::VisitTailCall() { BuildCall(TailCallMode::kAllow); } -void BytecodeGraphBuilder::VisitCallWide( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCall(iterator); +void BytecodeGraphBuilder::VisitTailCallWide() { + BuildCall(TailCallMode::kAllow); } - -void BytecodeGraphBuilder::VisitCallJSRuntime( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - Node* callee = BuildLoadNativeContextField(iterator.GetIndexOperand(0)); - interpreter::Register receiver = iterator.GetRegisterOperand(1); - size_t arg_count = iterator.GetCountOperand(2); +void BytecodeGraphBuilder::BuildCallJSRuntime() { + FrameStateBeforeAndAfter states(this); + Node* callee = + BuildLoadNativeContextField(bytecode_iterator().GetIndexOperand(0)); + interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); + size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); // Create node to perform the JS runtime call. - const Operator* call = - javascript()->CallFunction(arg_count + 2, language_mode()); - Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2); + const Operator* call = javascript()->CallFunction(arg_count + 1); + Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1); environment()->BindAccumulator(value, &states); } +void BytecodeGraphBuilder::VisitCallJSRuntime() { BuildCallJSRuntime(); } + +void BytecodeGraphBuilder::VisitCallJSRuntimeWide() { BuildCallJSRuntime(); } Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments( const Operator* call_runtime_op, interpreter::Register first_arg, size_t arity) { - Node** all = info()->zone()->NewArray<Node*>(arity); + Node** all = local_zone()->NewArray<Node*>(arity); int first_arg_index = first_arg.index(); for (int i = 0; i < static_cast<int>(arity); ++i) { all[i] = environment()->LookupRegister( @@ -1251,14 +1053,12 @@ Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments( return value; } - -void BytecodeGraphBuilder::VisitCallRuntime( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildCallRuntime() { + FrameStateBeforeAndAfter states(this); Runtime::FunctionId functionId = - static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0)); - interpreter::Register first_arg = iterator.GetRegisterOperand(1); - size_t arg_count = iterator.GetCountOperand(2); + static_cast<Runtime::FunctionId>(bytecode_iterator().GetIndexOperand(0)); + interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); + size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); // Create node to perform the runtime call. const Operator* call = javascript()->CallRuntime(functionId, arg_count); @@ -1266,15 +1066,18 @@ void BytecodeGraphBuilder::VisitCallRuntime( environment()->BindAccumulator(value, &states); } +void BytecodeGraphBuilder::VisitCallRuntime() { BuildCallRuntime(); } -void BytecodeGraphBuilder::VisitCallRuntimeForPair( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::VisitCallRuntimeWide() { BuildCallRuntime(); } + +void BytecodeGraphBuilder::BuildCallRuntimeForPair() { + FrameStateBeforeAndAfter states(this); Runtime::FunctionId functionId = - static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0)); - interpreter::Register first_arg = iterator.GetRegisterOperand(1); - size_t arg_count = iterator.GetCountOperand(2); - interpreter::Register first_return = iterator.GetRegisterOperand(3); + static_cast<Runtime::FunctionId>(bytecode_iterator().GetIndexOperand(0)); + interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); + size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); + interpreter::Register first_return = + bytecode_iterator().GetRegisterOperand(3); // Create node to perform the runtime call. const Operator* call = javascript()->CallRuntime(functionId, arg_count); @@ -1282,164 +1085,151 @@ void BytecodeGraphBuilder::VisitCallRuntimeForPair( environment()->BindRegistersToProjections(first_return, return_pair, &states); } +void BytecodeGraphBuilder::VisitCallRuntimeForPair() { + BuildCallRuntimeForPair(); +} + +void BytecodeGraphBuilder::VisitCallRuntimeForPairWide() { + BuildCallRuntimeForPair(); +} Node* BytecodeGraphBuilder::ProcessCallNewArguments( - const Operator* call_new_op, interpreter::Register callee, + const Operator* call_new_op, Node* callee, Node* new_target, interpreter::Register first_arg, size_t arity) { - Node** all = info()->zone()->NewArray<Node*>(arity); - all[0] = environment()->LookupRegister(callee); + Node** all = local_zone()->NewArray<Node*>(arity); + all[0] = new_target; int first_arg_index = first_arg.index(); for (int i = 1; i < static_cast<int>(arity) - 1; ++i) { all[i] = environment()->LookupRegister( interpreter::Register(first_arg_index + i - 1)); } - // Original constructor is the same as the callee. - all[arity - 1] = environment()->LookupRegister(callee); + all[arity - 1] = callee; Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false); return value; } +void BytecodeGraphBuilder::BuildCallConstruct() { + FrameStateBeforeAndAfter states(this); + interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); + interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); + size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); -void BytecodeGraphBuilder::VisitNew( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - interpreter::Register callee = iterator.GetRegisterOperand(0); - interpreter::Register first_arg = iterator.GetRegisterOperand(1); - size_t arg_count = iterator.GetCountOperand(2); - + Node* new_target = environment()->LookupAccumulator(); + Node* callee = environment()->LookupRegister(callee_reg); // TODO(turbofan): Pass the feedback here. const Operator* call = javascript()->CallConstruct( static_cast<int>(arg_count) + 2, VectorSlotPair()); - Node* value = ProcessCallNewArguments(call, callee, first_arg, arg_count + 2); + Node* value = ProcessCallNewArguments(call, callee, new_target, first_arg, + arg_count + 2); environment()->BindAccumulator(value, &states); } +void BytecodeGraphBuilder::VisitNew() { BuildCallConstruct(); } + +void BytecodeGraphBuilder::VisitNewWide() { BuildCallConstruct(); } -void BytecodeGraphBuilder::VisitThrow( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildThrow() { + FrameStateBeforeAndAfter states(this); Node* value = environment()->LookupAccumulator(); - // TODO(mythria): Change to Runtime::kThrow when we have deoptimization - // information support in the interpreter. - NewNode(javascript()->CallRuntime(Runtime::kReThrow, 1), value); - Node* control = NewNode(common()->Throw(), value); - environment()->RecordAfterState(control, &states); - UpdateControlDependencyToLeaveFunction(control); + Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); + environment()->BindAccumulator(call, &states); +} + +void BytecodeGraphBuilder::VisitThrow() { + BuildThrow(); + Node* call = environment()->LookupAccumulator(); + Node* control = NewNode(common()->Throw(), call); + MergeControlToLeaveFunction(control); } +void BytecodeGraphBuilder::VisitReThrow() { + Node* value = environment()->LookupAccumulator(); + Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); + Node* control = NewNode(common()->Throw(), call); + MergeControlToLeaveFunction(control); +} -void BytecodeGraphBuilder::BuildBinaryOp( - const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0)); +void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) { + FrameStateBeforeAndAfter states(this); + Node* left = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); Node* right = environment()->LookupAccumulator(); Node* node = NewNode(js_op, left, right); environment()->BindAccumulator(node, &states); } - -void BytecodeGraphBuilder::VisitAdd( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitAdd() { BinaryOperationHints hints = BinaryOperationHints::Any(); - BuildBinaryOp(javascript()->Add(language_mode(), hints), iterator); + BuildBinaryOp(javascript()->Add(hints)); } - -void BytecodeGraphBuilder::VisitSub( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitSub() { BinaryOperationHints hints = BinaryOperationHints::Any(); - BuildBinaryOp(javascript()->Subtract(language_mode(), hints), iterator); + BuildBinaryOp(javascript()->Subtract(hints)); } - -void BytecodeGraphBuilder::VisitMul( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitMul() { BinaryOperationHints hints = BinaryOperationHints::Any(); - BuildBinaryOp(javascript()->Multiply(language_mode(), hints), iterator); + BuildBinaryOp(javascript()->Multiply(hints)); } - -void BytecodeGraphBuilder::VisitDiv( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitDiv() { BinaryOperationHints hints = BinaryOperationHints::Any(); - BuildBinaryOp(javascript()->Divide(language_mode(), hints), iterator); + BuildBinaryOp(javascript()->Divide(hints)); } - -void BytecodeGraphBuilder::VisitMod( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitMod() { BinaryOperationHints hints = BinaryOperationHints::Any(); - BuildBinaryOp(javascript()->Modulus(language_mode(), hints), iterator); + BuildBinaryOp(javascript()->Modulus(hints)); } - -void BytecodeGraphBuilder::VisitBitwiseOr( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitBitwiseOr() { BinaryOperationHints hints = BinaryOperationHints::Any(); - BuildBinaryOp(javascript()->BitwiseOr(language_mode(), hints), iterator); + BuildBinaryOp(javascript()->BitwiseOr(hints)); } - -void BytecodeGraphBuilder::VisitBitwiseXor( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitBitwiseXor() { BinaryOperationHints hints = BinaryOperationHints::Any(); - BuildBinaryOp(javascript()->BitwiseXor(language_mode(), hints), iterator); + BuildBinaryOp(javascript()->BitwiseXor(hints)); } - -void BytecodeGraphBuilder::VisitBitwiseAnd( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitBitwiseAnd() { BinaryOperationHints hints = BinaryOperationHints::Any(); - BuildBinaryOp(javascript()->BitwiseAnd(language_mode(), hints), iterator); + BuildBinaryOp(javascript()->BitwiseAnd(hints)); } - -void BytecodeGraphBuilder::VisitShiftLeft( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitShiftLeft() { BinaryOperationHints hints = BinaryOperationHints::Any(); - BuildBinaryOp(javascript()->ShiftLeft(language_mode(), hints), iterator); + BuildBinaryOp(javascript()->ShiftLeft(hints)); } - -void BytecodeGraphBuilder::VisitShiftRight( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitShiftRight() { BinaryOperationHints hints = BinaryOperationHints::Any(); - BuildBinaryOp(javascript()->ShiftRight(language_mode(), hints), iterator); + BuildBinaryOp(javascript()->ShiftRight(hints)); } - -void BytecodeGraphBuilder::VisitShiftRightLogical( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitShiftRightLogical() { BinaryOperationHints hints = BinaryOperationHints::Any(); - BuildBinaryOp(javascript()->ShiftRightLogical(language_mode(), hints), - iterator); + BuildBinaryOp(javascript()->ShiftRightLogical(hints)); } - -void BytecodeGraphBuilder::VisitInc( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - const Operator* js_op = - javascript()->Add(language_mode(), BinaryOperationHints::Any()); +void BytecodeGraphBuilder::VisitInc() { + FrameStateBeforeAndAfter states(this); + const Operator* js_op = javascript()->Add(BinaryOperationHints::Any()); Node* node = NewNode(js_op, environment()->LookupAccumulator(), jsgraph()->OneConstant()); environment()->BindAccumulator(node, &states); } - -void BytecodeGraphBuilder::VisitDec( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - const Operator* js_op = - javascript()->Subtract(language_mode(), BinaryOperationHints::Any()); +void BytecodeGraphBuilder::VisitDec() { + FrameStateBeforeAndAfter states(this); + const Operator* js_op = javascript()->Subtract(BinaryOperationHints::Any()); Node* node = NewNode(js_op, environment()->LookupAccumulator(), jsgraph()->OneConstant()); environment()->BindAccumulator(node, &states); } - -void BytecodeGraphBuilder::VisitLogicalNot( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitLogicalNot() { Node* value = NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), environment()->LookupAccumulator()); Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value, @@ -1447,408 +1237,307 @@ void BytecodeGraphBuilder::VisitLogicalNot( environment()->BindAccumulator(node); } - -void BytecodeGraphBuilder::VisitTypeOf( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitTypeOf() { Node* node = NewNode(javascript()->TypeOf(), environment()->LookupAccumulator()); environment()->BindAccumulator(node); } - -void BytecodeGraphBuilder::BuildDelete( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) { + FrameStateBeforeAndAfter states(this); Node* key = environment()->LookupAccumulator(); - Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0)); + Node* object = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); Node* node = - NewNode(javascript()->DeleteProperty(language_mode()), object, key); + NewNode(javascript()->DeleteProperty(language_mode), object, key); environment()->BindAccumulator(node, &states); } - -void BytecodeGraphBuilder::VisitDeletePropertyStrict( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_strict(language_mode())); - BuildDelete(iterator); +void BytecodeGraphBuilder::VisitDeletePropertyStrict() { + BuildDelete(LanguageMode::STRICT); } - -void BytecodeGraphBuilder::VisitDeletePropertySloppy( - const interpreter::BytecodeArrayIterator& iterator) { - DCHECK(is_sloppy(language_mode())); - BuildDelete(iterator); -} - - -void BytecodeGraphBuilder::VisitDeleteLookupSlot( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - Node* name = environment()->LookupAccumulator(); - const Operator* op = javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2); - Node* result = NewNode(op, environment()->Context(), name); - environment()->BindAccumulator(result, &states); +void BytecodeGraphBuilder::VisitDeletePropertySloppy() { + BuildDelete(LanguageMode::SLOPPY); } - -void BytecodeGraphBuilder::BuildCompareOp( - const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0)); +void BytecodeGraphBuilder::BuildCompareOp(const Operator* js_op) { + FrameStateBeforeAndAfter states(this); + Node* left = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); Node* right = environment()->LookupAccumulator(); Node* node = NewNode(js_op, left, right); environment()->BindAccumulator(node, &states); } - -void BytecodeGraphBuilder::VisitTestEqual( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCompareOp(javascript()->Equal(), iterator); +void BytecodeGraphBuilder::VisitTestEqual() { + BuildCompareOp(javascript()->Equal()); } - -void BytecodeGraphBuilder::VisitTestNotEqual( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCompareOp(javascript()->NotEqual(), iterator); +void BytecodeGraphBuilder::VisitTestNotEqual() { + BuildCompareOp(javascript()->NotEqual()); } - -void BytecodeGraphBuilder::VisitTestEqualStrict( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCompareOp(javascript()->StrictEqual(), iterator); +void BytecodeGraphBuilder::VisitTestEqualStrict() { + BuildCompareOp(javascript()->StrictEqual()); } - -void BytecodeGraphBuilder::VisitTestNotEqualStrict( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCompareOp(javascript()->StrictNotEqual(), iterator); +void BytecodeGraphBuilder::VisitTestNotEqualStrict() { + BuildCompareOp(javascript()->StrictNotEqual()); } - -void BytecodeGraphBuilder::VisitTestLessThan( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCompareOp(javascript()->LessThan(language_mode()), iterator); +void BytecodeGraphBuilder::VisitTestLessThan() { + BuildCompareOp(javascript()->LessThan()); } - -void BytecodeGraphBuilder::VisitTestGreaterThan( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCompareOp(javascript()->GreaterThan(language_mode()), iterator); +void BytecodeGraphBuilder::VisitTestGreaterThan() { + BuildCompareOp(javascript()->GreaterThan()); } - -void BytecodeGraphBuilder::VisitTestLessThanOrEqual( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCompareOp(javascript()->LessThanOrEqual(language_mode()), iterator); +void BytecodeGraphBuilder::VisitTestLessThanOrEqual() { + BuildCompareOp(javascript()->LessThanOrEqual()); } - -void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCompareOp(javascript()->GreaterThanOrEqual(language_mode()), iterator); +void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() { + BuildCompareOp(javascript()->GreaterThanOrEqual()); } - -void BytecodeGraphBuilder::VisitTestIn( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCompareOp(javascript()->HasProperty(), iterator); +void BytecodeGraphBuilder::VisitTestIn() { + BuildCompareOp(javascript()->HasProperty()); } - -void BytecodeGraphBuilder::VisitTestInstanceOf( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCompareOp(javascript()->InstanceOf(), iterator); +void BytecodeGraphBuilder::VisitTestInstanceOf() { + BuildCompareOp(javascript()->InstanceOf()); } - -void BytecodeGraphBuilder::BuildCastOperator( - const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) { + FrameStateBeforeAndAfter states(this); Node* node = NewNode(js_op, environment()->LookupAccumulator()); environment()->BindAccumulator(node, &states); } - -void BytecodeGraphBuilder::VisitToName( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCastOperator(javascript()->ToName(), iterator); +void BytecodeGraphBuilder::VisitToName() { + BuildCastOperator(javascript()->ToName()); } - -void BytecodeGraphBuilder::VisitToObject( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCastOperator(javascript()->ToObject(), iterator); -} - - -void BytecodeGraphBuilder::VisitToNumber( - const interpreter::BytecodeArrayIterator& iterator) { - BuildCastOperator(javascript()->ToNumber(), iterator); +void BytecodeGraphBuilder::VisitToObject() { + BuildCastOperator(javascript()->ToObject()); } - -void BytecodeGraphBuilder::VisitJump( - const interpreter::BytecodeArrayIterator& iterator) { - BuildJump(); -} - - -void BytecodeGraphBuilder::VisitJumpConstant( - const interpreter::BytecodeArrayIterator& iterator) { - BuildJump(); +void BytecodeGraphBuilder::VisitToNumber() { + BuildCastOperator(javascript()->ToNumber()); } +void BytecodeGraphBuilder::VisitJump() { BuildJump(); } -void BytecodeGraphBuilder::VisitJumpConstantWide( - const interpreter::BytecodeArrayIterator& iterator) { - BuildJump(); -} +void BytecodeGraphBuilder::VisitJumpConstant() { BuildJump(); } +void BytecodeGraphBuilder::VisitJumpConstantWide() { BuildJump(); } -void BytecodeGraphBuilder::VisitJumpIfTrue( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfTrue() { BuildJumpIfEqual(jsgraph()->TrueConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfTrueConstant( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfTrueConstant() { BuildJumpIfEqual(jsgraph()->TrueConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfTrueConstantWide( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfTrueConstantWide() { BuildJumpIfEqual(jsgraph()->TrueConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfFalse( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfFalse() { BuildJumpIfEqual(jsgraph()->FalseConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfFalseConstant( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfFalseConstant() { BuildJumpIfEqual(jsgraph()->FalseConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfFalseConstantWide( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfFalseConstantWide() { BuildJumpIfEqual(jsgraph()->FalseConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue() { BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant() { BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstantWide( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstantWide() { BuildJumpIfToBooleanEqual(jsgraph()->TrueConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse() { BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant() { BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstantWide( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstantWide() { BuildJumpIfToBooleanEqual(jsgraph()->FalseConstant()); } +void BytecodeGraphBuilder::VisitJumpIfNotHole() { BuildJumpIfNotHole(); } -void BytecodeGraphBuilder::VisitJumpIfNull( - const interpreter::BytecodeArrayIterator& iterator) { - BuildJumpIfEqual(jsgraph()->NullConstant()); +void BytecodeGraphBuilder::VisitJumpIfNotHoleConstant() { + BuildJumpIfNotHole(); } +void BytecodeGraphBuilder::VisitJumpIfNotHoleConstantWide() { + BuildJumpIfNotHole(); +} -void BytecodeGraphBuilder::VisitJumpIfNullConstant( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfNull() { BuildJumpIfEqual(jsgraph()->NullConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfNullConstantWide( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfNullConstant() { BuildJumpIfEqual(jsgraph()->NullConstant()); } +void BytecodeGraphBuilder::VisitJumpIfNullConstantWide() { + BuildJumpIfEqual(jsgraph()->NullConstant()); +} -void BytecodeGraphBuilder::VisitJumpIfUndefined( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfUndefined() { BuildJumpIfEqual(jsgraph()->UndefinedConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() { BuildJumpIfEqual(jsgraph()->UndefinedConstant()); } - -void BytecodeGraphBuilder::VisitJumpIfUndefinedConstantWide( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitJumpIfUndefinedConstantWide() { BuildJumpIfEqual(jsgraph()->UndefinedConstant()); } +void BytecodeGraphBuilder::VisitStackCheck() { + FrameStateBeforeAndAfter states(this); + Node* node = NewNode(javascript()->StackCheck()); + environment()->RecordAfterState(node, &states); +} -void BytecodeGraphBuilder::VisitReturn( - const interpreter::BytecodeArrayIterator& iterator) { +void BytecodeGraphBuilder::VisitReturn() { Node* control = NewNode(common()->Return(), environment()->LookupAccumulator()); - UpdateControlDependencyToLeaveFunction(control); - set_environment(nullptr); + MergeControlToLeaveFunction(control); } +void BytecodeGraphBuilder::VisitDebugger() { + FrameStateBeforeAndAfter states(this); + Node* call = + NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); + environment()->BindAccumulator(call, &states); +} -void BytecodeGraphBuilder::VisitForInPrepare( - const interpreter::BytecodeArrayIterator& iterator) { - Node* prepare = nullptr; - { - FrameStateBeforeAndAfter states(this, iterator); - Node* receiver = environment()->LookupAccumulator(); - prepare = NewNode(javascript()->ForInPrepare(), receiver); - environment()->RecordAfterState(prepare, &states); - } - // Project cache_type, cache_array, cache_length into register - // operands 1, 2, 3. - for (int i = 0; i < 3; i++) { - environment()->BindRegister(iterator.GetRegisterOperand(i), - NewNode(common()->Projection(i), prepare)); - } +// We cannot create a graph from the debugger copy of the bytecode array. +#define DEBUG_BREAK(Name, ...) \ + void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); } +DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK); +#undef DEBUG_BREAK + +void BytecodeGraphBuilder::BuildForInPrepare() { + FrameStateBeforeAndAfter states(this); + Node* receiver = environment()->LookupAccumulator(); + Node* prepare = NewNode(javascript()->ForInPrepare(), receiver); + environment()->BindRegistersToProjections( + bytecode_iterator().GetRegisterOperand(0), prepare, &states); } +void BytecodeGraphBuilder::VisitForInPrepare() { BuildForInPrepare(); } -void BytecodeGraphBuilder::VisitForInDone( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(0)); +void BytecodeGraphBuilder::VisitForInPrepareWide() { BuildForInPrepare(); } + +void BytecodeGraphBuilder::VisitForInDone() { + FrameStateBeforeAndAfter states(this); + Node* index = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); Node* cache_length = - environment()->LookupRegister(iterator.GetRegisterOperand(1)); + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length); environment()->BindAccumulator(exit_cond, &states); } - -void BytecodeGraphBuilder::VisitForInNext( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); +void BytecodeGraphBuilder::BuildForInNext() { + FrameStateBeforeAndAfter states(this); Node* receiver = - environment()->LookupRegister(iterator.GetRegisterOperand(0)); - Node* cache_type = - environment()->LookupRegister(iterator.GetRegisterOperand(1)); - Node* cache_array = - environment()->LookupRegister(iterator.GetRegisterOperand(2)); - Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(3)); + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); + Node* index = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); + int catch_reg_pair_index = bytecode_iterator().GetRegisterOperand(2).index(); + Node* cache_type = environment()->LookupRegister( + interpreter::Register(catch_reg_pair_index)); + Node* cache_array = environment()->LookupRegister( + interpreter::Register(catch_reg_pair_index + 1)); + Node* value = NewNode(javascript()->ForInNext(), receiver, cache_array, cache_type, index); environment()->BindAccumulator(value, &states); } +void BytecodeGraphBuilder::VisitForInNext() { BuildForInNext(); } -void BytecodeGraphBuilder::VisitForInStep( - const interpreter::BytecodeArrayIterator& iterator) { - FrameStateBeforeAndAfter states(this, iterator); - Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(0)); +void BytecodeGraphBuilder::VisitForInNextWide() { BuildForInNext(); } + +void BytecodeGraphBuilder::VisitForInStep() { + FrameStateBeforeAndAfter states(this); + Node* index = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); index = NewNode(javascript()->ForInStep(), index); environment()->BindAccumulator(index, &states); } - -void BytecodeGraphBuilder::MergeEnvironmentsOfBackwardBranches( - int source_offset, int target_offset) { - DCHECK_GE(source_offset, target_offset); - const ZoneVector<int>* branch_sites = - branch_analysis()->BackwardBranchesTargetting(target_offset); - if (branch_sites->back() == source_offset) { - // The set of back branches is complete, merge them. - DCHECK_GE(branch_sites->at(0), target_offset); - Environment* merged = merge_environments_[branch_sites->at(0)]; - for (size_t i = 1; i < branch_sites->size(); i++) { - DCHECK_GE(branch_sites->at(i), target_offset); - merged->Merge(merge_environments_[branch_sites->at(i)]); +void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) { + if (merge_environments_[current_offset] != nullptr) { + if (environment() != nullptr) { + merge_environments_[current_offset]->Merge(environment()); } - // And now merge with loop header environment created when loop - // header was visited. - loop_header_environments_[target_offset]->Merge(merged); + set_environment(merge_environments_[current_offset]); } } - -void BytecodeGraphBuilder::MergeEnvironmentsOfForwardBranches( - int source_offset) { - if (branch_analysis()->forward_branches_target(source_offset)) { - // Merge environments of branches that reach this bytecode. - auto branch_sites = - branch_analysis()->ForwardBranchesTargetting(source_offset); - DCHECK_LT(branch_sites->at(0), source_offset); - Environment* merged = merge_environments_[branch_sites->at(0)]; - for (size_t i = 1; i < branch_sites->size(); i++) { - DCHECK_LT(branch_sites->at(i), source_offset); - merged->Merge(merge_environments_[branch_sites->at(i)]); - } - if (environment()) { - merged->Merge(environment()); - } - set_environment(merged); - } -} - - -void BytecodeGraphBuilder::BuildLoopHeaderForBackwardBranches( - int source_offset) { - if (branch_analysis()->backward_branches_target(source_offset)) { +void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { + if (branch_analysis()->backward_branches_target(current_offset)) { // Add loop header and store a copy so we can connect merged back // edge inputs to the loop header. - loop_header_environments_[source_offset] = environment()->CopyForLoop(); + merge_environments_[current_offset] = environment()->CopyForLoop(); } } - -void BytecodeGraphBuilder::BuildJump(int source_offset, int target_offset) { - DCHECK_NULL(merge_environments_[source_offset]); - merge_environments_[source_offset] = environment(); - if (source_offset >= target_offset) { - MergeEnvironmentsOfBackwardBranches(source_offset, target_offset); +void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { + if (merge_environments_[target_offset] == nullptr) { + // Append merge nodes to the environment. We may merge here with another + // environment. So add a place holder for merge nodes. We may add redundant + // but will be eliminated in a later pass. + // TODO(mstarzinger): Be smarter about this! + NewMerge(); + merge_environments_[target_offset] = environment(); + } else { + merge_environments_[target_offset]->Merge(environment()); } set_environment(nullptr); } +void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { + exit_controls_.push_back(exit); + set_environment(nullptr); +} void BytecodeGraphBuilder::BuildJump() { - int source_offset = bytecode_iterator()->current_offset(); - int target_offset = bytecode_iterator()->GetJumpTargetOffset(); - BuildJump(source_offset, target_offset); + MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); } void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { - int source_offset = bytecode_iterator()->current_offset(); NewBranch(condition); Environment* if_false_environment = environment()->CopyForConditional(); NewIfTrue(); - BuildJump(source_offset, bytecode_iterator()->GetJumpTargetOffset()); + MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); set_environment(if_false_environment); NewIfFalse(); } @@ -1870,6 +1559,15 @@ void BytecodeGraphBuilder::BuildJumpIfToBooleanEqual(Node* comperand) { BuildConditionalJump(condition); } +void BytecodeGraphBuilder::BuildJumpIfNotHole() { + Node* accumulator = environment()->LookupAccumulator(); + Node* condition = NewNode(javascript()->StrictEqual(), accumulator, + jsgraph()->TheHoleConstant()); + Node* node = + NewNode(common()->Select(MachineRepresentation::kTagged), condition, + jsgraph()->FalseConstant(), jsgraph()->TrueConstant()); + BuildConditionalJump(node); +} Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { if (size > input_buffer_size_) { @@ -1880,16 +1578,31 @@ Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { return input_buffer_; } +void BytecodeGraphBuilder::EnterAndExitExceptionHandlers(int current_offset) { + Handle<HandlerTable> table = exception_handler_table(); + int num_entries = table->NumberOfRangeEntries(); -void BytecodeGraphBuilder::PrepareEntryFrameState(Node* node) { - DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); - DCHECK_EQ(IrOpcode::kDead, - NodeProperties::GetFrameStateInput(node, 0)->opcode()); - NodeProperties::ReplaceFrameStateInput( - node, 0, environment()->Checkpoint(BailoutId(0), - OutputFrameStateCombine::Ignore())); -} + // Potentially exit exception handlers. + while (!exception_handlers_.empty()) { + int current_end = exception_handlers_.top().end_offset_; + if (current_offset < current_end) break; // Still covered by range. + exception_handlers_.pop(); + } + // Potentially enter exception handlers. + while (current_exception_handler_ < num_entries) { + int next_start = table->GetRangeStart(current_exception_handler_); + if (current_offset < next_start) break; // Not yet covered by range. + int next_end = table->GetRangeEnd(current_exception_handler_); + int next_handler = table->GetRangeHandler(current_exception_handler_); + int context_register = table->GetRangeData(current_exception_handler_); + CatchPrediction pred = + table->GetRangePrediction(current_exception_handler_); + exception_handlers_.push( + {next_start, next_end, next_handler, context_register, pred}); + current_exception_handler_++; + } +} Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count, Node** value_inputs, bool incomplete) { @@ -1907,6 +1620,7 @@ Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count, if (!has_context && frame_state_count == 0 && !has_control && !has_effect) { result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); } else { + bool inside_handler = !exception_handlers_.empty(); int input_count_with_deps = value_input_count; if (has_context) ++input_count_with_deps; input_count_with_deps += frame_state_count; @@ -1931,21 +1645,40 @@ Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count, *current_input++ = environment()->GetControlDependency(); } result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); - if (!environment()->IsMarkedAsUnreachable()) { - // Update the current control dependency for control-producing nodes. - if (NodeProperties::IsControl(result)) { - environment()->UpdateControlDependency(result); - } - // Update the current effect dependency for effect-producing nodes. - if (result->op()->EffectOutputCount() > 0) { - environment()->UpdateEffectDependency(result); - } - // Add implicit success continuation for throwing nodes. - if (!result->op()->HasProperty(Operator::kNoThrow)) { - const Operator* if_success = common()->IfSuccess(); - Node* on_success = graph()->NewNode(if_success, result); - environment_->UpdateControlDependency(on_success); - } + // Update the current control dependency for control-producing nodes. + if (NodeProperties::IsControl(result)) { + environment()->UpdateControlDependency(result); + } + // Update the current effect dependency for effect-producing nodes. + if (result->op()->EffectOutputCount() > 0) { + environment()->UpdateEffectDependency(result); + } + // Add implicit exception continuation for throwing nodes. + if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { + int handler_offset = exception_handlers_.top().handler_offset_; + int context_index = exception_handlers_.top().context_register_; + CatchPrediction prediction = exception_handlers_.top().pred_; + interpreter::Register context_register(context_index); + IfExceptionHint hint = prediction == CatchPrediction::CAUGHT + ? IfExceptionHint::kLocallyCaught + : IfExceptionHint::kLocallyUncaught; + Environment* success_env = environment()->CopyForConditional(); + const Operator* op = common()->IfException(hint); + Node* effect = environment()->GetEffectDependency(); + Node* on_exception = graph()->NewNode(op, effect, result); + Node* context = environment()->LookupRegister(context_register); + environment()->UpdateControlDependency(on_exception); + environment()->UpdateEffectDependency(on_exception); + environment()->BindAccumulator(on_exception); + environment()->SetContext(context); + MergeIntoSuccessorEnvironment(handler_offset); + set_environment(success_env); + } + // Add implicit success continuation for throwing nodes. + if (!result->op()->HasProperty(Operator::kNoThrow)) { + const Operator* if_success = common()->IfSuccess(); + Node* on_success = graph()->NewNode(if_success, result); + environment()->UpdateControlDependency(on_success); } } @@ -2028,13 +1761,6 @@ Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, return value; } - -void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { - if (environment()->IsMarkedAsUnreachable()) return; - environment()->MarkAsUnreachable(); - exit_controls_.push_back(exit); -} - } // namespace compiler } // namespace internal } // namespace v8 |