#ifndef V8_COMPILER_NODE_PROPERTIES_H_
#define V8_COMPILER_NODE_PROPERTIES_H_
#include "src/codegen/machine-type.h"
#include "src/common/globals.h"
#include "src/compiler/heap-refs.h"
#include "src/compiler/node.h"
#include "src/compiler/operator-properties.h"
#include "src/compiler/turbofan-types.h"
namespace v8 {
namespace internal {
namespace compiler {
class TFGraph;
class Operator;
class CommonOperatorBuilder;
class V8_EXPORT_PRIVATE NodeProperties {
public:
static int FirstValueIndex(const Node* node) { return 0; }
static int FirstContextIndex(Node* node) { return PastValueIndex(node); }
static int FirstFrameStateIndex(Node* node) { return PastContextIndex(node); }
static int FirstEffectIndex(Node* node) { return PastFrameStateIndex(node); }
static int FirstControlIndex(Node* node) { return PastEffectIndex(node); }
static int PastValueIndex(Node* node) {
return FirstValueIndex(node) + node->op()->ValueInputCount();
}
static int PastContextIndex(Node* node) {
return FirstContextIndex(node) +
OperatorProperties::GetContextInputCount(node->op());
}
static int PastFrameStateIndex(Node* node) {
return FirstFrameStateIndex(node) +
OperatorProperties::GetFrameStateInputCount(node->op());
}
static int PastEffectIndex(Node* node) {
return FirstEffectIndex(node) + node->op()->EffectInputCount();
}
static int PastControlIndex(Node* node) {
return FirstControlIndex(node) + node->op()->ControlInputCount();
}
static Node* GetValueInput(Node* node, int index) {
CHECK_LE(0, index);
CHECK_LT(index, node->op()->ValueInputCount());
return node->InputAt(FirstValueIndex(node) + index);
}
static const Node* GetValueInput(const Node* node, int index) {
CHECK_LE(0, index);
CHECK_LT(index, node->op()->ValueInputCount());
return node->InputAt(FirstValueIndex(node) + index);
}
static Node* GetContextInput(Node* node) {
CHECK(OperatorProperties::HasContextInput(node->op()));
return node->InputAt(FirstContextIndex(node));
}
static Node* GetFrameStateInput(Node* node) {
CHECK(OperatorProperties::HasFrameStateInput(node->op()));
return node->InputAt(FirstFrameStateIndex(node));
}
static Node* GetEffectInput(Node* node, int index = 0) {
CHECK_LE(0, index);
CHECK_LT(index, node->op()->EffectInputCount());
return node->InputAt(FirstEffectIndex(node) + index);
}
static Node* GetControlInput(Node* node, int index = 0) {
CHECK_LE(0, index);
CHECK_LT(index, node->op()->ControlInputCount());
return node->InputAt(FirstControlIndex(node) + index);
}
static bool IsValueEdge(Edge edge);
static bool IsContextEdge(Edge edge);
static bool IsFrameStateEdge(Edge edge);
static bool IsEffectEdge(Edge edge);
static bool IsControlEdge(Edge edge);
static bool IsCommon(Node* node) {
return IrOpcode::IsCommonOpcode(node->opcode());
}
static bool IsControl(Node* node) {
return IrOpcode::IsControlOpcode(node->opcode());
}
static bool IsConstant(Node* node) {
return IrOpcode::IsConstantOpcode(node->opcode());
}
static bool IsPhi(Node* node) {
return IrOpcode::IsPhiOpcode(node->opcode());
}
#if V8_ENABLE_WEBASSEMBLY
static bool IsSimd128Operation(Node* node) {
return IrOpcode::IsSimd128Opcode(node->opcode());
}
#endif
static bool IsExceptionalCall(Node* node, Node** out_exception = nullptr);
static Node* FindSuccessfulControlProjection(Node* node);
static bool IsValueIdentity(Node* node, Node** out_value) {
switch (node->opcode()) {
case IrOpcode::kTypeGuard:
*out_value = GetValueInput(node, 0);
return true;
default:
return false;
}
}
static void ReplaceValueInput(Node* node, Node* value, int index);
static void ReplaceContextInput(Node* node, Node* context);
static void ReplaceControlInput(Node* node, Node* control, int index = 0);
static void ReplaceEffectInput(Node* node, Node* effect, int index = 0);
static void ReplaceFrameStateInput(Node* node, Node* frame_state);
static void RemoveNonValueInputs(Node* node);
static void RemoveValueInputs(Node* node);
static void ReplaceValueInputs(Node* node, Node* value);
static void MergeControlToEnd(TFGraph* graph, CommonOperatorBuilder* common,
Node* node);
static void RemoveControlFromEnd(TFGraph* graph,
CommonOperatorBuilder* common, Node* node);
static void ReplaceUses(Node* node, Node* value, Node* effect = nullptr,
Node* success = nullptr, Node* exception = nullptr);
static void ChangeOp(Node* node, const Operator* new_op);
static void ChangeOpUnchecked(Node* node, const Operator* new_op);
static Node* FindFrameStateBefore(Node* node, Node* unreachable_sentinel);
static Node* FindProjection(Node* node, size_t projection_index);
static void CollectValueProjections(Node* node, Node** proj, size_t count);
static void CollectControlProjections(Node* node, Node** proj, size_t count);
static MachineRepresentation GetProjectionType(Node const* projection);
static bool IsSame(Node* a, Node* b);
static bool Equals(Node* a, Node* b);
static size_t HashCode(Node* node);
enum InferMapsResult {
kNoMaps,
kReliableMaps,
kUnreliableMaps
};
static InferMapsResult InferMapsUnsafe(JSHeapBroker* broker, Node* receiver,
Effect effect,
ZoneRefSet<Map>* maps_out);
static OptionalMapRef GetJSCreateMap(JSHeapBroker* broker, Node* receiver);
static bool NoObservableSideEffectBetween(Node* effect, Node* dominator);
static bool CanBePrimitive(JSHeapBroker* broker, Node* receiver,
Effect effect);
static bool CanBeNullOrUndefined(JSHeapBroker* broker, Node* receiver,
Effect effect);
static Node* GetOuterContext(Node* node, size_t* depth);
static bool IsTyped(const Node* node) { return !node->type().IsInvalid(); }
static Type GetType(const Node* node) {
DCHECK(IsTyped(node));
return node->type();
}
static Type GetTypeOrAny(const Node* node);
static void SetType(Node* node, Type type) {
DCHECK(!type.IsInvalid());
node->set_type(type);
}
static void RemoveType(Node* node) { node->set_type(Type::Invalid()); }
static bool AllValueInputsAreTyped(Node* node);
private:
static inline bool IsInputRange(Edge edge, int first, int count);
};
}
}
}
#endif