23 analysis_result_(analysis_result),
24 object_id_cache_(zone),
25 node_cache_(
jsgraph->graph(), zone),
26 arguments_elements_(zone),
33 if (replacement->
opcode() == IrOpcode::kDead ||
35 RelaxEffectsAndControls(original);
36 return Replace(replacement);
40 if (replacement_type.
Is(original_type)) {
41 RelaxEffectsAndControls(original);
42 return Replace(replacement);
59 jsgraph()->common()->TypeGuard(original_type));
60 ReplaceWithValue(original, original, original, control);
77 DCHECK(node->opcode() != IrOpcode::kAllocate &&
78 node->opcode() != IrOpcode::kFinishRegion);
83 switch (node->opcode()) {
84 case IrOpcode::kAllocate:
85 case IrOpcode::kTypeGuard: {
88 RelaxEffectsAndControls(node);
92 case IrOpcode::kFinishRegion: {
94 if (effect->opcode() == IrOpcode::kBeginRegion) {
95 RelaxEffectsAndControls(effect);
96 RelaxEffectsAndControls(node);
100 case IrOpcode::kNewArgumentsElements:
107 if (node->op()->EffectInputCount() > 0) {
121 DCHECK_LE(vobject->
id(), std::numeric_limits<int>::max());
122 int id =
static_cast<int>(vobject->
id());
137 DCHECK_GE(node->op()->EffectInputCount(), 1);
138 for (
int i = 0;
i < node->InputCount(); ++
i) {
140 if (input->opcode() == IrOpcode::kFrameState) {
143 node->ReplaceInput(
i, ret);
151 if (node->opcode() == IrOpcode::kFrameState) {
166 return new_node.
Get();
167 }
else if (node->opcode() == IrOpcode::kStateValues) {
169 for (
int i = 0;
i < node->op()->ValueInputCount(); ++
i) {
174 return new_node.
Get();
177 if (vobject->HasEscaped())
return node;
181 std::vector<Node*> inputs;
186 if (field !=
jsgraph()->Dead()) {
190 int num_inputs =
static_cast<int>(inputs.size());
193 jsgraph()->common()->ObjectState(vobject->id(), num_inputs),
195 return new_node.
Get();
204 for (
Node* node : all.reachable) {
205 if (node->opcode() == IrOpcode::kAllocate) {
208 if (!vobject->HasEscaped()) {
209 FATAL(
"Escape analysis failed to remove node %s#%d\n",
210 node->op()->mnemonic(), node->id());
224 ? params.formal_parameter_count()
228 if (arguments_length->
opcode() != IrOpcode::kArgumentsLength)
continue;
230 Node* arguments_length_state =
nullptr;
232 Node* use = edge.from();
233 switch (use->opcode()) {
234 case IrOpcode::kObjectState:
235 case IrOpcode::kTypedObjectState:
236 case IrOpcode::kStateValues:
237 case IrOpcode::kTypedStateValues:
238 if (!arguments_length_state) {
240 jsgraph()->common()->ArgumentsLengthState());
242 Type::OtherInternal());
244 edge.UpdateTo(arguments_length_state);
251 bool escaping_use =
false;
253 for (
Edge edge : node->use_edges()) {
254 Node* use = edge.from();
256 if (use->use_edges().empty()) {
260 switch (use->opcode()) {
261 case IrOpcode::kStateValues:
262 case IrOpcode::kTypedStateValues:
263 case IrOpcode::kObjectState:
264 case IrOpcode::kTypedObjectState:
266 case IrOpcode::kLoadElement:
267 if (mapped_count == 0) {
273 case IrOpcode::kLoadField:
287 if (escaping_use)
break;
291 jsgraph()->common()->ArgumentsElementsState(type));
293 ReplaceWithValue(node, arguments_elements_state);
295 for (
Node* load : loads) {
296 switch (load->opcode()) {
297 case IrOpcode::kLoadElement: {
299 Node* formal_parameter_count =
302 formal_parameter_count,
309 offset_to_first_elem,
316 offset_to_first_elem);
317 Type offset_type = op_typer.NumberAdd(
326 formal_parameter_count);
328 offset, op_typer.NumberAdd(
333 jsgraph()->machine()->LoadFramePointer());
341 case IrOpcode::kLoadField: {
345 ReplaceWithValue(load, length);
357 auto it =
cache_.find(node);
366 const Operator* op,
int input_count,
368 : node_cache_(cache), from_(nullptr) {
370 tmp_ = node_cache_->temp_nodes_.back();
371 node_cache_->temp_nodes_.pop_back();
372 int tmp_input_count = tmp_->InputCount();
373 if (input_count <= tmp_input_count) {
374 tmp_->TrimInputCount(input_count);
376 for (
int i = 0;
i < input_count; ++
i) {
377 if (
i < tmp_input_count) {
385 tmp_ = node_cache_->graph_->NewNode(op, input_count, inputs);
395 if (!node) node =
from_;
412 if (node_cache_->temp_nodes_.empty()) {
413 tmp_ = node_cache_->graph_->CloneNode(from_);
415 tmp_ = node_cache_->temp_nodes_.back();
416 node_cache_->temp_nodes_.pop_back();
417 int from_input_count = from_->InputCount();
418 int tmp_input_count = tmp_->InputCount();
419 if (from_input_count <= tmp_input_count) {
420 tmp_->TrimInputCount(from_input_count);
422 for (
int i = 0;
i < from_input_count; ++
i) {
423 if (
i < tmp_input_count) {
424 tmp_->ReplaceInput(
i, from_->InputAt(
i));
426 tmp_->AppendInput(node_cache_->graph_->zone(), from_->InputAt(
i));
SimplifiedOperatorBuilder * simplified
bool Contains(int i) const
void Resize(int new_length, Zone *zone)
static constexpr int kFixedSlotCountAboveFp
void resize(size_t new_size)
void push_back(const T &value)
bool SeenBefore(const VirtualObject *vobject)
Reduction ReplaceNode(Node *original, Node *replacement)
ZoneSet< Node * > arguments_elements_
Node * ReduceDeoptState(Node *node, Node *effect, Deduplicator *deduplicator)
Reduction Reduce(Node *node) override
EscapeAnalysisResult analysis_result() const
void ReduceFrameStateInputs(Node *node)
JSHeapBroker *const broker_
void VerifyReplacement() const
EscapeAnalysisReducer(Editor *editor, JSGraph *jsgraph, JSHeapBroker *broker, EscapeAnalysisResult analysis_result, Zone *zone)
ZoneVector< Node * > object_id_cache_
Node * ObjectIdNode(const VirtualObject *vobject)
NodeHashCache node_cache_
JSGraph * jsgraph() const
Node * GetVirtualObjectField(const VirtualObject *vobject, int field, Node *effect)
const VirtualObject * GetVirtualObject(Node *node)
static constexpr int kFrameStateLocalsInput
static constexpr int kFrameStateContextInput
static constexpr int kFrameStateParametersInput
static constexpr int kFrameStateFunctionInput
static constexpr int kFrameStateOuterStateInput
static constexpr int kFrameStateStackInput
Node * ConstantNoHole(ObjectRef ref, JSHeapBroker *broker)
NodeHashCache * node_cache_
Constructor(NodeHashCache *cache, Node *from)
void ReplaceValueInput(Node *input, int i)
void ReplaceInput(Node *input, int i)
ZoneVector< Node * > temp_nodes_
ZoneUnorderedSet< Node *, NodeHashCode, NodeEquals > cache_
static void ChangeOp(Node *node, const Operator *new_op)
static Type GetType(const Node *node)
static bool IsTyped(const Node *node)
static Node * GetEffectInput(Node *node, int index=0)
static bool IsValueEdge(Edge edge)
static Node * GetValueInput(Node *node, int index)
static void SetType(Node *node, Type type)
static void ReplaceValueInput(Node *node, Node *value, int index)
static Node * GetControlInput(Node *node, int index=0)
constexpr IrOpcode::Value opcode() const
void TrimInputCount(int new_input_count)
const Operator * op() const
void ReplaceInput(int index, Node *new_to)
Node * InputAt(int index) const
void AppendInput(Zone *zone, Node *new_to)
Node * NewNode(const Operator *op, int input_count, Node *const *inputs, bool incomplete=false)
static Type Constant(JSHeapBroker *broker, Handle< i::Object > value, Zone *zone)
static Type Intersect(Type type1, Type type2, Zone *zone)
JSHeapBroker *const broker_
const NewArgumentsElementsParameters & NewArgumentsElementsParametersOf(const Operator *op)
const FieldAccess & FieldAccessOf(const Operator *op)
Node * SkipValueIdentities(Node *node)
constexpr int kTaggedSize
#define DCHECK_LE(v1, v2)
#define CHECK_NOT_NULL(val)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)