14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_COMPILER_ESCAPE_ANALYSIS_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_COMPILER_ESCAPE_ANALYSIS_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/compiler/combined_pass_visitor.h"
204514f5e3Sopenharmony_ci#include "ecmascript/compiler/gate_accessor.h"
214514f5e3Sopenharmony_ci#include "ecmascript/mem/chunk_containers.h"
224514f5e3Sopenharmony_ci
234514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
244514f5e3Sopenharmony_ci
254514f5e3Sopenharmony_ciclass EscapeAnalysis;
264514f5e3Sopenharmony_ciclass FieldLocation;
274514f5e3Sopenharmony_ci
284514f5e3Sopenharmony_ciclass VirtualObject {
294514f5e3Sopenharmony_cipublic:
304514f5e3Sopenharmony_ci    VirtualObject(size_t numIn, Chunk* chunk);
314514f5e3Sopenharmony_ci    void SetEscaped();
324514f5e3Sopenharmony_ci    bool IsEscaped() const;
334514f5e3Sopenharmony_ci    ChunkVector<GateRef>& GetUsers();
344514f5e3Sopenharmony_ci    void ClearUsers();
354514f5e3Sopenharmony_ci    void AddUser(GateRef gate);
364514f5e3Sopenharmony_ci    FieldLocation GetField(size_t offset);
374514f5e3Sopenharmony_ciprivate:
384514f5e3Sopenharmony_ci    ChunkVector<FieldLocation> fields_;
394514f5e3Sopenharmony_ci    // Gates which use this virtual object
404514f5e3Sopenharmony_ci    ChunkVector<GateRef> users_;
414514f5e3Sopenharmony_ci    bool escaped_ {false};
424514f5e3Sopenharmony_ci};
434514f5e3Sopenharmony_ci
444514f5e3Sopenharmony_ciclass FieldLocation {
454514f5e3Sopenharmony_cipublic:
464514f5e3Sopenharmony_ci    FieldLocation() : id_(maxid++) {}
474514f5e3Sopenharmony_ci    FieldLocation(size_t id) : id_(id) {}
484514f5e3Sopenharmony_ci    bool operator == (const FieldLocation &v) const
494514f5e3Sopenharmony_ci    {
504514f5e3Sopenharmony_ci        return id_ == v.id_;
514514f5e3Sopenharmony_ci    }
524514f5e3Sopenharmony_ci    bool operator != (const FieldLocation &v) const
534514f5e3Sopenharmony_ci    {
544514f5e3Sopenharmony_ci        return id_ != v.id_;
554514f5e3Sopenharmony_ci    }
564514f5e3Sopenharmony_ci    bool operator < (const FieldLocation &v) const
574514f5e3Sopenharmony_ci    {
584514f5e3Sopenharmony_ci        return id_ < v.id_;
594514f5e3Sopenharmony_ci    }
604514f5e3Sopenharmony_ci    static constexpr size_t invalid = -1;
614514f5e3Sopenharmony_ci    static FieldLocation Invalid()
624514f5e3Sopenharmony_ci    {
634514f5e3Sopenharmony_ci        return FieldLocation(invalid);
644514f5e3Sopenharmony_ci    }
654514f5e3Sopenharmony_ciprivate:
664514f5e3Sopenharmony_ci    static size_t maxid;
674514f5e3Sopenharmony_ci    size_t id_;
684514f5e3Sopenharmony_ci};
694514f5e3Sopenharmony_ci
704514f5e3Sopenharmony_ciclass State {
714514f5e3Sopenharmony_cipublic:
724514f5e3Sopenharmony_ci    explicit State(Chunk* chunk) : map_(chunk) {}
734514f5e3Sopenharmony_ci    void SetFieldValue(FieldLocation field, GateRef gate);
744514f5e3Sopenharmony_ci    GateRef GetFieldValue(FieldLocation field) const;
754514f5e3Sopenharmony_ci    bool IsMapEqual(const State &state) const;
764514f5e3Sopenharmony_ci    auto begin() const { return map_.begin(); }
774514f5e3Sopenharmony_ci    auto end() const { return map_.end(); }
784514f5e3Sopenharmony_ciprivate:
794514f5e3Sopenharmony_ci    ChunkMap<FieldLocation, GateRef> map_;
804514f5e3Sopenharmony_ci};
814514f5e3Sopenharmony_ci
824514f5e3Sopenharmony_ci// When we visit a gate, we first create a GateInfo which maintains results and all information
834514f5e3Sopenharmony_ci// that may be used in this visit. After finishing this visit, virtual object and replacement
844514f5e3Sopenharmony_ci// of this gate must be reset.
854514f5e3Sopenharmony_ciclass GateInfo {
864514f5e3Sopenharmony_cipublic:
874514f5e3Sopenharmony_ci    GateInfo(Circuit* circuit, GateRef curGate, EscapeAnalysis* escapeAnalysis, Chunk* chunk);
884514f5e3Sopenharmony_ci    ~GateInfo();
894514f5e3Sopenharmony_ci    GateRef GetCurrentGate() const;
904514f5e3Sopenharmony_ci    GateRef GetFieldValue(FieldLocation field) const;
914514f5e3Sopenharmony_ci    void SetFieldValue(FieldLocation field, GateRef value);
924514f5e3Sopenharmony_ci    void SetEliminated();
934514f5e3Sopenharmony_ci    void SetVirtualObject(VirtualObject* object);
944514f5e3Sopenharmony_ci    State MergeState(GateRef gate);
954514f5e3Sopenharmony_ci    void SetReplacement(GateRef replacement);
964514f5e3Sopenharmony_ciprivate:
974514f5e3Sopenharmony_ci    Circuit* circuit_;
984514f5e3Sopenharmony_ci    GateAccessor acc_;
994514f5e3Sopenharmony_ci    GateRef curGate_;
1004514f5e3Sopenharmony_ci    EscapeAnalysis* escapeAnalysis_;
1014514f5e3Sopenharmony_ci    State state_;
1024514f5e3Sopenharmony_ci    VirtualObject* object_ {nullptr};
1034514f5e3Sopenharmony_ci    GateRef replacement_ {Circuit::NullGate()};
1044514f5e3Sopenharmony_ci};
1054514f5e3Sopenharmony_ci
1064514f5e3Sopenharmony_ciclass EscapeAnalysis : public PassVisitor {
1074514f5e3Sopenharmony_cipublic:
1084514f5e3Sopenharmony_ci    EscapeAnalysis(Circuit* circuit, RPOVisitor* visitor, Chunk* chunk, bool isTraced)
1094514f5e3Sopenharmony_ci        : PassVisitor(circuit, chunk, visitor), circuit_(circuit), replacements_(chunk), gateToVirtualObject_(chunk),
1104514f5e3Sopenharmony_ci          gateToState_(chunk), chunk_(chunk), isTraced_(isTraced) {}
1114514f5e3Sopenharmony_ci
1124514f5e3Sopenharmony_ci    GateRef VisitGate(GateRef gate) override;
1134514f5e3Sopenharmony_ci    void SetEscaped(GateRef gate);
1144514f5e3Sopenharmony_ci    GateRef GetCurrentGate(GateRef gate) const;
1154514f5e3Sopenharmony_ci    void RevisitUser(VirtualObject* vObj);
1164514f5e3Sopenharmony_ci    GateRef TryGetReplacement(GateRef gate) const;
1174514f5e3Sopenharmony_ci    void SetReplacement(GateRef gate, GateRef replacement);
1184514f5e3Sopenharmony_ci    VirtualObject* TryGetVirtualObject(GateRef gate) const;
1194514f5e3Sopenharmony_ci    VirtualObject* TryGetVirtualObjectAndAddUser(GateRef gate, GateRef currentGate);
1204514f5e3Sopenharmony_ci    void SetVirtualObject(GateRef gate, VirtualObject* object);
1214514f5e3Sopenharmony_ci    VirtualObject* GetOrCreateVirtualObject(size_t numIn, GateInfo* info);
1224514f5e3Sopenharmony_ci    State& GetOrCreateState(GateRef gate);
1234514f5e3Sopenharmony_ci    void SetState(GateRef gate, State state);
1244514f5e3Sopenharmony_ci    void RevisitGate(GateRef gate);
1254514f5e3Sopenharmony_ci    void SetReplaceGate(GateRef gate);
1264514f5e3Sopenharmony_ciprivate:
1274514f5e3Sopenharmony_ci    GateRef VisitCreateObjectWithBuffer(GateRef gate, GateInfo* info);
1284514f5e3Sopenharmony_ci    GateRef VisitLoadProperty(GateRef gate, GateInfo* info);
1294514f5e3Sopenharmony_ci    GateRef VisitLoadConstOffset(GateRef gate, GateInfo* info);
1304514f5e3Sopenharmony_ci    GateRef VisitStoreProperty(GateRef gate, GateInfo* info);
1314514f5e3Sopenharmony_ci    GateRef VisitObjectTypeCheck(GateRef gate, GateInfo* info);
1324514f5e3Sopenharmony_ci
1334514f5e3Sopenharmony_ci    Circuit *circuit_ {nullptr};
1344514f5e3Sopenharmony_ci    ChunkMap<GateRef, GateRef> replacements_;
1354514f5e3Sopenharmony_ci    ChunkMap<GateRef, VirtualObject*> gateToVirtualObject_;
1364514f5e3Sopenharmony_ci    ChunkMap<GateRef, State> gateToState_;
1374514f5e3Sopenharmony_ci    GateRef replaceGate_ {Circuit::NullGate()};
1384514f5e3Sopenharmony_ci    Chunk* chunk_;
1394514f5e3Sopenharmony_ci    bool isTraced_;
1404514f5e3Sopenharmony_ci};
1414514f5e3Sopenharmony_ci
1424514f5e3Sopenharmony_ci};
1434514f5e3Sopenharmony_ci
1444514f5e3Sopenharmony_ci#endif