summaryrefslogtreecommitdiff
path: root/deps/v8/src/maglev/maglev-graph-builder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/maglev/maglev-graph-builder.cc')
-rw-r--r--deps/v8/src/maglev/maglev-graph-builder.cc616
1 files changed, 616 insertions, 0 deletions
diff --git a/deps/v8/src/maglev/maglev-graph-builder.cc b/deps/v8/src/maglev/maglev-graph-builder.cc
new file mode 100644
index 0000000000..b38bece1d5
--- /dev/null
+++ b/deps/v8/src/maglev/maglev-graph-builder.cc
@@ -0,0 +1,616 @@
+// Copyright 2022 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/maglev/maglev-graph-builder.h"
+
+#include "src/compiler/feedback-source.h"
+#include "src/compiler/heap-refs.h"
+#include "src/handles/maybe-handles-inl.h"
+#include "src/ic/handler-configuration.h"
+#include "src/objects/feedback-vector.h"
+#include "src/objects/name-inl.h"
+#include "src/objects/slots-inl.h"
+
+namespace v8 {
+namespace internal {
+
+namespace maglev {
+
+MaglevGraphBuilder::MaglevGraphBuilder(MaglevCompilationUnit* compilation_unit)
+ : compilation_unit_(compilation_unit),
+ iterator_(bytecode().object()),
+ jump_targets_(zone()->NewArray<BasicBlockRef>(bytecode().length())),
+ // Overallocate merge_states_ by one to allow always looking up the
+ // next offset.
+ merge_states_(zone()->NewArray<MergePointInterpreterFrameState*>(
+ bytecode().length() + 1)),
+ graph_(Graph::New(zone())),
+ current_interpreter_frame_(*compilation_unit_) {
+ memset(merge_states_, 0,
+ bytecode().length() * sizeof(InterpreterFrameState*));
+ // Default construct basic block refs.
+ // TODO(leszeks): This could be a memset of nullptr to ..._jump_targets_.
+ for (int i = 0; i < bytecode().length(); ++i) {
+ new (&jump_targets_[i]) BasicBlockRef();
+ }
+
+ CalculatePredecessorCounts();
+
+ for (auto& offset_and_info : bytecode_analysis().GetLoopInfos()) {
+ int offset = offset_and_info.first;
+ const compiler::LoopInfo& loop_info = offset_and_info.second;
+
+ const compiler::BytecodeLivenessState* liveness =
+ bytecode_analysis().GetInLivenessFor(offset);
+
+ merge_states_[offset] = zone()->New<MergePointInterpreterFrameState>(
+ *compilation_unit_, offset, NumPredecessors(offset), liveness,
+ &loop_info);
+ }
+
+ current_block_ = zone()->New<BasicBlock>(nullptr);
+ block_offset_ = -1;
+
+ for (int i = 0; i < parameter_count(); i++) {
+ interpreter::Register reg = interpreter::Register::FromParameterIndex(i);
+ current_interpreter_frame_.set(reg, AddNewNode<InitialValue>({}, reg));
+ }
+
+ // TODO(leszeks): Extract out a separate "incoming context/closure" nodes,
+ // to be able to read in the machine register but also use the frame-spilled
+ // slot.
+ interpreter::Register regs[] = {interpreter::Register::current_context(),
+ interpreter::Register::function_closure()};
+ for (interpreter::Register& reg : regs) {
+ current_interpreter_frame_.set(reg, AddNewNode<InitialValue>({}, reg));
+ }
+
+ interpreter::Register new_target_or_generator_register =
+ bytecode().incoming_new_target_or_generator_register();
+
+ const compiler::BytecodeLivenessState* liveness =
+ bytecode_analysis().GetInLivenessFor(0);
+ int register_index = 0;
+ // TODO(leszeks): Don't emit if not needed.
+ ValueNode* undefined_value =
+ AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue);
+ if (new_target_or_generator_register.is_valid()) {
+ int new_target_index = new_target_or_generator_register.index();
+ for (; register_index < new_target_index; register_index++) {
+ StoreRegister(interpreter::Register(register_index), undefined_value,
+ liveness);
+ }
+ StoreRegister(
+ new_target_or_generator_register,
+ // TODO(leszeks): Expose in Graph.
+ AddNewNode<RegisterInput>({}, kJavaScriptCallNewTargetRegister),
+ liveness);
+ register_index++;
+ }
+ for (; register_index < register_count(); register_index++) {
+ StoreRegister(interpreter::Register(register_index), undefined_value,
+ liveness);
+ }
+
+ BasicBlock* first_block = CreateBlock<Jump>({}, &jump_targets_[0]);
+ MergeIntoFrameState(first_block, 0);
+}
+
+// TODO(v8:7700): Clean up after all bytecodes are supported.
+#define MAGLEV_UNIMPLEMENTED(BytecodeName) \
+ do { \
+ std::cerr << "Maglev: Can't compile, bytecode " #BytecodeName \
+ " is not supported\n"; \
+ found_unsupported_bytecode_ = true; \
+ this_field_will_be_unused_once_all_bytecodes_are_supported_ = true; \
+ } while (false)
+
+#define MAGLEV_UNIMPLEMENTED_BYTECODE(Name) \
+ void MaglevGraphBuilder::Visit##Name() { MAGLEV_UNIMPLEMENTED(Name); }
+
+template <Operation kOperation, typename... Args>
+ValueNode* MaglevGraphBuilder::AddNewOperationNode(
+ std::initializer_list<ValueNode*> inputs, Args&&... args) {
+ switch (kOperation) {
+#define CASE(Name) \
+ case Operation::k##Name: \
+ return AddNewNode<Generic##Name>(inputs, std::forward<Args>(args)...);
+ OPERATION_LIST(CASE)
+#undef CASE
+ }
+}
+
+template <Operation kOperation>
+void MaglevGraphBuilder::BuildGenericUnaryOperationNode() {
+ FeedbackSlot slot_index = GetSlotOperand(0);
+ ValueNode* value = GetAccumulator();
+ ValueNode* node = AddNewOperationNode<kOperation>(
+ {value}, compiler::FeedbackSource{feedback(), slot_index});
+ SetAccumulator(node);
+ MarkPossibleSideEffect();
+}
+
+template <Operation kOperation>
+void MaglevGraphBuilder::BuildGenericBinaryOperationNode() {
+ ValueNode* left = LoadRegister(0);
+ FeedbackSlot slot_index = GetSlotOperand(1);
+ ValueNode* right = GetAccumulator();
+ ValueNode* node = AddNewOperationNode<kOperation>(
+ {left, right}, compiler::FeedbackSource{feedback(), slot_index});
+ SetAccumulator(node);
+ MarkPossibleSideEffect();
+}
+
+template <Operation kOperation>
+void MaglevGraphBuilder::VisitUnaryOperation() {
+ // TODO(victorgomes): Use feedback info and create optimized versions.
+ BuildGenericUnaryOperationNode<kOperation>();
+}
+
+template <Operation kOperation>
+void MaglevGraphBuilder::VisitBinaryOperation() {
+ // TODO(victorgomes): Use feedback info and create optimized versions.
+ BuildGenericBinaryOperationNode<kOperation>();
+}
+
+void MaglevGraphBuilder::VisitLdar() { SetAccumulator(LoadRegister(0)); }
+
+void MaglevGraphBuilder::VisitLdaZero() {
+ SetAccumulator(AddNewNode<SmiConstant>({}, Smi::zero()));
+}
+void MaglevGraphBuilder::VisitLdaSmi() {
+ Smi constant = Smi::FromInt(iterator_.GetImmediateOperand(0));
+ SetAccumulator(AddNewNode<SmiConstant>({}, constant));
+}
+void MaglevGraphBuilder::VisitLdaUndefined() {
+ SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kUndefinedValue));
+}
+void MaglevGraphBuilder::VisitLdaNull() {
+ SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kNullValue));
+}
+void MaglevGraphBuilder::VisitLdaTheHole() {
+ SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kTheHoleValue));
+}
+void MaglevGraphBuilder::VisitLdaTrue() {
+ SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kTrueValue));
+}
+void MaglevGraphBuilder::VisitLdaFalse() {
+ SetAccumulator(AddNewNode<RootConstant>({}, RootIndex::kFalseValue));
+}
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaConstant)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaContextSlot)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaImmutableContextSlot)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaCurrentContextSlot)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaImmutableCurrentContextSlot)
+void MaglevGraphBuilder::VisitStar() {
+ StoreRegister(
+ iterator_.GetRegisterOperand(0), GetAccumulator(),
+ bytecode_analysis().GetOutLivenessFor(iterator_.current_offset()));
+}
+void MaglevGraphBuilder::VisitMov() {
+ StoreRegister(
+ iterator_.GetRegisterOperand(1), LoadRegister(0),
+ bytecode_analysis().GetOutLivenessFor(iterator_.current_offset()));
+}
+MAGLEV_UNIMPLEMENTED_BYTECODE(PushContext)
+MAGLEV_UNIMPLEMENTED_BYTECODE(PopContext)
+MAGLEV_UNIMPLEMENTED_BYTECODE(TestReferenceEqual)
+MAGLEV_UNIMPLEMENTED_BYTECODE(TestUndetectable)
+MAGLEV_UNIMPLEMENTED_BYTECODE(TestNull)
+MAGLEV_UNIMPLEMENTED_BYTECODE(TestUndefined)
+MAGLEV_UNIMPLEMENTED_BYTECODE(TestTypeOf)
+void MaglevGraphBuilder::VisitLdaGlobal() {
+ // LdaGlobal <name_index> <slot>
+
+ static const int kNameOperandIndex = 0;
+ static const int kSlotOperandIndex = 1;
+
+ compiler::NameRef name = GetRefOperand<Name>(kNameOperandIndex);
+ FeedbackSlot slot_index = GetSlotOperand(kSlotOperandIndex);
+ ValueNode* context = GetContext();
+
+ USE(slot_index); // TODO(v8:7700): Use the feedback info.
+
+ SetAccumulator(AddNewNode<LoadGlobal>({context}, name));
+ MarkPossibleSideEffect();
+}
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaGlobalInsideTypeof)
+MAGLEV_UNIMPLEMENTED_BYTECODE(StaGlobal)
+MAGLEV_UNIMPLEMENTED_BYTECODE(StaContextSlot)
+MAGLEV_UNIMPLEMENTED_BYTECODE(StaCurrentContextSlot)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaLookupSlot)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaLookupContextSlot)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaLookupGlobalSlot)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaLookupSlotInsideTypeof)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaLookupContextSlotInsideTypeof)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaLookupGlobalSlotInsideTypeof)
+MAGLEV_UNIMPLEMENTED_BYTECODE(StaLookupSlot)
+void MaglevGraphBuilder::VisitGetNamedProperty() {
+ // GetNamedProperty <object> <name_index> <slot>
+ ValueNode* object = LoadRegister(0);
+ FeedbackNexus nexus = feedback_nexus(2);
+
+ if (nexus.ic_state() == InlineCacheState::UNINITIALIZED) {
+ EnsureCheckpoint();
+ AddNewNode<SoftDeopt>({});
+ } else if (nexus.ic_state() == InlineCacheState::MONOMORPHIC) {
+ std::vector<MapAndHandler> maps_and_handlers;
+ nexus.ExtractMapsAndHandlers(&maps_and_handlers);
+ DCHECK_EQ(maps_and_handlers.size(), 1);
+ MapAndHandler& map_and_handler = maps_and_handlers[0];
+ if (map_and_handler.second->IsSmi()) {
+ int handler = map_and_handler.second->ToSmi().value();
+ LoadHandler::Kind kind = LoadHandler::KindBits::decode(handler);
+ if (kind == LoadHandler::Kind::kField &&
+ !LoadHandler::IsWasmStructBits::decode(handler)) {
+ EnsureCheckpoint();
+ AddNewNode<CheckMaps>({object},
+ MakeRef(broker(), map_and_handler.first));
+ SetAccumulator(AddNewNode<LoadField>({object}, handler));
+ return;
+ }
+ }
+ }
+
+ ValueNode* context = GetContext();
+ compiler::NameRef name = GetRefOperand<Name>(1);
+ SetAccumulator(AddNewNode<LoadNamedGeneric>({context, object}, name));
+ MarkPossibleSideEffect();
+}
+
+MAGLEV_UNIMPLEMENTED_BYTECODE(GetNamedPropertyFromSuper)
+MAGLEV_UNIMPLEMENTED_BYTECODE(GetKeyedProperty)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LdaModuleVariable)
+MAGLEV_UNIMPLEMENTED_BYTECODE(StaModuleVariable)
+
+void MaglevGraphBuilder::VisitSetNamedProperty() {
+ // SetNamedProperty <object> <name_index> <slot>
+ ValueNode* object = LoadRegister(0);
+ FeedbackNexus nexus = feedback_nexus(2);
+
+ if (nexus.ic_state() == InlineCacheState::UNINITIALIZED) {
+ EnsureCheckpoint();
+ AddNewNode<SoftDeopt>({});
+ } else if (nexus.ic_state() == InlineCacheState::MONOMORPHIC) {
+ std::vector<MapAndHandler> maps_and_handlers;
+ nexus.ExtractMapsAndHandlers(&maps_and_handlers);
+ DCHECK_EQ(maps_and_handlers.size(), 1);
+ MapAndHandler& map_and_handler = maps_and_handlers[0];
+ if (map_and_handler.second->IsSmi()) {
+ int handler = map_and_handler.second->ToSmi().value();
+ StoreHandler::Kind kind = StoreHandler::KindBits::decode(handler);
+ if (kind == StoreHandler::Kind::kField) {
+ EnsureCheckpoint();
+ AddNewNode<CheckMaps>({object},
+ MakeRef(broker(), map_and_handler.first));
+ ValueNode* value = GetAccumulator();
+ AddNewNode<StoreField>({object, value}, handler);
+ return;
+ }
+ }
+ }
+
+ // TODO(victorgomes): Generic store.
+ MAGLEV_UNIMPLEMENTED(VisitSetNamedProperty);
+}
+
+MAGLEV_UNIMPLEMENTED_BYTECODE(DefineNamedOwnProperty)
+MAGLEV_UNIMPLEMENTED_BYTECODE(SetKeyedProperty)
+MAGLEV_UNIMPLEMENTED_BYTECODE(DefineKeyedOwnProperty)
+MAGLEV_UNIMPLEMENTED_BYTECODE(StaInArrayLiteral)
+MAGLEV_UNIMPLEMENTED_BYTECODE(DefineKeyedOwnPropertyInLiteral)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CollectTypeProfile)
+
+void MaglevGraphBuilder::VisitAdd() { VisitBinaryOperation<Operation::kAdd>(); }
+void MaglevGraphBuilder::VisitSub() {
+ VisitBinaryOperation<Operation::kSubtract>();
+}
+void MaglevGraphBuilder::VisitMul() {
+ VisitBinaryOperation<Operation::kMultiply>();
+}
+void MaglevGraphBuilder::VisitDiv() {
+ VisitBinaryOperation<Operation::kDivide>();
+}
+void MaglevGraphBuilder::VisitMod() {
+ VisitBinaryOperation<Operation::kModulus>();
+}
+void MaglevGraphBuilder::VisitExp() {
+ VisitBinaryOperation<Operation::kExponentiate>();
+}
+void MaglevGraphBuilder::VisitBitwiseOr() {
+ VisitBinaryOperation<Operation::kBitwiseOr>();
+}
+void MaglevGraphBuilder::VisitBitwiseXor() {
+ VisitBinaryOperation<Operation::kBitwiseXor>();
+}
+void MaglevGraphBuilder::VisitBitwiseAnd() {
+ VisitBinaryOperation<Operation::kBitwiseAnd>();
+}
+void MaglevGraphBuilder::VisitShiftLeft() {
+ VisitBinaryOperation<Operation::kShiftLeft>();
+}
+void MaglevGraphBuilder::VisitShiftRight() {
+ VisitBinaryOperation<Operation::kShiftRight>();
+}
+void MaglevGraphBuilder::VisitShiftRightLogical() {
+ VisitBinaryOperation<Operation::kShiftRightLogical>();
+}
+
+MAGLEV_UNIMPLEMENTED_BYTECODE(AddSmi)
+MAGLEV_UNIMPLEMENTED_BYTECODE(SubSmi)
+MAGLEV_UNIMPLEMENTED_BYTECODE(MulSmi)
+MAGLEV_UNIMPLEMENTED_BYTECODE(DivSmi)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ModSmi)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ExpSmi)
+MAGLEV_UNIMPLEMENTED_BYTECODE(BitwiseOrSmi)
+MAGLEV_UNIMPLEMENTED_BYTECODE(BitwiseXorSmi)
+MAGLEV_UNIMPLEMENTED_BYTECODE(BitwiseAndSmi)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ShiftLeftSmi)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ShiftRightSmi)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ShiftRightLogicalSmi)
+
+void MaglevGraphBuilder::VisitInc() {
+ VisitUnaryOperation<Operation::kIncrement>();
+}
+void MaglevGraphBuilder::VisitDec() {
+ VisitUnaryOperation<Operation::kDecrement>();
+}
+void MaglevGraphBuilder::VisitNegate() {
+ VisitUnaryOperation<Operation::kNegate>();
+}
+void MaglevGraphBuilder::VisitBitwiseNot() {
+ VisitUnaryOperation<Operation::kBitwiseNot>();
+}
+
+MAGLEV_UNIMPLEMENTED_BYTECODE(ToBooleanLogicalNot)
+MAGLEV_UNIMPLEMENTED_BYTECODE(LogicalNot)
+MAGLEV_UNIMPLEMENTED_BYTECODE(TypeOf)
+MAGLEV_UNIMPLEMENTED_BYTECODE(DeletePropertyStrict)
+MAGLEV_UNIMPLEMENTED_BYTECODE(DeletePropertySloppy)
+MAGLEV_UNIMPLEMENTED_BYTECODE(GetSuperConstructor)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CallAnyReceiver)
+
+// TODO(leszeks): For all of these:
+// a) Read feedback and implement inlining
+// b) Wrap in a helper.
+void MaglevGraphBuilder::VisitCallProperty() {
+ ValueNode* function = LoadRegister(0);
+
+ interpreter::RegisterList args = iterator_.GetRegisterListOperand(1);
+ ValueNode* context = GetContext();
+
+ static constexpr int kTheContext = 1;
+ CallProperty* call_property = AddNewNode<CallProperty>(
+ args.register_count() + kTheContext, function, context);
+ // TODO(leszeks): Move this for loop into the CallProperty constructor,
+ // pre-size the args array.
+ for (int i = 0; i < args.register_count(); ++i) {
+ call_property->set_arg(i, current_interpreter_frame_.get(args[i]));
+ }
+ SetAccumulator(call_property);
+ MarkPossibleSideEffect();
+}
+void MaglevGraphBuilder::VisitCallProperty0() {
+ ValueNode* function = LoadRegister(0);
+ ValueNode* context = GetContext();
+
+ CallProperty* call_property =
+ AddNewNode<CallProperty>({function, context, LoadRegister(1)});
+ SetAccumulator(call_property);
+ MarkPossibleSideEffect();
+}
+void MaglevGraphBuilder::VisitCallProperty1() {
+ ValueNode* function = LoadRegister(0);
+ ValueNode* context = GetContext();
+
+ CallProperty* call_property = AddNewNode<CallProperty>(
+ {function, context, LoadRegister(1), LoadRegister(2)});
+ SetAccumulator(call_property);
+ MarkPossibleSideEffect();
+}
+void MaglevGraphBuilder::VisitCallProperty2() {
+ ValueNode* function = LoadRegister(0);
+ ValueNode* context = GetContext();
+
+ CallProperty* call_property = AddNewNode<CallProperty>(
+ {function, context, LoadRegister(1), LoadRegister(2), LoadRegister(3)});
+ SetAccumulator(call_property);
+ MarkPossibleSideEffect();
+}
+MAGLEV_UNIMPLEMENTED_BYTECODE(CallUndefinedReceiver)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CallUndefinedReceiver0)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CallUndefinedReceiver1)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CallUndefinedReceiver2)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CallWithSpread)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CallRuntime)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CallRuntimeForPair)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CallJSRuntime)
+MAGLEV_UNIMPLEMENTED_BYTECODE(InvokeIntrinsic)
+MAGLEV_UNIMPLEMENTED_BYTECODE(Construct)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ConstructWithSpread)
+MAGLEV_UNIMPLEMENTED_BYTECODE(TestEqual)
+MAGLEV_UNIMPLEMENTED_BYTECODE(TestEqualStrict)
+
+void MaglevGraphBuilder::VisitTestLessThan() {
+ VisitBinaryOperation<Operation::kLessThan>();
+}
+void MaglevGraphBuilder::VisitTestLessThanOrEqual() {
+ VisitBinaryOperation<Operation::kLessThanOrEqual>();
+}
+void MaglevGraphBuilder::VisitTestGreaterThan() {
+ VisitBinaryOperation<Operation::kGreaterThan>();
+}
+void MaglevGraphBuilder::VisitTestGreaterThanOrEqual() {
+ VisitBinaryOperation<Operation::kGreaterThanOrEqual>();
+}
+
+MAGLEV_UNIMPLEMENTED_BYTECODE(TestInstanceOf)
+MAGLEV_UNIMPLEMENTED_BYTECODE(TestIn)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ToName)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ToNumber)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ToNumeric)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ToObject)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ToString)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateRegExpLiteral)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateArrayLiteral)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateArrayFromIterable)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateEmptyArrayLiteral)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateObjectLiteral)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateEmptyObjectLiteral)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CloneObject)
+MAGLEV_UNIMPLEMENTED_BYTECODE(GetTemplateObject)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateClosure)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateBlockContext)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateCatchContext)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateFunctionContext)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateEvalContext)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateWithContext)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateMappedArguments)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateUnmappedArguments)
+MAGLEV_UNIMPLEMENTED_BYTECODE(CreateRestParameter)
+
+void MaglevGraphBuilder::VisitJumpLoop() {
+ int target = iterator_.GetJumpTargetOffset();
+ BasicBlock* block =
+ target == iterator_.current_offset()
+ ? FinishBlock<JumpLoop>(next_offset(), {}, &jump_targets_[target])
+ : FinishBlock<JumpLoop>(next_offset(), {},
+ jump_targets_[target].block_ptr());
+
+ merge_states_[target]->MergeLoop(*compilation_unit_,
+ current_interpreter_frame_, block, target);
+ block->set_predecessor_id(0);
+}
+void MaglevGraphBuilder::VisitJump() {
+ BasicBlock* block = FinishBlock<Jump>(
+ next_offset(), {}, &jump_targets_[iterator_.GetJumpTargetOffset()]);
+ MergeIntoFrameState(block, iterator_.GetJumpTargetOffset());
+ DCHECK_LT(next_offset(), bytecode().length());
+}
+MAGLEV_UNIMPLEMENTED_BYTECODE(JumpConstant)
+void MaglevGraphBuilder::VisitJumpIfNullConstant() { VisitJumpIfNull(); }
+void MaglevGraphBuilder::VisitJumpIfNotNullConstant() { VisitJumpIfNotNull(); }
+void MaglevGraphBuilder::VisitJumpIfUndefinedConstant() {
+ VisitJumpIfUndefined();
+}
+void MaglevGraphBuilder::VisitJumpIfNotUndefinedConstant() {
+ VisitJumpIfNotUndefined();
+}
+void MaglevGraphBuilder::VisitJumpIfUndefinedOrNullConstant() {
+ VisitJumpIfUndefinedOrNull();
+}
+void MaglevGraphBuilder::VisitJumpIfTrueConstant() { VisitJumpIfTrue(); }
+void MaglevGraphBuilder::VisitJumpIfFalseConstant() { VisitJumpIfFalse(); }
+void MaglevGraphBuilder::VisitJumpIfJSReceiverConstant() {
+ VisitJumpIfJSReceiver();
+}
+void MaglevGraphBuilder::VisitJumpIfToBooleanTrueConstant() {
+ VisitJumpIfToBooleanTrue();
+}
+void MaglevGraphBuilder::VisitJumpIfToBooleanFalseConstant() {
+ VisitJumpIfToBooleanFalse();
+}
+
+void MaglevGraphBuilder::MergeIntoFrameState(BasicBlock* predecessor,
+ int target) {
+ if (merge_states_[target] == nullptr) {
+ DCHECK(!bytecode_analysis().IsLoopHeader(target));
+ const compiler::BytecodeLivenessState* liveness =
+ bytecode_analysis().GetInLivenessFor(target);
+ // If there's no target frame state, allocate a new one.
+ merge_states_[target] = zone()->New<MergePointInterpreterFrameState>(
+ *compilation_unit_, current_interpreter_frame_, target,
+ NumPredecessors(target), predecessor, liveness);
+ } else {
+ // If there already is a frame state, merge.
+ merge_states_[target]->Merge(*compilation_unit_, current_interpreter_frame_,
+ predecessor, target);
+ }
+}
+
+void MaglevGraphBuilder::BuildBranchIfTrue(ValueNode* node, int true_target,
+ int false_target) {
+ // TODO(verwaest): Materialize true/false in the respective environments.
+ if (GetOutLiveness()->AccumulatorIsLive()) SetAccumulator(node);
+ BasicBlock* block = FinishBlock<BranchIfTrue>(next_offset(), {node},
+ &jump_targets_[true_target],
+ &jump_targets_[false_target]);
+ MergeIntoFrameState(block, iterator_.GetJumpTargetOffset());
+}
+void MaglevGraphBuilder::BuildBranchIfToBooleanTrue(ValueNode* node,
+ int true_target,
+ int false_target) {
+ // TODO(verwaest): Materialize true/false in the respective environments.
+ if (GetOutLiveness()->AccumulatorIsLive()) SetAccumulator(node);
+ BasicBlock* block = FinishBlock<BranchIfToBooleanTrue>(
+ next_offset(), {node}, &jump_targets_[true_target],
+ &jump_targets_[false_target]);
+ MergeIntoFrameState(block, iterator_.GetJumpTargetOffset());
+}
+void MaglevGraphBuilder::VisitJumpIfToBooleanTrue() {
+ BuildBranchIfToBooleanTrue(GetAccumulator(), iterator_.GetJumpTargetOffset(),
+ next_offset());
+}
+void MaglevGraphBuilder::VisitJumpIfToBooleanFalse() {
+ BuildBranchIfToBooleanTrue(GetAccumulator(), next_offset(),
+ iterator_.GetJumpTargetOffset());
+}
+void MaglevGraphBuilder::VisitJumpIfTrue() {
+ BuildBranchIfTrue(GetAccumulator(), iterator_.GetJumpTargetOffset(),
+ next_offset());
+}
+void MaglevGraphBuilder::VisitJumpIfFalse() {
+ BuildBranchIfTrue(GetAccumulator(), next_offset(),
+ iterator_.GetJumpTargetOffset());
+}
+MAGLEV_UNIMPLEMENTED_BYTECODE(JumpIfNull)
+MAGLEV_UNIMPLEMENTED_BYTECODE(JumpIfNotNull)
+MAGLEV_UNIMPLEMENTED_BYTECODE(JumpIfUndefined)
+MAGLEV_UNIMPLEMENTED_BYTECODE(JumpIfNotUndefined)
+MAGLEV_UNIMPLEMENTED_BYTECODE(JumpIfUndefinedOrNull)
+MAGLEV_UNIMPLEMENTED_BYTECODE(JumpIfJSReceiver)
+MAGLEV_UNIMPLEMENTED_BYTECODE(SwitchOnSmiNoFeedback)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ForInEnumerate)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ForInPrepare)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ForInContinue)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ForInNext)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ForInStep)
+MAGLEV_UNIMPLEMENTED_BYTECODE(SetPendingMessage)
+MAGLEV_UNIMPLEMENTED_BYTECODE(Throw)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ReThrow)
+void MaglevGraphBuilder::VisitReturn() {
+ FinishBlock<Return>(next_offset(), {GetAccumulator()});
+}
+MAGLEV_UNIMPLEMENTED_BYTECODE(ThrowReferenceErrorIfHole)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ThrowSuperNotCalledIfHole)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ThrowSuperAlreadyCalledIfNotHole)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ThrowIfNotSuperConstructor)
+MAGLEV_UNIMPLEMENTED_BYTECODE(SwitchOnGeneratorState)
+MAGLEV_UNIMPLEMENTED_BYTECODE(SuspendGenerator)
+MAGLEV_UNIMPLEMENTED_BYTECODE(ResumeGenerator)
+MAGLEV_UNIMPLEMENTED_BYTECODE(GetIterator)
+MAGLEV_UNIMPLEMENTED_BYTECODE(Debugger)
+MAGLEV_UNIMPLEMENTED_BYTECODE(IncBlockCounter)
+MAGLEV_UNIMPLEMENTED_BYTECODE(Abort)
+#define SHORT_STAR_VISITOR(Name, ...) \
+ void MaglevGraphBuilder::Visit##Name() { \
+ StoreRegister( \
+ interpreter::Register::FromShortStar(interpreter::Bytecode::k##Name), \
+ GetAccumulator(), \
+ bytecode_analysis().GetOutLivenessFor(iterator_.current_offset())); \
+ }
+SHORT_STAR_BYTECODE_LIST(SHORT_STAR_VISITOR)
+#undef SHORT_STAR_VISITOR
+
+void MaglevGraphBuilder::VisitWide() { UNREACHABLE(); }
+void MaglevGraphBuilder::VisitExtraWide() { UNREACHABLE(); }
+#define DEBUG_BREAK(Name, ...) \
+ void MaglevGraphBuilder::Visit##Name() { UNREACHABLE(); }
+DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK)
+#undef DEBUG_BREAK
+void MaglevGraphBuilder::VisitIllegal() { UNREACHABLE(); }
+
+} // namespace maglev
+} // namespace internal
+} // namespace v8